List 列表变换器功能

List 列表变换器功能,list,List,在这里,我很难理解一个简单的序言问题。 我需要对原子列表的元素执行某种操作(由我自己定义)。但是,只有当列表中的元素对于指定的谓词P(x)返回true时,我才应该执行这样的操作 所以基本上,如果我有规则: mutate_if(isOdd, addOne, [1,2,3,4,5], L2). 我应该得到以下输出: L2 = [2,2,4,4,6] 到目前为止,我已经想出了这个代码 mutate_if(P, OP, L1, L2):- findall(Y, ((member(X,L1),

在这里,我很难理解一个简单的序言问题。 我需要对原子列表的元素执行某种操作(由我自己定义)。但是,只有当列表中的元素对于指定的谓词P(x)返回true时,我才应该执行这样的操作

所以基本上,如果我有规则:

mutate_if(isOdd, addOne, [1,2,3,4,5], L2).
我应该得到以下输出:

L2 = [2,2,4,4,6]
到目前为止,我已经想出了这个代码

mutate_if(P, OP, L1, L2):-
  findall(Y, ((member(X,L1),
  Oper=.. [P,X],
  call(Oper)) -> (Mutate=.. [OP, X, Y], call(Mutate)); X=Y),
  L2).
在我看来,这应该可以很好地工作,但是当我在Prolog SWI上运行它时,我得到以下结果:

?- mutate_if(isOdd, addOne, [1,2,3,4,5], L2).<
L2=[2].
?-如果(isOdd,addOne,[1,2,3,4,5],L2)发生突变<
L2=[2]。
其中,
isOdd
addOne
都是检查输入变量是否为奇数的简单规则,并分别向输入变量添加一个

我不明白为什么Prolog只查找列表的一个元素,而
findall
谓词在技术上应该查找第一个列表的所有成员


这是我自己的逻辑错误吗?

有几点建议

对此,您不需要
=../2
call(P,X)
将使用参数
X
调用函子
P
call(OP,X,Y)
将使用参数
X
Y
调用函子
OP

如果您正确设置了条件,可以在此处使用
findall
。它将收集导致给定表达式成功的值(产生
true
)。由于您希望将列表中的每个元素映射到一个结果,因此我将使用
maplist/3
和一个谓词,如
mutate\u one\u if(P,OP,X,Y)
,它将单个
X
变为
Y
,或者根据条件(如您所需)单独使用(
X=Y

maplist/3
将为
L1
L2
中的每个对应元素调用
mutate\u one\u if(p,OP)
。如您所见,
调用
非常灵活,因为如果您想调用
mutate\u one\u if(P,OP,X,Y)
,您可以将其称为,
调用(mutate\u one\u if(P,OP,X,Y)
或As
调用(mutate\u one\u if(P,OP,X,Y))
。Prolog的
调用将适当地收集参数

因此,使用这些:

isOdd(X) :- X /\ 1 =:= 1.
addOne(X, Y) := Y is X + 1.
收益率:

| ?- mutate_if(isOdd, addOne, [1,2,3,4,5], L).

L = [2,2,4,4,6]

yes

一些建议

对此,您不需要
=../2
call(P,X)
将使用参数
X
调用函子
P
call(OP,X,Y)
将使用参数
X
Y
调用函子
OP

如果您正确设置了条件,可以在此处使用
findall
。它将收集导致给定表达式成功的值(产生
true
)。由于您希望将列表中的每个元素映射到一个结果,因此我将使用
maplist/3
和一个谓词,如
mutate\u one\u if(P,OP,X,Y)
,它将单个
X
变为
Y
,或者根据条件(如您所需)单独使用(
X=Y

maplist/3
将为
L1
L2
中的每个对应元素调用
mutate\u one\u if(p,OP)
。如您所见,
调用
非常灵活,因为如果您想调用
mutate\u one\u if(P,OP,X,Y)
,您可以将其称为,
调用(mutate\u one\u if(P,OP,X,Y)
或As
调用(mutate\u one\u if(P,OP,X,Y))
。Prolog的
调用将适当地收集参数

因此,使用这些:

isOdd(X) :- X /\ 1 =:= 1.
addOne(X, Y) := Y is X + 1.
收益率:

| ?- mutate_if(isOdd, addOne, [1,2,3,4,5], L).

L = [2,2,4,4,6]

yes

我认为您没有正确确定“if/then/else”操作数的作用域。 根据这个定义

mutate_if(P, OP, L1, L2):-
  findall(Y, (
    member(X,L1),
    Oper=.. [P,X],
    ( call(Oper) -> Mutate=.. [OP, X, Y], call(Mutate); X=Y )
  ), L2).
我明白了


(请注意,@lower建议非常有价值)

我认为您没有正确确定“if/then/else”操作数的范围。 根据这个定义

mutate_if(P, OP, L1, L2):-
  findall(Y, (
    member(X,L1),
    Oper=.. [P,X],
    ( call(Oper) -> Mutate=.. [OP, X, Y], call(Mutate); X=Y )
  ), L2).
我明白了

(请注意,@潜伏者建议非常有价值)