2014-04-19 20 views
2

当描述状态变量时,水星reference manual表示:“!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(A, B, !Values) :- 
    A = pick(!Values), 
    B = pick(!Values), 
    A \= 3, A > 2, B > 2, B \= 4. 

回答

3

你的“功能”选择有一个奇怪的模式,(进出)=出。这是非常不寻常的,这就是为什么!:Values语法在你的第一个例子中起作用的原因。它通常不会像函数通常具有的模式(in,in,...,in)= out。

参考手册的正确之处在于!X语法在函数调用中没有意义,我也相信您对!:Values和您的函数模式的使用也没有意义。是的,你的代码是合法的,编译器接受它并可以编译它,但是我不知道为什么有人会在这里使用一个函数而不是谓词。这样做可能会使人们在将来阅读你的代码时感到困惑。

1

状态变量的通常解释是对中的一个是输入,另一个是输出,函数的通常解释是所有参数都是输入,返回值是输出。参考手册指出,鉴于这些解释,使用状态变量作为参数是没有意义的。

的理由可归纳为:仅仅因为你可以允许程序员写的东西,并不意味着你应该

相关问题