:- module(lazy, [ lazy_unfold/5 , lazy_unfold/4 , lazy_unfold_finite/4 , lazy_seqmap/5 , lazy_seqmap/4 , lazy_maplist/2 , lazy_maplist/3 , lazy_maplist/4 , lazy_repeat/2 , lazy/4 ]). :- meta_predicate lazy_seqmap(4,?,?,?,?) , lazy_seqmap(3,?,?,?) , lazy_unfold(4,?,?,?,?) , lazy_unfold(3,?,?,?) , lazy_unfold_finite(3,?,?,?) , lazy_maplist(1,?) , lazy_maplist(2,?,?) , lazy_maplist(3,?,?,?) , lazy(3,?,?,-) . %% lazy(+P:pred(+A,+B,-C), X:A, Y:B, -Z:C) is det % Lazy version of call/4, triggered when Z is needed. Goal % expansion version allows macro expansion of call(P, ...). lazy(P,X,Y,Z) :- freeze(Z,call(P,X,Y,Z)). user:goal_expansion(lazy(P,X,Y,Z), freeze(Z,call(P,X,Y,Z))). %% lazy_unfold( +P:pred(-A1,-A2,+S,-S), -XX1:list(A1), -XX2:list(A2), +S1:S, -S2:S) is det. %% lazy_unfold( +P:pred(-A1,+S,-S), -XX1:list(A1), +S1:S, -S2:S) is det. % % Lazily unfold an infinite stream lazy_unfold(P,[X1|XX],[Y1|YY],S1,S3) :- call(P,X1,Y1,S1,S2), freeze(YY,lazy:lazy_unfold(P,XX,YY,S2,S3)). lazy_unfold(P,[X1|XX],S1,S3) :- call(P,X1,S1,S2), freeze(XX,lazy:lazy_unfold(P,XX,S2,S3)). %% lazy_unfold_finite( +P:pred(-A1,+S,-S), -XX1:list(A1), +S1:S, -S2:S) is det. % Lazily unfold a finite list or infinite stream. If unfolding predicate fails, % then a finite list is produced. lazy_unfold_finite(P,Xs,S1,S3) :- ( call(P,X1,S1,S2) -> Xs=[X1|XX], freeze(XX,lazy:lazy_unfold_finite(P,XX,S2,S3)) ; Xs=[] ). %% lazy_seqmap( +P:pred(A1,A2,S,S), +XX1:list(A1), -XX2:list(A2), S1:S, S2:S) is det. %% lazy_seqmap( +P:pred(A1,A2,S,S), -XX1:list(A1), -XX2:list(A2), S1:S, S2:S) is nondet. %% lazy_seqmap( +P:pred(A1,S,S), -XX1:list(A1), S1:S, S2:S) is nondet. % % Lazy versions of dcg_core:seqmap//{2,3} - can succeed for any lenght of list. % Computation is frozen on last list, which is to be understood as an 'output'. lazy_seqmap(_,[],[],S,S). lazy_seqmap(P,[X1|XX],[Y1|YY],S1,S3) :- call(P,X1,Y1,S1,S2), freeze(YY,lazy:lazy_seqmap(P,XX,YY,S2,S3)). lazy_seqmap(_,[],S,S). lazy_seqmap(P,[X1|XX],S1,S3) :- call(P,X1,S1,S2), freeze(XX,lazy:lazy_seqmap(P,XX,S2,S3)). lazy_maplist(P,[X|XX]) :- call(P,X), freeze(XX,lazy:lazy_maplist(P,XX)). lazy_maplist(_,[]). lazy_maplist(P,[X|XX],[Y|YY]) :- call(P,X,Y), freeze(YY,lazy:lazy_maplist(P,XX,YY)). lazy_maplist(_,[],[]). lazy_maplist(P,[X|XX],[Y|YY],[Z|ZZ]) :- call(P,X,Y,Z), freeze(ZZ,lazy:lazy_maplist(P,XX,YY,ZZ)). lazy_maplist(_,[],[],[]). lazy_repeat(X,[X|L]) :- freeze(L,lazy:lazy_repeat(X,L)).