列表更换器功能

时间:2015-11-07 21:13:03

标签: list

我在这里找出一个简单的Prolog问题时遇到了一些麻烦。 我需要在原子列表的元素上执行某种操作(由我自己定义)。但是,如果列表中的元素对于指定的谓词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].

其中isOddaddOne都是简单的规则,它们检查输入变量是否为奇数,并分别在输入变量中加1。

我无法弄清楚当findall谓词在技术上应该找到第一个列表的所有成员时,为什么Prolog只找到列表中的一个元素。

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

2 个答案:

答案 0 :(得分:2)

一些建议......

您不需要=../2call(P, X)会使用参数P调用仿函数X,而call(OP, X, Y)将使用参数OPX调用仿函数Y

如果您正确设置了条件,可以在此处使用findall。它将收集导致给定表达式成功的值(产生true)。由于您希望将映射列表中的每个元素添加到结果中,因此我会将maplist/3与谓词类似,mutate_one_if(P, OP, X, Y)将单个X变为{ {1}}或单独留下(Y),具体取决于条件(按照您的要求)。

X = Y

mutate_one_if(P, OP, X, Y) :- ( call(P, X) -> call(OP, X, Y) ; X = Y ). mutate_if(P, OP, L1, L2) :- maplist(mutate_one_if(P, OP), L1, L2). 会针对maplist/3mutate_one_if(P, OP)中的每个对应元素致电L1。如您所见,L2非常灵活,因为如果您想致电call,可以将其称为mutate_one_if(P, OP, X, Y)call(mutate_one_if(P, OP), X, Y)。 Prolog的call(mutate_one_if(P, OP, X, Y))将适当地收集论据。

所以,使用这些:

call

收率:

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

答案 1 :(得分:2)

我认为你没有正确确定'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).

我得到了

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

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