我正在尝试编写一个简短的Prolog程序,该程序会获取一个数字列表并返回一个列表,其中所有数字都已被平方。
即:[2,4,5]
=> [4,16,25]
到目前为止我的代码:
list_of_squares([X], L) :-
L is X^2.
list_of_squares([X|XS], [X^2|M]) :-
list_of_squares(XS, M).
出于某种原因,尽管Prolog并不喜欢我在将X添加到列表时对X进行平方...对于我如何做到这一点的任何想法?
答案 0 :(得分:3)
你不是那么遥远,但是你犯了两个小错误:
首先,您将元素X
与列表L
混合。你的第一个条款应该是:
list_of_squares([X], [Y]):-
Y is X ^ 2.
其次,您不能以列表表示法执行算术功能。 您的第二个条款应如下:
list_of_squares([X|Xs], [Y|Ys]):-
Y is X ^ 2,
list_of_squares(Xs, Ys).
第三,存在一个更基本的问题。使用前两个修复程序,您的代码可以正常工作,但基本情况(即第一个子句)并没有很好地选择。 (一)代码无法处理空列表。 (B)对于单例列表,代码是不必要的不确定性,因为这两个条款都适用。这可以通过明智地选择基本案例来解决:
squares([], []).
squares([X|Xs], [Y|Ys]):-
Y is X ^ 2,
squares(Xs, Ys).
答案 1 :(得分:1)
以下是一般方法,您可以如何本地化此类错误。首先,让我们从你的例子开始:
?- list_of_squares([2,4,5],[4,16,25]).
false.
哦不!它失败!在这种情况下,有一种非常通用的方法:
所以我们用一个新的,新鲜的(啊,真正的新鲜!)变量替换[4,16,25]
:
?- list_of_squares([2,4,5],L).
L = [2^2, 4^2|25] ;
false.
这样更好:现在你知道有一个“结果”,但结果并不是你所期望的。
接下来,
列表太长了,所以我会砍掉一些元素。说,前两个:
?- list_of_squares([5],L).
L = 25 ;
false.
再次,错误,但更小。现在,错误在哪里?得到它
list_of_squares([X], L) :- L is X^2.list_of_squares([X|XS], [X^2|M]) :- false, list_of_squares(XS, M).
该程序再次给出了同样错误的答案!所以在可见部分有一个错误。我们期待的是
?- list_of_squares([5],[25]).
false.
这是成功的。但错误在哪里?再次:
?- list_of_squares([5],[X]).
false.
HET!
现在,您应该意识到该规则可能是:
list_of_squares([X], [Y]):-
Y is X ^ 2.
在递归规则中应该使用相同的(is)/2
。而且,为什么不接受[]
。
我个人宁愿使用library(lambda)
写一下:
list_of_squares(Xs, Ys) :-
maplist(\X^XX^(XX is X^2), Xs, Ys).
或者,甚至更好,使用library(clpfd)
list_of_squares(Xs, Ys) :-
maplist(\X^XX^(XX #= X^2), Xs, Ys).
答案 2 :(得分:0)
Prolog没有'功能'思维模式,但是一些标准的内置谓词可以帮助处理列表。在这种情况下
list_of_squares(L,S) :- findall(Sq,(member(E,L),Sq is E*E),S).
?- list_of_squares([2,4,5], R).
R = [4, 16, 25].
在这种情况下,member / 2扮演类似于lambda表达式的角色,为L. findall / 3中的每个元素E提供一个“名称”,计算其目标,(member(E,L),Sq is E*E),
的所有解,并收集结果( '模板'表达式,即Sq
)。