首页 > 解决方案 > 如何在 ECLiPSe CLP 中暂停直到完整列表被实例化?

问题描述

ECLiPSe CLP 有一个内置谓词 suspend(+Goal, +Prio, +CondList),其中 CondList 通常采用 X -> inst 的形式。但是如何在整个列表实例化之前暂停呢?如果您执行 List -> inst,它将从实例化一个元素的那一刻起成功。旁注:列表没有固定大小。

标签: prologconstraint-programmingeclipse-clp

解决方案


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到辅助变量,这反过来又触发了暂停的目标XsYs

?- 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)

推荐阅读