【问题标题】:Prolog split list by predicate - how to check predicate's result?Prolog 按谓词拆分列表 - 如何检查谓词的结果?
【发布时间】:2016-05-20 21:28:51
【问题描述】:

我正在尝试实现一个谓词,它将整数列表拆分为两个给定另一个谓词作为参数。定义如下:

split(P, L, L1, L2),

在哪里:

P - predicate to split upon
L - list to split
L1 - result list of integers that return true on predicate check
L2 - result list of integers that return false on predicate check

我正在尝试修改此代码,它使用硬编码检查所讨论的整数是否更大/更小或等于 X 来拆分列表(这可行):

split(X, [], [], []).
split(X, [H|T], [H|L1], L2) :- H=<X, split(X, T, L1, L2).
split(X, [H|T], L1, [H|L2]) :- H>X, split(X, T, L1, L2).

出于测试目的,我从 RosettaCode 中复制了一个谓词来检查数字是否为偶数,如下所示:

even(N) :-
 (between(0, inf, N); integer(N) ),
 0 is N mod 2.

这是我对上面代码的修改,但它在最后两行返回“语法错误:预期运算符”:

split2(P, [], [], []).
split2(P, [H|T], [H|L1], L2) :- P(H), split2(P, T, L1, L2).
split2(P, [H|T], L1, [H|L2]) :- \+ P(H), split2(P, T, L1, L2).

我认为我的错误在于检查谓词是返回真还是假,但找不到合适的方法。

编辑:忘记添加我的电话:

 ?- split2(even,[2,7,4,8,-1,5],L1,L2)

【问题讨论】:

    标签: list prolog


    【解决方案1】:

    不能这样调用谓词,需要使用call

    ?- A = between(0,3,1), A. % OK, because A can be evaluated as it is
    A = between(0, 3, 1).
    
    ?- A = between, A(0,3,1). % won't work
    ERROR: Syntax error: Operator expected
    ERROR: A = between, 
    ERROR: ** here **
    ERROR: A(0,3,1) . 
    ?- A = between, call(A, 0, 3, 1). % OK, using call
    A = between.
    
    ?- A = between(0, 3), call(A, 1). % Partial application
    A = between(0, 3).
    

    请记住,已经有库谓词可以完全满足您的需求,请参阅library(apply),尤其是。 include/3。您还应该看看at the implementation,因为它与您正在做的事情略有不同,并且不会留下选择点。

    PS:重新排列参数以使输入列表位于最前面是实现此确定性的第一步。你还需要去掉两个子句引起的选择点,一个是call(P,H),一个是\+ call(P,H)。您可以使用-&gt; 来执行此操作,就像在 SWI-Prolog 库中一样。

    或者你可能不被选择点所困扰,或者想要做一个更一般的谓词。我确信在 Prolog 标签上的 Stackoverflow 上有解决方案。

    【讨论】:

    • "已经有库谓词可以完全满足您的需求" - 我想是这样,但我想自己写一个来学习 Prolog。如果您能详细说明您的答案,我将不胜感激。正如您从我的问题中看到的那样,我是 Prolog 的新手,我真的不知道如何解决这个问题,非常感谢您提供任何帮助(我尝试用谷歌搜索,但是当您不知道该怎么做时很难搜索)。解决我的问题是否需要进行大量更改?
    • @Asunez 请重新阅读我的回答。我使用一个简化的示例重现了您的错误,并向您展示了如何纠正它。
    • @Asunez 如果您愿意点击我提供的链接,尤其是显示include/3 实现的链接,您将看到一个如何使用call 的示例来评估一个谓词。阅读他人的代码是学习编程的最基本方法之一。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多