2013-10-17 30 views
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這個構造或等價物?請記住,我在Prolog中有點新手,可能會漏掉一些明顯的東西。

+0

在水星裏,人們只會寫一個名爲accum的謂詞來做這件事。然而,你不能使用目標作爲參數(就像你在問題中所做的那樣),你必須改用lambda表達式。 –

+0

@PaulBone結果取決於計算髮生器的所有解決方案。因此,最終,從Mercury的「解決方案」模塊中調用某些東西仍然是必需的,除非你想使用非邏輯功能(在這種情況下,副詞「簡單」不適用;))。 –

回答

3

我假設你的意思是沒有顯式遞歸?如果是這樣,則可以使用高位謂詞列表的實現向左摺疊,並使用lambda表達式來避免需要輔助謂詞。使用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/)。您還可以使用帶支持的Prolog編譯器的Ulrich的lambda庫(http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord.html)以及爲相同結果提供摺疊左謂詞的Prolog庫。現在使用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. 

簡言之,摺疊左謂詞遍歷列表,遞歸地施加在其第一個參數的列表元素和蓄能器的關閉,返回最終累加器值。

+0

問題是要求通過回溯生成解決方案。你的迴應從已經生成的解決方案[1,2,3]開始,所以它不回答這個問題。 –

+0

'[1,2,3]'是**不是**解決方案列表,它是**輸入**列表,與您在「成員(Val,List)」位傳入的內容相同問題的例子。 –

+0

你只解決了這個例子,而不是一般情況。我再說一遍,問題顯然是要求回溯生成解決方案。 –

5

SWI-Prolog的library(aggregate)有一個強大的接口,例如

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

的(看似簡單)分擔匯聚和發電之間的變量與斷言獲得foreach/2,這可能會感興趣。

在SWI-Prolog中,你可以做?- edit(library(aggregate)).學習的內部...

庫(總)效率比較低,但加上SWI-Prolog的nb_(非backtrackable)數據結構應該做的工作非常好...

關於不可回溯的數據結構:here是我的「自建」累加器的一個示例,通過nb_setarg/3實現。

2

在Mercury的標準庫中,「解決方案」模塊提供了這樣的功能。

請注意,X is X + Val不會爲X分配新值。如果Val爲零,則爲true;如果爲其他任何數字,則爲false,這可能不是您的意思。像這樣的累加器通常表示爲初始值和最終值之間的關係。

在水星,你的例子可以寫成:

​​

無需單獨的過濾器參數,因爲它可以作爲發電機的一部分。

相關問題