我在要求我在 Prolog中实现经典的arg谓词的练习中遇到了一些麻烦。
arg(?Arg, +Term, ?Value)
其中 Arg 是 Term 参数列表中参数的索引。值它是这个参数的值。
例如:
arg(1, t(f(X),Y,a), Value)
Value = f(X).
因为 f(x) 它是 t 主函子的参数列表中的第一个参数。
所以我试图以这种方式使用 univ =.. 谓词来解决练习:
argom(ArgIndex,Term,ValueArg):- Term =.. [_|ArgsList],
element_n(ArgIndex,ArgsList,ValueArg).
element_n(1,[ValueArg,_],ValueArg).
element_n(N,[_,Tail],ValueArg):- N1 is N-1,
element_n(N1,Tail,ValueArg).
其中argom关系是我个人对内置谓词arg的实现......
问题是解决方案不起作用......这个想法是我有一个argom谓词:
- ArgIndex:我将获得的参数的索引。
- 术语是一个表达式,如:f(a,b,c)
- ValueArg:表示以ArgIndex为索引的参数的值
所以,如果我有f(a,b,c)作为Term并且ArgIndex是 1,那么ArgValue必须是a。
我使用unive内置谓词,从我的Term创建一个列表,其中头部是我的Term的主要仿函数,尾部(名为ArgsList)是主要仿函数的参数列表。
我将使用第 n 个参数,因此我将使用 ArgsList 中的第 n 个元素并获得它,我定义了element_n关系:ArgIndex、ArgsList、ValueArg。
如果我希望列表中的第一个元素ArgIndex值为 1 并且基本情况匹配:
element_n(1,[ValueArg,_],ValueArg).
所以 ValueArg 在我的 ArgsList 参数列表的头部并统一它。
否则调用规则获取ArgsList中的第n个元素
问题是,当我咨询它不起作用时,答案总是:如果我尝试获取第一个元素也会失败(这是我使用基本案例规则的最简单情况)
查看跟踪我有同样的情况:
[trace] 9 ?- argom(1,f(a,b,c),a).
Call: (6) argom(1, f(a, b, c), a) ? creep
Call: (7) f(a, b, c)=..[_G3148|_G3149] ? creep
Exit: (7) f(a, b, c)=..[f, a, b, c] ? creep
Call: (7) element_n(1, [a, b, c], a) ? creep
Fail: (7) element_n(1, [a, b, c], a) ? creep
Fail: (6) argom(1, f(a, b, c), a) ? creep
false.
因此,它调用 argom 规则对它说:“主函子的第一个参数是 a 是真的吗?”
它以正确的方式使用univ =..内置谓词从我的 Term f(a, b, c)生成列表[f, a, b, c]
现在它调用element_n谓词,这是基本情况,因此必须将ValueArg与列表的头部统一,但随后失败
我也尝试过问:如果 ArgIndex 值为 1 且 Term 为 f(a,b,c),ValueArg 的值是多少?
[trace] 10 ?- argom(1,f(a,b,c),ValueArg).
Call: (6) argom(1, f(a, b, c), _G3483) ? creep
Call: (7) f(a, b, c)=..[_G3553|_G3554] ? creep
Exit: (7) f(a, b, c)=..[f, a, b, c] ? creep
Call: (7) element_n(1, [a, b, c], _G3483) ? creep
Fail: (7) element_n(1, [a, b, c], _G3483) ? creep
Fail: (6) argom(1, f(a, b, c), _G3483) ? creep
false.
所以很明显,问题在于将列表的头部与此规则中的 ValueArg 统一起来似乎有些问题:
element_n(1,[ValueArg,_],ValueArg).
为什么?