产量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)
是否有可能使用单线程实现,避免多线程导致很多复杂性?
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
谢谢伯特!我已经检查过了,发生器类仍然在Pharo中。 –
这是一个有趣的话题,但是为了让它成为主题,所以你至少应该提供一个例子来展示你想要翻译成Smalltalk的代码。 –
我记得有一个非常旧的Smalltalk版本(我认为它是在Smalltalk/V中),那里有一个Prolog编译器,你可以在一个类中定义它应该用它来编译它的方法。 –
@ CarlosE.Ferro如果我记得正确的话,在Squeak里面也有一个Prolog。 –