List 如何检查Prolog列表中的每个元素是否大于0?

List 如何检查Prolog列表中的每个元素是否大于0?,list,recursion,prolog,List,Recursion,Prolog,我有以下Prolog谓词原型:solution(+InputVector),其中InputVector是长度未知的值列表。如果列表中的所有值都大于0,我将打印一条消息。我该怎么做 尝试检查列表是否为[]或[X | Xs],并相应地采取行动。您就快到了。考虑下面(更新感谢@ ABT医生): 让我们考虑一下这一行是如何工作的: 定义谓词solution/1的第一个子句,该子句将包含X的单个元素列表作为参数 测试项目X是否为>0的数字。否则,谓词将在此处终止并失败。否则,Prolog将继续到下一行 虽

我有以下Prolog谓词原型:solution(+InputVector),其中InputVector是长度未知的值列表。如果列表中的所有值都大于0,我将打印一条消息。我该怎么做

尝试检查列表是否为[]或[X | Xs],并相应地采取行动。

您就快到了。考虑下面(更新感谢@ ABT医生):

让我们考虑一下这一行是如何工作的:

  • 定义谓词
    solution/1
    的第一个子句,该子句将包含
    X
    的单个元素列表作为参数
  • 测试项目
    X
    是否为
    >0
    的数字。否则,谓词将在此处终止并失败。否则,Prolog将继续到下一行
  • 虽然不是严格必要的,但是这里的cut(
    )删除了在第(1)行生成的选择点Prolog,因为第(6)行的第二个子句也可能是用输入执行的
    [X]
    ,因为这相当于
    [X | Y]
    其中
    Y
    =
    []
    。因此,这是一种所谓的“grue”——仅为提高效率而削减
  • 由于列表
    [X]
    包含所有大于零的元素,谓词将打印一条消息并成功
  • 定义谓词
    solution/1
    的第二个子句,它获取一个包含一个或多个项的列表,其中
    X
    是列表的头部,
    Y
    是列表的尾部(剩余部分)(列表本身可能为空:
    []
  • 与第(2)行相同
  • 继续递归测试列表的其余部分,
    Y
  • 请注意,上述定义假定
    solution/1
    只能在大于零的非空数字列表上成功。如果希望允许此谓词在空列表上成功,则可以简化实现:

    solution([]) :- 
        write_ln('Success!').
    solution([X|Y]) :-
        X > 0, 
        solution(Y).
    
    在此版本中,
    solution/1
    的两个子句中的任何一个都是基于参数执行的:第一个处理空列表,第二个处理大于零的非空数字列表。这里不需要cut(
    ),因为谓词参数是不可统一的(
    []
    \=
    [X | Y]
    ),并且Prolog不会为第一个子句的任何调用生成选择点


    我希望这对您有所帮助,并使Prolog语法的一些语义更清晰。

    我将这样编写谓词:

    all_greater_than_zero([]).
    all_greater_than_zero([H|T]) :-
        H > 0,
        all_greater_than_zero(T).
    

    我认为空名单是可以接受的。如果不是,你可以删除第一个子句。

    < P>如果你有兴趣将你的学习扩展到“高阶”谓词,考虑/ 2:


    3?-maplist(你已经在你的问题中描述了解决方案……我是prolog新手,我的教授不是最好的老师,所以我只是在猜测和测试。下面是一个我迄今为止尝试过的例子:解决方案([X | Y]):-X>0。解决方案([u | Y]):-solution Y(Y)。你没有处理空列表
    []
    ,当前,如果任何数字都大于零,则您的解决方案将成功,如果所有数字都大于零,则不会成功。我对prolog完全不熟悉,因此语法本身对我来说完全不熟悉。同样,如果原始输入列表为空(可能不是预期的),则此操作将失败。此外,如果没有if-then-else,则执行此操作似乎更干净。您可以把没有
    ->
    的空列表包括在内,这样:
    解决方案([Val]):-Val>0,写下[u ln('Solved')。解决方案([Val]Vals]):-Val>0解决方案(Vals)
    @aBathologist你说得对,谢谢!我会更新答案,因为我更喜欢它,因为它简化了描述(特别是针对假定空列表正常的备选方案)@sharky我很高兴我能做出有用的贡献!我有两个问题,以防万一你有时间回答:首先,我对Prolog很陌生,还没有来得及研究切割,所以我对它在这里的用法仍然有点不清楚,但我不知怎的形成了一种偏见,认为最好尽可能避免它们,因为它们会增加声明式方法的“不洁”。这有什么道理吗?第二,你能避免第5行与[X,Y |[]]之间的歧义吗?@aBathologist,而在实践中,cuts确实会使Prolog程序变得不洁(例如对于现实世界的Prolog编程)削减通常对效率至关重要。如果你在做任何严肃的Prolog编程,我建议你了解如何以及何时正确使用。此外,
    [X | Y]
    !=
    [X,Y |[]]
    。列表符号中的条形
    将头元素(LHS)与尾元素(RHS)分开。在
    [X | Y]
    X
    是head元素,
    Y
    是任意长度的尾部列表,而
    [X,Y |[]]
    表示长度为2的列表。如果不能接受空列表,那么如果所有元素都是
    >0
    ,那么简单地删除示例中的第一个子句如何允许OP根据需要“打印消息”?
    all_greater_than_zero([]).
    all_greater_than_zero([H|T]) :-
        H > 0,
        all_greater_than_zero(T).
    
    3 ?- maplist(<(0), [1,2,3]).
    true.
    
    4 ?- maplist(<(0),[0,1,2,3]).
    false.