Prolog中的Switch语句

Prolog中的Switch语句,prolog,switch-statement,pattern-matching,Prolog,Switch Statement,Pattern Matching,在Prolog谓词中,我经常编写重复的条件语句,就像这样,但我希望它们可以写得更简洁: output(Lang, Type, Output) :- (Lang = javascript -> Output = ["function", Type]; Lang = ruby -> Output = ["def", Type]; Lang = java -> Output = [Type]). 是否可以

在Prolog谓词中,我经常编写重复的条件语句,就像这样,但我希望它们可以写得更简洁:

output(Lang, Type, Output) :-   
    (Lang = javascript ->
        Output = ["function", Type];
    Lang = ruby ->
        Output = ["def", Type];
    Lang = java ->
        Output = [Type]).
是否可以用更简洁的switch语句替换这一系列条件语句?

稍微短一点:

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]
  ]).

似乎为这个用例设计了多个子句,而且非常简洁

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

在Prolog中,使用元谓词(将目标或谓词作为参数的谓词)定义自己的控制结构非常容易

例如,您可以实现一个开关构造,如

switch(X, [
    a : writeln(case1),
    b : writeln(case2),
    c : writeln(case3)
])
通过定义

switch(X, [Val:Goal|Cases]) :-
    ( X=Val ->
        call(Goal)
    ;
        switch(X, Cases)
    ).
如有必要,可以通过许多Prolog系统(在ECLiPSe中,或在其他几个系统中进行目标扩展)支持的编译时转换来提高效率


通过运算符声明,您可以将语法调整到您喜欢的任何程度。

使用memberchk/2复制Prolog实现(这些实现目前都是活动维护的实现)的结构是一种非常低效的方法,因为它首先将整个结构复制到堆栈,然后运行memberchk/2,最后将复制的结构的回忆留给GC。第一个更容易接受,但使用单独的子句作为下一个answe才是真正的开场白方式:考虑到子句索引,考虑周到且快速。@JanWielemaker:我同意,我的答案不太好。。。而且,我的第一个代码片段并不等同于OP代码。但是,如果没有删减,两个单独的子句都不会……当然,只有当谓词有少量参数时,它才会简洁。我仍在寻找一种更简洁的方法来实现Prolog中的switch语句。它们是Prolog中可用的主要控制流工具。因此,它们当然涵盖了这个陈腐的用例。您在条件周围写的括号是多余的。您应该在整个(a->b;c->d;e)构造周围放置一对圆括号。当你想把条件和其他目标结合起来时,这是避免意外的最佳实践。@JSF我解决了这个问题,所以现在看起来更简洁了。