我正在学习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),
!
我想尝试另一种方式来实现它。所以,我使用findall
和arg
重写了这个:
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).
因此,我有一个简单的问题:是否可以将arg
与findall
一起使用以检索每个参数的名称?
答案 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的这种不同行为也很有用。