将findall与arg一起使用

时间:2015-12-13 15:18:55

标签: prolog

我正在学习Prolog,我尝试重写univ谓词:

?- foo(hello, X) =.. List.
List = [foo, hello, X]

?- Term =.. [baz, foo(1)].
Term = baz(foo(1))

我已经写了一个效果很好的第一个版本:

get_args(_, Arity, Arity, []).
get_args(T, Arity, N, [Arg|Args]) :-
    I is N + 1,
    arg(I, T, Arg),
    get_args(T, Arity, I, Args).

univ(T, [Functor|Args]) :-
    length(Args, Arity),
    functor(T, Functor, Arity),
    get_args(T, Arity, 0, Args),
    !

我想尝试另一种方式来实现它。所以,我使用findallarg重写了这个:

univ(T, [Functor|Args]) :-
    length(Args, Arity),
    functor(T, Functor, Arity),
    findall(Arg, arg(_, T, Arg), Args),
    !.

这个效果不好。这是一个例子:

?- univ(a(C, D, E), L).
L = [a, _G1312, _G1315, _G1318].
?- univ(T, [a, C, D, E]).
T = a(_G1325, _G1326, _G1327).

因此,我有一个简单的问题:是否可以将argfindall一起使用以检索每个参数的名称?

1 个答案:

答案 0 :(得分:2)

如@mat所述,findall / 3拷贝变量。您可以使用bagof / 3代替:

univ(T, [Functor|Args]) :-
    length(Args, Arity),
    functor(T, Functor, Arity),
    bagof(Arg, I^arg(I, T, Arg), Args),
    !.

?- univ(a(C, D, E), L).
L = [a, C, D, E].

当你需要处理属性变量时,找到allall / 3和setof / 3的这种不同行为也很有用。