
[英]How to generate lists of fresh variables in Mercury like I can in Prolog?
[英]In Mercury, why can't I use a state variable in a function application?
在描述状态变量时,Mercury 参考手册说:“ !X
可能不会在函数应用程序中作为参数出现,因为考虑到状态变量和函数的通常解释,这是没有道理的”(第14页)。 我想更好地理解这种推理:关于状态变量和函数的什么使组合变得毫无意义?
我的部分困惑来自下面的代码,在这里我可以使用状态变量的!.X, !:X
形式,但不能使用!X
形式。 如果可以使用前者,为什么不使用后者呢?
此代码编译并按预期运行:
% Choose values, A and B, from the list of values, subject to certain restrictions
:- pred pick_a_b(int, int, list(int), list(int)).
:- mode pick_a_b(out, out, in, out) is nondet.
pick_a_b(A, B, !Values) :-
A = pick(!.Values, !:Values),
B = pick(!.Values, !:Values),
A \= 3, A > 2, B > 2, B \= 4.
% Choose any item from the input list; pass all the un-chosen items back to the caller.
:- func pick(list(int), list(int)) = int.
:- mode pick(in, out) = out is nondet.
pick([X | Xs], Xs) = X.
pick([X | Xs], [X | Zs]) = pick(Xs, Zs).
main(!IO) :-
if
Values = [1, 2, 3, 4, 5],
pick_a_b(A, B, Values, _)
then
io.format("A = %i\n", [i(A)], !IO),
io.format("B = %i\n", [i(B)], !IO)
else
io.format("Something went wrong\n", [], !IO).
但是更改pick_a_b
的前两行pick_a_b
导致编译错误。
pick_a_b(A, B, !Values) :-
A = pick(!Values),
B = pick(!Values),
A \= 3, A > 2, B > 2, B \= 4.
您的“功能”选择有一个奇怪的模式,(进,出)=出。 这是非常不寻常的,这就是!:Values语法在第一个示例中起作用的原因。 通常情况下,函数不会具有(in,in,...,in)= out模式。
参考手册正确地说,!X语法在函数调用中没有意义,我也相信您对!:Values的使用和函数的模式也没有意义。 是的,您的代码是合法的,编译器接受并可以编译它,但是我不知道为什么有人会在这里使用函数而不是谓词。 这样做很可能使将来的人们混淆您的代码阅读。
状态变量的通常解释是,一对变量中的一个是输入,另一个是输出,而函数的通常解释是,所有参数都是输入,而返回值是输出。 参考手册指出,根据这些解释,使用状态变量作为参数是没有意义的。
推理可以概括为:仅仅因为您可以允许程序员写点东西,并不意味着您应该这样做 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.