产量Prolog适用于Smalltalk

问题描述:

如何使http://yieldprolog.sourceforge.net中描述的方法适应Pharo Smalltalk?产量Prolog适用于Smalltalk

是否存在类似于Smalltalk中的yield和generator函数?

对于开始,应该怎么重写代码从Tutorial1与消息传:

  • 发电机功能使用收率:

class UnifyingVariable: def __init__(self): self._isBound = False def unify(self, arg): if not self._isBound: self._value = arg self._isBound = True yield False # Remove the binding. self._isBound = False elif self._value == arg: yield False

def personWithUnify(Person): for l1 in Person.unify("Chelsea"): yield False for l1 in Person.unify("Hillary"): yield False for l1 in Person.unify("Bill"): yield False

def main(): print("Names using UnifyingVariable:") Person = UnifyingVariable() for l1 in personWithUnify(Person): print(Person._value)

是否有可能使用单线程实现,避免多线程导致很多复杂性?

+0

这是一个有趣的话题,但是为了让它成为主题,所以你至少应该提供一个例子来展示你想要翻译成Smalltalk的代码。 –

+0

我记得有一个非常旧的Smalltalk版本(我认为它是在Smalltalk/V中),那里有一个Prolog编译器,你可以在一个类中定义它应该用它来编译它的方法。 –

+0

@ CarlosE.Ferro如果我记得正确的话,在Squeak里面也有一个Prolog。 –

Squeak Smalltalk有Generator类和yield:方法(如果Pharo没有删除它,那么它应该仍然存在)。

在Smalltalk中,yield不像其他语言那样是关键字,但在Smalltalk中实现。它使用单个线程和协程(操作执行上下文)。

这里的第一个例子从YieldProlog:

personWithReturnValue := Generator on: [ :g | 
    g yield: 'Chelsea'. 
    g yield: 'Hillary'. 
    g yield: 'Bill' ]. 

Transcript cr; show: 'Names using a return value:'. 
personWithReturnValue do: [ :p | 
    Transcript cr; show: p ]. 

只要生成器是副作用自由,它可以精确地用作其他语言。

但是,YieldProlog在统一其变量时依赖于副作用。不同的是,在Squeak中,代码直到下一个yield:立即执行。也就是说,创建生成器时,所有代码将被执行,直到第一个yield:。在第一个next调用它执行所有的代码,直到第二个yield:,但回答第一个收益的价值。等等。这是因为发生器可以检测何时停止执行(因为它是Stream的子类,并且需要支持其接口atEnd)。

这意味着你必须在产量之后产生的副作用。例如。第二YieldProlog例如这个作品:

Object subclass: #SimpleVariable 
    instanceVariableNames: '_value' 
    classVariableNames: '' 
    poolDictionaries: '' 
    category: 'YieldProlog'. 

SimpleVariable createInstVarAccessors. 

personWithSimpleVariable := [ :person | 
    Generator on: [ :g | 
     g yield: false. 
     person _value: 'Chelsea'. 

     g yield: false. 
     person _value: 'Hillary'. 

     g yield: false. 
     person _value: 'Bill' ] ]. 

Transcript cr; show: 'Names using a SimpleVariable:'. 
p := SimpleVariable new. 
(personWithSimpleVariable value: p) do: [ :l1 | 
    Transcript cr; show: p _value ]. 

但总的来说这使得它很难正确地实现YieldProlog。现在,由于Generator在Smalltalk中实现,所以解决这个问题也相对容易。看到变更张贴在http://forum.world.st/Generators-td4941886.html

随着这种变化,在UnifyingVariable示例工作:

Object subclass: #UnifyingVariable 
    instanceVariableNames: '_value _isBound' 
    classVariableNames: '' 
    poolDictionaries: '' 
    category: 'YieldProlog'. 

UnifyingVariable createInstVarAccessors. 

UnifyingVariable compile: 'unify: arg 
    ^Generator on: [ :g | 
     _isBound = true 
      ifFalse: [ 
       _value := arg. 
       _isBound := true. 
       g yield: false. 
       "Remove the binding". 
       _isBound := false ] 
      ifTrue: [ 
       _value = arg 
        ifTrue: [ g yield: false ] ] ]'. 

personWithUnify := [ :person | 
    Generator on: [:g | 
     (person unify: 'Chelsea') do: [ :l1 | 
      g yield: false ]. 
     (person unify: 'Hillary') do: [ :l1 | 
      g yield: false ]. 
     (person unify: 'Bill') do: [ :l1 | 
      g yield: false ] ] ]. 

Transcript cr; show: 'Names using a UnifyingVariable:'. 
person := UnifyingVariable new. 
(personWithUnify value: person) do: [ :l1 | 
    Transcript cr; show: person _value ]. 

Transcript cr; show: 'Use unify to check a person:'. 
person := UnifyingVariable new. 
(person unify: 'Hillary') do: [ :l1 | 
    (personWithUnify value: person) do: [ :l2 | 
     Transcript cr; show: 'Hillary is a person.' ] ]. 
(person unify: 'Buddy') do: [ :l1 | 
    (personWithUnify value: person) do: [ :l2 | 
     "This won't print." 
     Transcript cr; show: 'Buddy is a person.' ] ]. 

这一切都这样说,我怀疑这YieldProlog实现是实际的Prolog佳乐高效。你应该看看这个:http://www.zogotounga.net/comp/squeak/prolog.htm

+0

谢谢伯特!我已经检查过了,发生器类仍然在Pharo中。 –