ECLiPSe CLP 有一个内置谓词 suspend(+Goal, +Prio, +CondList),其中 CondList 通常采用 X -> inst 的形式。但是如何在整个列表实例化之前暂停呢?如果您执行 List -> inst,它将从实例化一个元素的那一刻起成功。旁注:列表没有固定大小。
问问题
128 次
1 回答
3
suspend/3原语只能将目标连接到挂起时已经存在的变量。但是,当一个列表逐渐建立(从前到后)时,现有列表的“尾”变量会被实例化,扩展列表现在有一个新的“尾”变量。这会导致您看到的行为,即在创建第一个列表元素后立即唤醒目标:
?- suspend(writeln(now:Xs), 0, Xs->inst), length(Xs, 5).
now : [_510|_511]
Xs = [_510, _520, _522, _524, _526]
Yes (0.00s cpu)
如果要等待列表完成,请使用以下方案,每次遇到未实例化的列表尾时都重新挂起:
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).
其行为如所愿
?- write_complete_list(Xs), length(Xs, 5).
now : [_514, _542, _570, _598, _626]
Xs = [_514, _542, _570, _598, _626]
Yes (0.00s cpu)
或者,如果您使用的是最新版本的 ECLiPSe,您可以使用eval_to_complete_list/2。在此示例中,它将在完成后将增量构造的列表传播Ys
到辅助变量,这反过来又触发了暂停的目标Xs
:Ys
?- 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)
于 2018-05-29T13:10:35.530 回答