prolog有spread/splat/*args运算符吗?



在许多过程语言(如python)中,我可以"解压缩"列表并将其用作函数的参数。例如。。。

def print_sum(a, b, c):
sum = a + b + c
print("The sum is %d" % sum)
print_sum(*[5, 2, 1])

此代码将打印:"The sum is 8">

下面是此语言功能的文档。

prolog有类似的功能吗?

有没有办法在Prolog中复制这种参数解包行为?

例如,我想在将列表变量传递到调用之前对其进行解压缩。

我可以写这样的谓词吗?

assert_true(Predicate, with_args([Input])) :-
call(Predicate, Input).
% Where `Input` is somehow unpacked before being passed into `call`.

。然后我可以查询

?- assert_true(reverse, with_args([ [1, 2, 3], [3, 2, 1] ])).
% Should be true, currently fails.
?- assert_true(succ, with_args([ 2, 3 ]).
% Should be true, currently fails.
?- assert_true(succ, with_args([ 2, 4 ]).
% Should be false, currently fails.

笔记

  • 您可能认为这是一个 XY 问题。可能是,但不要气馁。最好收到我的问题标题的答案。

  • 你可能会告诉我,我处理这个问题的方式很差。我知道你的意图是好的,但这种建议无助于回答这个问题。请参考以上几点。

  • 也许我以太多的程序思维方式接近Prolog。如果是这种情况,那么什么心态可以帮助我解决问题?

  • 我正在使用SWI-Prolog。

内置(=..)/2(univ) 用于此目的。 例如

?- G =.. [g, 1, 2, 3].
G = g(1,2,3).
?- g(1,2,3) =.. Xs.
Xs = [g,1,2,3].

但是,请注意,参数数量固定的(=..)/2的许多用法都可以替换为call/2...call/8.

首先:如果你知道列表的形状,那么使用统一和模式匹配来获取列表的元素或任何术语的参数太容易了。换句话说:

sum_of_three(X, Y, Z, Sum) :- Sum is X+Y+Z.
?- List = [5, 2, 1],
List = [X, Y, Z], % or List = [X, Y, Z|_] if the list might be longer
sum_of_three(X, Y, Z, Sum).

例如,如果您有命令行参数,并且只对前两个命令行参数感兴趣,则很容易像这样获取它们:

current_prolog_flag(argv, [First, Second|_])

许多标准谓词将列表作为参数。例如,任何需要多个选项的谓词,如open/3open/4。这样的对可以按如下方式实现:

open(SrcDest, Mode, Stream) :-
open(SrcDest, Mode, Stream, []).
open(SrcDest, Mode, Stream, Options) :-
% get the relevant options and open the file

在这里,可以使用像library(option)这样的库来获取相关选项,

例如可以使用:
?- option(bar(X), [foo(1), bar(2), baz(3)]).
X = 2.

因此,这就是传递命名参数的方法。

@false在回答中没有提到的另一件事:在Prolog中,您可以执行以下操作:

Goal = reverse(X, Y), X = [a,b,c], Y = [c,b,a]

在稍后的某个时候:

call(Goal)

甚至

Goal

换句话说,我认为将参数作为列表传递而不是仅将目标作为术语传递的意义不大。参数在什么时候是一个列表,为什么它们被打包到一个列表中?

换句话说:考虑到call的工作原理,通常不需要解压缩列表[X, Y, Z]X, Y, Z,然后您可以将其用作参数列表。就像在对您的问题的评论中一样,这些都很好:

call(reverse, [a,b,c], [c,b,a])

call(reverse([a,b,c]), [c,b,a])

call(reverse([a,b,c], [c,b,a]))

最后一个与

Goal = reverse([a,b,c], [c,b,a]), Goal

这就是为什么你可以做这样的事情:

?- maplist(=(X), [Y, Z]).
X = Y, Y = Z.

而不是写:

?- maplist(=, [X,X], [Y, Z]).
X = Y, Y = Z.

相关内容

  • 没有找到相关文章

最新更新