2

状態変数を説明するとき、Mercury のリファレンス マニュアルでは次のように述べて!Xいます。私はその推論をよりよく理解したいと思います.状態変数と関数について、組み合わせを無意味にするのは何ですか?

私の混乱の一部は、以下のコードから来ています。ここでは!.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).

ただし、最初の 2 行を変更するとpick_a_b、コンパイル エラーが発生します。

pick_a_b(A, B, !Values) :-
    A = pick(!Values),
    B = pick(!Values),
    A \= 3, A > 2, B > 2, B \= 4.
4

2 に答える 2

3

あなたの「機能」ピックには奇妙なモード、(イン、アウト)=アウトがあります。これは非常に珍しいことであり、これが !:Values 構文が最初の例で機能する理由です。通常、関数にはモード (in、in、...、in) = out があるため、通常はそうではありません。

リファレンス マニュアルは、関数呼び出しでは !X 構文が意味をなさないと言っている点で正しいです。また、!:Values の使用と関数のモードも意味をなさないと思います。はい、あなたのコードは合法であり、コンパイラはそれを受け入れてコンパイルできますが、述語ではなく関数を使用する理由がわかりません。これを行うと、将来コードを読む人が混乱する可能性があります。

于 2014-04-21T03:46:57.777 に答える