ECLiPSe CLP has a built-in predicate suspend(+Goal, +Prio, +CondList) whereby CondList often is of the form X -> inst. But how can you suspend until a whole list is instantiated? If you do List -> inst, it will succeed from the moment one element is instantiated. Sidenote: the list does not have a fixed size.
The suspend/3 primitive can only connect a goal to variables that already exist at suspend-time. But when a list is built up incrementally (from front to back), the "tail"-variable of the existing list becomes instantiated, and the extended list now has a new "tail"-variable. This leads to the behaviour you see, where the goal is woken immediately after the first list element has been created:
?- suspend(writeln(now:Xs), 0, Xs->inst), length(Xs, 5).
now : [_510|_511]
Xs = [_510, _520, _522, _524, _526]
Yes (0.00s cpu)
If you want to wait for the list to be complete, use the following scheme, where you re-suspend every time you encounter an uninstantiated list tail:
write_complete_list(Xs) :-
write_complete_list(Xs, Xs).
write_complete_list(Xs, Ts) :- var(Ts), !,
suspend(write_complete_list(Xs,Ts), 0, Ts->inst).
write_complete_list(Xs, [_|Ts]) :-
write_complete_list(Xs, Ts).
write_complete_list(Xs, []) :- % Xs is now a complete list
writeln(now:Xs).
which behaves as desired
?- write_complete_list(Xs), length(Xs, 5).
now : [_514, _542, _570, _598, _626]
Xs = [_514, _542, _570, _598, _626]
Yes (0.00s cpu)
Alternatively, if you are using the latest release of ECLiPSe, you could employ eval_to_complete_list/2 . In this example, it will propagate the incrementally constructed list Ys
to the auxiliary variable Xs
as soon as Ys
is complete, which in turn triggers the suspended goal:
?- suspend(writeln(now:Xs), 0, Xs->inst), eval_to_complete_list(Ys, Xs), length(Ys, 5).
now : [_597, _626, _655, _684, _713]
Xs = [_597, _626, _655, _684, _713]
Ys = [_597, _626, _655, _684, _713]
Yes (0.00s cpu)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.