我想追加([],C,C),其中C是包含一些元素的列表。可能吗?如果其他条件为真,我将在包含元素的C中追加一些列表追加(Found,C,C)。 而且我想将C中的最终值存储到变量D中。我怎么能这样做?
答案 0 :(得分:2)
我想追加([],C,C),其中C是包含一些元素的列表。有可能吗?
append([],C,C)
永远是真的。一个空列表与任何东西相结合就是一切。看看Prolog在您尝试时所说的内容:
?- append([],C,C).
true.
这个没有任何绑定的true
告诉您Prolog建立了证明,但结果没有创建新的绑定。此代码具有相同的结果:
meaningless(_, _, _).
?- meaningless(everybody, X, Squant).
true.
这表明你的愿望是错位的。 append([], C, C)
不符合您的想法。
如果其他条件为真,我会在C中追加一些包含元素append(Found,C,C)的列表。而且我还希望将C中的最终值存储到变量D.我该怎么做?
根据"存储"进行思考和其他暗示可变状态的操作是一个肯定的迹象,表明你不了解Prolog。在Prolog中,您可以建立绑定(或将事实断言到动态存储中,这对于初学者来说是一个tar坑)。通过这样的方式可以以Prolog的方式实现类似的东西:
frob(cat, List, Result) :- append([cat], List, Result).
frob(dog, List, List).
这个谓词frob/3
有两个参数:一个原子和一个列表。如果原子是cat
,那么它会将[cat]
附加到列表的开头。您在子句头部的参数和它们在子句主体中的使用之间看到的线程是Prolog如何管理状态。基本上,Prolog中的所有状态都在调用堆栈或动态存储中。
举一个Python的例子,考虑这两种实现阶乘的方法:
def fac(n):
result = 1
while n > 1:
result = result * n
n = n - 1
此版本有一个变量result
,这是一种状态。我们在循环中反复变异状态以实现计算。虽然阶乘函数可以定义为fac(n)= n * fac(n-1),但是这个实现没有明确隐藏在代码中的fac(n-1)。
递归方法是:
def fac(n):
if n < 1:
return 1
else:
return n * fac(n-1)
这里没有明确的状态,那么计算如何运作?状态是隐含的,它是在堆栈上进行的。程序员往往会在递归时提出一个持怀疑态度的眉毛,但在Prolog中,没有assignable这样的东西,所以第一种方法不能使用。
回到frob/3
,条件隐含在第一个参数上。主体中的行为是不同的,因为在第一个主体中,第三个参数将绑定到append/3
调用的第三个参数,这将与附加到第二个参数的原子cat
的列表统一起来。参数List
。在第二个主体中,没有任何特殊情况会发生,第三个参数将与第二个参数绑定相同的值。因此,如果您要致电frob(Animal, List, Result)
,Result
将在前面与cat
绑定,或者不会根据Animal
的内容绑定。
不要混淆并认为Prolog只是将最后一个参数视为返回值!如果这是真的,那肯定不会这样:
?- frob(X, Y, [whale]).
X = dog,
Y = [whale].
这里似乎发生的事情是Prolog可以告诉我,因为列表不是以cat
开头,而是能够推断出X是dog
。好的Prolog程序员渴望在他们的API中维持这种错觉,但是这里真正发生的一切是Prolog进入第一条规则,扩展到append([cat], X, [whale])
然后统一失败,因为Prolog无法想出一个X,如果前面有[cat]
,则生成[whale]
。结果,它进入了第二个规则,它将X与dog
统一,并将第二个两个参数相互统一。因此Y = [whale]
。
我希望这有帮助!