因为Prolog使用按时间顺序回溯(来自Prolog维基百科页面)甚至在找到答案后(在这个例子中只能有一个解决方案),这是否可以证明Prolog是否可以使用热切的评估?
mother_child(trude, sally).
father_child(tom, sally).
father_child(tom, erica).
father_child(mike, tom).
sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).
parent_child(X, Y) :- father_child(X, Y).
parent_child(X, Y) :- mother_child(X, Y).
使用以下输出:
?- sibling(sally, erica).
true ;
false.
答案 0 :(得分:7)
总结下面与@WillNess的讨论,是,Prolog是严格的。但是,Prolog的执行模型和语义与通常标记为严格或非严格的语言有很大不同。有关此内容的更多信息,请参见下文。
我不确定这个问题是否真的适用于Prolog,因为它并没有真正具有其他语言所具有的隐式评估顺序。如果这在Haskell这样的语言中发挥作用,你可能会有一个表达式:
f (g x) (h y)
在像ML这样的严格语言中,有一个定义的评估顺序:g x
将被评估,然后是h y
,f (g x) (h y)
最后。在像Haskell这样的语言中,g x
和h y
只会根据需要进行评估(“非严格”比“懒惰”更准确)。但是在Prolog中,
f(g(X), h(Y))
具有相同的含义,因为它没有使用函数表示法。该查询将分为三个部分g(X, A)
,h(Y, B)
和f(A,B,C)
,这些成分可以按任何顺序放置。评估策略是严格的,因为序列中较早出现的内容将在接下来的内容之前进行评估,但在没有严格意义上它是不严格的要求在评估开始之前将变量实例化为基础术语。统一是完美的内容,无需给出每个变量的值。我提出这个问题是因为你必须将另一种语言中复杂的嵌套表达式分解为Prolog中的几个表达式。
答案 1 :(得分:5)
Prolog在给出问题的几个正确答案之后暂停,与懒惰无关;它是其用户交互协议的一部分。每个答案都是急切地计算出来的。
有时只会有一个答案,但Prolog事先并不知道,所以等待我们按;
继续搜索,希望找到另一个解决方案。有时候它能够提前推断出来并立即停止,但有时只会停止。
更新
Prolog本身没有评估。所有术语都未被评估,就像在Lisp中“引用”一样。
Prolog将以书面形式展开您的谓词定义,并且非常乐意让您的数据结构充满未经评估的未经实例化的漏洞,如果您的谓词定义需要这样做的话。
Haskell在请求输出时不需要任何值,用户。
同样,Prolog根据用户要求逐个生成解决方案。
Prolog甚至可以被看作比Haskell更懒惰,其中所有算术都是严格的,即立即,而在Prolog中你必须明确地请求算术评估,is/2
。
所以也许这个问题是不合适的。 Prolog的运营模式只是太不同。一个人没有“结果”或“功能”;但从另一个角度来看,一切都是结果,谓词是“多功能”。
答案 2 :(得分:3)
目前看,问题在于它的陈述是不正确的。按时间顺序回溯并不意味着 Prolog必须回溯“在一个只有一个解决方案的例子中”。
考虑一下:
foo(a, 1).
foo(b, 2).
foo(c, 3).
?- foo(b, X).
X = 2.
?- foo(X, 2).
X = b.
所以这是一个只有一个解决方案的例子,而Prolog认识到这一点,并且不会尝试回溯。在某些情况下,您可以通过Prolog将无法识别只有一个逻辑解决方案的方式实现问题的解决方案,但这是由于实现而不是Prolog执行所固有的模型。
您应该阅读Prolog的执行模型。从您似乎引用的Wikipedia article,“操作上,Prolog的执行策略可以被认为是其他语言中函数调用的一般化,一个区别在于多个子句头可以匹配给定的调用。 In那个案例, [强调我的]系统创建一个选择点,用第一个选择的子句头统一目标,并继续第一个选择的目标。“阅读Sterling和Shapiro的“Prolog的艺术”,对该主题进行更全面的讨论。
答案 3 :(得分:3)
在急切的评估中,只要表达式绑定到变量,就会对其进行求值。
然后我认为有两个级别 - 在用户级别(我们的谓词)Prolog并不急切。 但它处于“系统”级别,因为变量尽可能高效地实现。
实际上,属性变量实现为惰性,而且与'逻辑'Prolog变量相当“正交”。