【问题标题】:Is it acceptable for a prolog procedure to work only one way?序言程序仅以一种方式工作是否可以接受?
【发布时间】:2023-03-24 08:05:01
【问题描述】:

我有一个序言程序:

link(liverpool,preston).
link(liverpool,manchester).
link(preston,lancaster).
link(preston,manchester).
link(lancaster,carlisle).
link(lancaster,leeds).
link(carlisle,leeds).
link(manchester,leeds).

%checks to see if X is in the supplied list
inlist( X, [X|_]).
inlist( X, [_|Ys]) :- inlist( X, Ys).


merge([],L,L).

merge([H|T],BList,CList):-
inlist(H,BList),
merge(T,BList,CList).

merge([H|T],BList,[H|CList]):-
merge(T,BList,CList),
not(inlist(H,BList)).

如果我这样称呼它,合并就可以工作:

merge([a,b,c],[d,e,f],Result). --> [a,b,c,d,e,f]

或更重要的是,它旨在解决什么问题:

merge([a,b,c],[a,d,e,f],Result). --> [a,b,c,d,e,f]

但如果我这样调用合并:

merge(X,[d,e,f],[a,b,c,d,e,f]).

堆栈溢出。对于设计为以一种方式工作的功能,这是通常可接受的行为吗?还是有一些约定,函数应该以两种方式工作?

编辑:如果你这样称呼它,合并就可以工作:

merge([a,b,c],X,[a,b,c,d,e,f]). --> [d,e,f]

【问题讨论】:

    标签: prolog logic


    【解决方案1】:

    首先,您不应该调用这些“函数”。 “谓词”是正确的术语。

    Prolog 谓词通常需要“双向”工作。但在特定情况下并不总是可行或值得付出努力。

    要了解谓词的使用方式,可以使用模式声明。这些声明约定因系统而异。这些声明主要用作程序员的文档,编译器很少使用,但可以用于测试框架和其他帮助工具。

    模式声明的约定示例:

    还有一个约定(例如,在“Prolog 的工艺”中描述)谓词的输入参数在前,输出参数在最后。

    【讨论】:

    • @mbratch - 如果您已指定(使用 Sergey 的模式)谓词不是 2 方式,那么肯定(像其他语言一样?)“其他”方式的行为是“未定义”,在在哪种情况下它可能会失败,堆栈溢出,制作一杯优质的大吉岭茶,或任何它想要的东西?是否应该在每种情况下明确编写代码以捕获“其他”方式并返回失败?您描述的这种“失败”行为是一种标准或一种惯例,还是一种很好的做法?
    • @mbratch:在任何情况下,“堆栈溢出”,即资源错误,或更一般的非终止,或实例化错误都比不正确或不完整的答案更可取。跨度>
    • @false & magus - 写完评论后,我重新考虑并同意。
    • 我了解,因此使用例如检测意外变量分配。 var/1 或 nonvar/1, instantiation_error/1 应该被调用(作为谓词的最后一行),这会向调用者引发异常。
    • @magus,在 Prolog 术语中,我认为它被称为“关系”,因为它可以是两种方式,三种方式等,具体取决于有多少变量。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-23
    相关资源
    最近更新 更多