2015-12-13 22 views
2

我学习Prolog的,我尝试重写univ断言:使用的findall与ARG

?- 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

'findall/3' *拷贝*变量。要恢复原始绑定,可以将子条目与所有变量一起复制(请参阅'term_variables/2'),然后统一公共变量,从而还原原始子条目。 – mat

回答

2

正如@mat所指出的,findall/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]. 

此不同的行为WRT的findall/3和SETOF/3也非常有用:您可以使用bagof/3来代替。

+0

完美!非常感谢! – Julien