List 在Prolog中检查两个列表是否都是偶数或奇数

List 在Prolog中检查两个列表是否都是偶数或奇数,list,prolog,List,Prolog,我正在争论是否应该用/或%除以来检查两个列表是否为偶数,以检查两个列表是否都为偶数并返回true,或者两个列表都为奇数并返回true,否则返回false;使用以下代码: evenOrOdd([],[],0). evenOrOdd(List1, List2, Output) :- length(List1, N), length(List2, M), (N/2 && M/2 || N%2 && M%%2 -> Output = List1

我正在争论是否应该用/或%除以来检查两个列表是否为偶数,以检查两个列表是否都为偶数并返回true,或者两个列表都为奇数并返回true,否则返回false;使用以下代码:

evenOrOdd([],[],0).
evenOrOdd(List1, List2, Output) :-
   length(List1, N),
   length(List2, M),
(N/2 && M/2 || N%2 && M%%2 ->
    Output = List1
;   Output = List2
).
下面的代码无法正确编译,我也不知道会出现什么问题。最后,我要比较的两个列表是:

[x,x,x]
[1,2,3]

但当我去测试它时,它返回了false。为什么会发生这种情况?

您的代码有几个问题,但首先让我向您展示解决方案

evenOrOdd(L, R) :-
  length(L, N),     length(R, M),
  N mod 2 =:= M mod 2.
你会注意到的第一件事是我必须创建很多临时值。Prolog中的表达式计算实际上是由
is/2
触发的;这不是自动发生的。尽管编写
N mod 2=M mod 2
很有诱惑力,但它只有在
N=M
时才会统一,这不是您想要的。您必须使用
is/2
触发求值,然后直接比较值,或者使用本身执行求值的
=:=/2
(谢谢@capelical!)

(旁白:在这种暂停评估权衡中,你实际上购买的是大量的DSL构建能力,但大多数大学课程的初学者从未看到这一点,所以他们只是觉得这是一种毫无意义的挫折。)

现在来讨论这些问题

首先,您的代码有一些“类型”混淆:如果给您的列表为空,那么最后一个变量将与0统一;如果给您非空列表,它将与一个或另一个列表统一。我很难想象这样的情景会有什么意义;我怀疑这是否是Python的遗留版本,其中0的布尔值为false,而非空列表的布尔值为true。或者,你可以假设你需要一个基本情况,即使你没有真正使用列表中的归纳情况。也许第三个参数只是用来表示一个结果,因为,事情必须有结果不管是什么情况,这都不是十分必要或正确的

其次,您犯了一个诚实的初学者错误,即假设算术表达式是由Prolog计算的。这是一个诚实的错误;地球上所有其他语言都是这样工作的,但Prolog是不同的
N/2&&M/2 | | N%2&&M%%2
远远不是语法上可以接受的序言。首先,
%
是Prolog中的注释字符;我们使用
mod
进行模块化算术(如Python)。另外,因为
is/2
是关于计算算术表达式的,所以布尔“and”和“and boolean”或“just bit-wise”没有语法,这并不完全是您需要的。规则的逻辑“and”和“or”是
。但我认为这个表达比你需要的要复杂得多;你只需要知道它们有相同的mod 2余数

允许Prolog的统一机制代表您传达真或假,而不是用一些变量明确地统一真和假,这几乎总是更好的;否则,您很容易遇到奇怪的情况,谓词在某种意义上“成功”表示失败。此外,您正在使用Prolog!您应该享受回溯的好处,而不是编写过程代码


希望这能把事情弄清楚

很好的解释。只是,可能更简单一些:
N mod 2=:=M mod 2
@capelical我总是忘记这一点!谢谢@DanielLyons谢谢你澄清了事情!我来自一个更java的背景,所以介绍Prolog可能会有点混乱。当我去测试我的代码时,它不起作用。我试图使用上面的代码已在上面的代码中编辑。再次感谢你的帮助!您的示例输入使用我的谓词。您仍在尝试使用您的谓词吗?@DanielLyons不,我正在使用您的谓词,但这是我得到的错误:错误:长度/2:Type错误:
list'应为,已为
4'(整数)