我正在讨论是否应该检查这两个列表是否通过除以/或%来检查两个列表是否都是列表是偶数并返回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]
但是当我去测试它时它返回了假。怎么会发生这种情况?
答案 0 :(得分:3)
您的代码存在一些问题,但让我先向您展示解决方案。
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
(感谢@CapelliC!)。
(旁白:你通过这种暂停评估权衡实际购买的是大量的DSL建设能力,但是大多数大学的初学者都没有看到它,所以他们只是发现它毫无意义的挫折。)
现在讨论问题。
首先,您的代码有一些"类型"混淆:如果给出空列表,则最终变量与0结合;如果您获得非空列表,它将与一个或另一个列表统一。我很难想象一个有意义的场景;我不知道这是否是Python的遗留物,其中0的布尔风味为false,但非空列表的布尔风味为true。或者,可能是您认为您需要一个基本案例,即使您并未真正使用列表的归纳案例。也许第三个论点就是代表结果,因为事情必须有结果。 :)无论情况如何,它都不是非常必要或正确。
其次,你正在犯这样一个诚实的初学者错误,假设算术表达式是由Prolog评估的。这是一个诚实的错误;地球上的其他语言都是这样的,但Prolog是不同的。 N/2 && M/2 || N%2 && M %%2
与语法上可接受的Prolog相差甚远。首先,%
是Prolog中的注释字符;我们使用mod
进行模运算(如Python)。另外,因为is/2
是关于评估算术表达式的,所以没有boolean"和"的语法。和布尔"或,"只是按位,这不完全是你需要的。常规逻辑"和"和"或"分别是Prolog中的,
和;
。但我认为这个表达方式比你需要的更复杂;你只需知道他们有相同的余数mod 2。
让Prolog的统一机制代表你传达真假,而不是用某些变量明确地统一真假,这几乎总是更好;否则你可以很容易地进入谓词已经成功的奇怪情况。在某种意义上意味着传达失败。此外,你还在使用Prolog!您应该享受回溯的好处,而不是编写程序代码。
希望这可以解决问题!