如何在实例化完整列表之前暂停ECLiPSe CLP?

时间:2018-05-28 10:15:49

标签: prolog constraint-programming eclipse-clp

ECLiPSe CLP具有内置谓词暂停(+目标,+ Prio,+ CondList),其中CondList通常具有X - >的形式。研究所。但是如何在实例化整个列表之前暂停?如果你做List - > inst,它将从一个元素实例化的那一刻起成功。旁注:列表没有固定的大小。

1 个答案:

答案 0 :(得分:3)

suspend/3原语只能将目标连接到暂停时已存在的变量。但是当列表以递增方式(从前到后)构建时,现有列表的" tail" -variable将被实例化,并且扩展列表现在具有新的"尾部" - 变量。这会导致您看到的行为,即在创建第一个列表元素后立即唤醒目标:

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