Prolog 序言列表平方,修改列表中的元素

Prolog 序言列表平方,修改列表中的元素,prolog,Prolog,我正试图编写一个简短的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添加到列表时对其进行平方运算。。。你有没有想过我该怎么做?你离得不远,但你犯了两

我正试图编写一个简短的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
与列表
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).
第三,还有一个更根本的问题。对于前两个修复,代码可以正常工作,但基本情况,即第一个子句,选择得不太好。(A) 代码无法处理空列表。(B) 对于单例列表,代码是不必要的不确定的,因为这两个子句都适用。这可以通过明智地选择基本情况来解决:

squares([], []).
squares([X|Xs], [Y|Ys]):-
  Y is X ^ 2,
  squares(Xs, Ys).

你离得不远,但你犯了两个小错误:

首先,将元素
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).
第三,还有一个更根本的问题。对于前两个修复,代码可以正常工作,但基本情况,即第一个子句,选择得不太好。(A) 代码无法处理空列表。(B) 对于单例列表,代码是不必要的不确定的,因为这两个子句都适用。这可以通过明智地选择基本情况来解决:

squares([], []).
squares([X|Xs], [Y|Ys]):-
  Y is X ^ 2,
  squares(Xs, Ys).

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中可用的每个元素E提供一个“名称”。findall/3计算其目标
,(member(E,L),Sq是E*E),
,并收集结果(“模板”表达式,即
Sq
)。

序言没有“功能性”思维,但是一些标准的内置谓词可以帮助处理列表。在这种情况下

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中可用的每个元素E提供一个“名称”。findall/3计算其目标
,(member(E,L),Sq是E*E),
,并收集结果(“模板”表达式,即
Sq
).

这里有一个通用的方法,您可以定位这样的错误。首先,让我们从您的示例开始:

?- 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], [Y]):-
  Y is X ^ 2.
在递归规则中应该使用相同的
(is)/2
。还有,为什么不接受
[]

一、 就个人而言,我更愿意使用:

或者,使用
库(clpfd)


下面是一个常规方法,您可以如何定位此类错误。首先,让我们从您的示例开始:

?- 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], [Y]):-
  Y is X ^ 2.
在递归规则中应该使用相同的
(is)/2
。还有,为什么不接受
[]

一、 就个人而言,我更愿意使用:

或者,使用
库(clpfd)


您可以只做
list of_square(L,S):-maplist(square,L,S)。正方形(X,XS):-XS是X^2。
你可以做
列出正方形(L,S):-maplist(正方形,L,S)。正方形(X,XS):-XS是X^2。
作为一个一般性问题,用L代替Y有什么内在的错误吗?@DarioP无任何错误
Y
L
只是变量名。您也可以使用
Fred
。或
Dario
:)@达里奥普,一点也不!任何变量名都可以,只要使用一致(例如,与另一个应该表示其他内容的变量不同)。纯粹出于教学目的,我选择变量名
X
Y
代表单个元素,选择变量名
Xs
Ys
代表元素列表。我没有复制您使用的
L
的原因是它有时被用来表示列表。(啊,潜伏者你很快:-P)@WouterBeek谢谢!我已经尝试实施了你的建议,所以对于清单[2,3,4],我得到了[4,9 | 16]。只是想知道|从何而来…@DarioP管道字符通常用于分隔列表的开头和结尾,例如
[a |[b,c]]==[a,b,c]
。据我所知,
[4,9 | 16]
不是一个列表,所以我不确定你是如何得到这个结果的。您使用的是哪种Prolog实现?作为一个一般性问题,使用L而不是Y有什么固有的错误吗?@DarioP一点也没有<代码>Y