2016-03-03 151 views
7

在Prolog謂詞,我經常寫這樣的一個重複的條件語句,但我希望他們可以更簡明地寫:switch語句

output(Lang, Type, Output) :- 
    (Lang = javascript -> 
     Output = ["function", Type]; 
    Lang = ruby -> 
     Output = ["def", Type]; 
    Lang = java -> 
     Output = [Type]). 

是否有可能取代這一系列的條件語句一個更簡潔的開關語句?

+1

您在條件下編寫的括號是多餘的。您應該在整個(a-> b; c-> d; e)構造中放置一對括號。當您想要將條件與其他目標結合時,這是避免意外的最佳實踐。 – jschimpf

+0

@jschimpf我解決了這個問題,所以現在看起來更簡潔。 –

回答

6

在Prolog中,使用元謂語(以謂詞或謂詞作爲參數的謂詞)定義自己的控制結構是很容易的。

例如,你可以實現一個開關通過定義

switch(X, [Val:Goal|Cases]) :- 
    (X=Val -> 
     call(Goal) 
    ; 
     switch(X, Cases) 
    ). 

如有必要,可以再進行編譯的時候被改造更高效的構造像

switch(X, [ 
    a : writeln(case1), 
    b : writeln(case2), 
    c : writeln(case3) 
]) 

許多Prolog的作爲支持系統(ECLiPSe中的inline/2或其他幾個系統中的目標擴展)。

通過運算符聲明,您可以將語法調整爲幾乎任何您喜歡的。

1

稍短:

output(Lang, Type, Output) :- 
    (Lang, Output) = (javascript, ["function", Type]) ; 
    (Lang, Output) = (ruby, ["def", Type]) ; 
    (Lang, Output) = (java, [Type]). 

地道:

output(Lang, Type, Output) :- 
    memberchk(Lang-Output, [ 
    javascript - ["function", Type], 
    ruby - ["def", Type], 
    java - [Type] 
    ]). 
+2

使用memberchk/2是一個相當低效的方法,因爲它首先將整個結構複製到堆棧,然後運行memberchk/2並最終將複製的結構留存到結構複製到Prolog實現(這是AFAIK當前所有主動維護的實現) GC。第一個是更可接受的,但使用單獨的子句作爲下一個answe是真正的Prolog方式:由於子句索引,consise和fast。 –

+0

@JanWielemaker:我同意,我的答案不好......另外,我的第一個片段不等同於OP'代碼。但是沒有任何單獨的分句是沒有切分的...... – CapelliC

6

看來,多個子句用於該用途的情況下取得,也相當簡潔。

output(javascript, Type, ["javascript", Type]). 
output(ruby, Type, ["def", Type]). 
output(java, Type, [Type]). 
+0

當然,如果謂詞有少量參數,它只會是簡潔的。我仍然在尋找更簡潔的方式來在Prolog中實現switch語句。 –

+0

可以肯定的是,這個用例中沒有多個子句。它們是Prolog中的主流**控制流工具。因此,它們當然涵蓋了這個平凡的用例。 – CapelliC