I’ve found a weird issue adapting the code in library/pure_input.pl to add some generality:
:- meta_predicate(lazy_list(2, -)).
lazy_list(Generator, List) :-
put_attr(List, lazy, lazy(Generator, _)).
lazy:attr_unify_hook(State, Value) :-
State = lazy(Generator, Next),
(var(Next) ->
call(Generator, List, Tail),
(var(Tail) ->
lazy_list(Generator, Tail),
nb_linkarg(2, State, List)
;
nb_setarg(2, State, List)
),
Value = List
;
Value = Next
).
n(Count, End, N, Next, List, Tail) :-
(Count = 0 ->
List = Tail,
Next = N
;
(N = End ->
Tail = [],
List = [],
Next = N
;
List = [N|List1],
N1 is N + 1,
Count1 is Count - 1,
n(Count1, End, N1, Next, List1, Tail)
)
).
n(Count, End, List, Tail) :-
nb_getval(next, Next),
n(Count, End, Next, Next1, List, Tail),
nb_setval(next, Next1).
w([]) :-
!.
w([H|T]) :-
write(H),
write(' '),
w(T).
test :-
nb_setval(next, 0),
lazy_list(n(10, 100), List),
(
List = [0,1,2,3,4,5,6,7,8,9|List1],
writeln(List),
(List1 = [a] ->
true
;
true
),
writeln(List),
(
List1 = [10,11,12,13,14,15,16,17,18,19,20|_],
writeln(List),
false
->
true
;
true
),
writeln(List),
List1 = [10|_],
writeln(List)
),
writeln(List),
w(List).
Some basic tests seems to work as expected also for backtracking case (where the strategy to avoid copying is a bit of black magic under the assumption that pure_input does things in the right way):
Welcome to SWI-Prolog (threaded, 64 bits, version 8.5.1)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- [q].
true.
?- test.
[0,1,2,3,4,5,6,7,8,9|_15590]
[0,1,2,3,4,5,6,7,8,9|_15590]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29|_15920]
[0,1,2,3,4,5,6,7,8,9|_15590]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19|_15712]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19|_15712]
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
true.
The weird thing is that I get different (wrong) results in debug mode:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.5.1)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- [q].
true.
?- debug.
true.
[debug] ?- test.
[0,1,2,3,4,5,6,7,8,9|_19026]
[0,1,2,3,4,5,6,7,8,9|_19026]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20|_19384]
[0,1,2,3,4,5,6,7,8,9|_19026]
[0,1,2,3,4,5,6,7,8,9,10|_19082]
[0,1,2,3,4,5,6,7,8,9,10|_19082]
0 1 2 3 4 5 6 7 8 9 10
true.
I believe this is definitely unexpected, am I missing something?