1:- module(lazy,
    2	[	lazy_unfold/5
    3	,	lazy_unfold/4
    4   ,  lazy_unfold_finite/4
    5	,	lazy_seqmap/5
    6	,	lazy_seqmap/4
    7   ,  lazy_maplist/2
    8   ,  lazy_maplist/3
    9   ,  lazy_maplist/4
   10   ,  lazy_repeat/2
   11   ,  lazy/4
   12	]).   13
   14:- meta_predicate
   15		lazy_seqmap(4,?,?,?,?)
   16   ,	lazy_seqmap(3,?,?,?)
   17	,	lazy_unfold(4,?,?,?,?)
   18	,	lazy_unfold(3,?,?,?)
   19   ,  lazy_unfold_finite(3,?,?,?)
   20   ,	lazy_maplist(1,?)
   21   ,	lazy_maplist(2,?,?)
   22   ,	lazy_maplist(3,?,?,?)
   23   ,  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, ...).
   29lazy(P,X,Y,Z) :- freeze(Z,call(P,X,Y,Z)).
   30user: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
   36lazy_unfold(P,[X1|XX],[Y1|YY],S1,S3) :-
   37	call(P,X1,Y1,S1,S2),
   38	freeze(YY,lazy:lazy_unfold(P,XX,YY,S2,S3)).
   39
   40lazy_unfold(P,[X1|XX],S1,S3) :-
   41	call(P,X1,S1,S2),
   42	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.
   47lazy_unfold_finite(P,Xs,S1,S3) :-
   48   (  call(P,X1,S1,S2)
   49   -> Xs=[X1|XX], freeze(XX,lazy:lazy_unfold_finite(P,XX,S2,S3))
   50   ;  Xs=[]
   51   ).
 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'.
   59lazy_seqmap(_,[],[],S,S).
   60lazy_seqmap(P,[X1|XX],[Y1|YY],S1,S3) :-
   61	call(P,X1,Y1,S1,S2),
   62	freeze(YY,lazy:lazy_seqmap(P,XX,YY,S2,S3)).
   63
   64lazy_seqmap(_,[],S,S).
   65lazy_seqmap(P,[X1|XX],S1,S3) :-
   66	call(P,X1,S1,S2),
   67	freeze(XX,lazy:lazy_seqmap(P,XX,S2,S3)).
   68
   69lazy_maplist(P,[X|XX]) :- call(P,X), freeze(XX,lazy:lazy_maplist(P,XX)).
   70lazy_maplist(_,[]).
   71
   72lazy_maplist(P,[X|XX],[Y|YY]) :- call(P,X,Y), freeze(YY,lazy:lazy_maplist(P,XX,YY)).
   73lazy_maplist(_,[],[]).
   74
   75lazy_maplist(P,[X|XX],[Y|YY],[Z|ZZ]) :- call(P,X,Y,Z), freeze(ZZ,lazy:lazy_maplist(P,XX,YY,ZZ)).
   76lazy_maplist(_,[],[],[]).
   77
   78lazy_repeat(X,[X|L]) :- freeze(L,lazy:lazy_repeat(X,L))