6

次のような組み込み呼び出しを含めることができる Prolog について疑問に思っていました。

accum(generator, filter, accumulator)
Calculates all solutions to generator.
For each one, if filter can be proved, accumulator is proved.
Backtracks to find all solutions to filter and generator.
Accumulator may backtrack internally, but multiple proofs of accumulator are 
  conjoined, not backtracked.

したがって、たとえば、再帰を使用せずにリストを合計するには、次のように記述できます。

X is 0, accum(member(Val,List), True, X is X + Val).

このコンストラクトまたは同等のプロローグはありますか? 私は Prolog の初心者であり、明らかな何かが欠けている可能性があることに注意してください。

4

3 に答える 3

5

SWI-Prologライブラリ (集合体)には強力なインターフェースがあります。

aggregate_all(sum(Val), member(Val,List), Sum)

集約と生成間での (一見単純な) 変数の共有は、述語foreach /2 を使用して得られます。

?- edit(library(aggregate)).SWI-Prologでは、内部構造を調べることができます...

library(aggregate) は比較的非効率的ですが、SWI-Prolog nb_ (非バックトラック可能) データ構造と組み合わせると、その仕事は非常にうまくいくはずです...

バックトラック不可能なデータ構造について:これは、 nb_setarg /3によって実装された「自己構築」アキュムレータの例です。

于 2013-10-17T13:55:18.497 に答える
3

Mercury の標準ライブラリでは、「ソリューション」モジュールがこのような機能を提供します。

X is X + Valは X に新しい値を割り当てないことに注意してください。これは、Val がゼロの場合は true であり、それ以外の数値の場合は false であるというステートメントであり、おそらくあなたの意図とは異なります。このようなアキュムレータは通常、初期値と最終値の関係として表現されます。

Mercury では、例は次のように記述できます。

:- import_module solutions.
...
sumlist(List, Sum) :-
    Generator = (pred(Val::out) is nondet :- member(Val, List), true),
    Accumulator = (pred(X::in, Y::in, Z::out) is det :- Z = X + Y),
    aggregate(Generator, Accumulator, 0, Sum).

ジェネレーターの一部として含めることができるため、個別のフィルター引数は必要ありません。

于 2014-10-05T12:03:21.953 に答える
3

明示的な再帰がないということですか?その場合、補助述語の必要性を回避するためにラムダ式と一緒に、上位述語リストの左折畳みの実装を使用できます。Logtalk を例として使用すると、次のように記述できます。

?- Sum0 is 0, meta::fold_left([X,Y,Z]>>(Z is Y+X), Sum0, [1,2,3], Sum).
Sum0 = 0,
Sum = 6.

Logtalk は、ほとんどの Prolog 実装 ( http://logtalk.org/ ) をバックエンド コンパイラとして使用できます。lambdaUlrich のライブラリ ( http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord.html ) をサポートされている Prolog コンパイラと一緒に使用することもできます。同じ結果です。例として now YAP を使用します。

$ yap
...
 ?- use_module(library(lambda)).
...
 ?- use_module(library(maplist)).
...
 ?- Sum0 is 0, foldl(\X^Y^Z^(Z is Y+X), [1,2,3], Sum0, Sum).
Sum = 6,
Sum0 = 0.

簡単に言うと、fold left 述語はリストを繰り返し処理し、最初の引数のクロージャをリスト要素とアキュムレータに再帰的に適用し、最終的なアキュムレータ値を返します。

于 2013-10-17T13:40:57.700 に答える