Smalltalk的Prolog自适应

Smalltalk的Prolog自适应,prolog,smalltalk,yield,Prolog,Smalltalk,Yield,如何将中描述的方法应用于Pharo Smalltalk Smalltalk中是否存在类似于产量和生成函数的函数 对于start,我应该如何使用消息传递从重写代码: 使用产量的发生器函数: 类统一变量: 定义初始化(自): self.\u isBound=False def统一(自身,参数): 如果不是自绑定的: 自身值=arg self.\u isBound=True 假屈服 #拆下绑定。 self.\u isBound=False elif self.\u值==arg: 产生错误 def

如何将中描述的方法应用于Pharo Smalltalk

Smalltalk中是否存在类似于产量和生成函数的函数

对于start,我应该如何使用消息传递从重写代码:

  • 使用产量的发生器函数:
类统一变量:
定义初始化(自):
self.\u isBound=False
def统一(自身,参数):
如果不是自绑定的:
自身值=arg
self.\u isBound=True
假屈服
#拆下绑定。
self.\u isBound=False
elif self.\u值==arg:
产生错误

def personWithUnify(个人):
对于l1本人,统一(“切尔西”):
假屈服
对于l1本人,统一(“希拉里”):
假屈服
对于l1本人,统一(“法案”):
产生错误

def main():
打印(“名称使用UnifyingVariable:”)
Person=UnifyingVariable()
对于l1中的personWithUnify(个人):
打印(个人值)


是否可以使用单线程实现,避免多线程导致大量复杂性?

Squeak Smalltalk有一个
生成器
类,带有
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:
之前的所有代码,但回答第一个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中实现的,所以解决这个问题也相对容易。请参阅发布在上的变更集

通过该更改,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实现是否与Squeak的实际Prolog一样高效。你应该看看:

Squeak Smalltalk有一个
生成器
类,它有一个
收益率:
方法(如果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:
之前的所有代码,但回答第一个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中实现的,所以解决这个问题也相对容易。请参阅发布在上的变更集

通过该更改,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实现是否与Squeak的实际Prolog一样高效。您应该看一下:

这是一个有趣的主题,但要使其成为主题,您至少应该提供一个示例,显示您希望转换为Smalltalk的代码。我记得Smalltalk的一个非常旧的版本(我认为它是在Smalltalk/V中),其中有一个Prolog编译器,你可以在一个类中定义它应该使用它来编译它的方法。@CarlosE.Ferro如果我没记错的话,Squeak里面也有一个Prolog。这是一个有趣的话题,但要使其成为主题,您至少应该提供一个示例,显示您希望翻译为Smalltalk的代码。我记得Smalltalk的一个非常旧的版本(我认为它在Smalltalk/V中),其中有一个Prolog编译器,你可以在一个类中定义它应该使用它来编译它的方法。@CarlosE.Ferro如果我没记错的话,Squeak里面也有一个Prolog。谢谢Bert!我已经检查过了,
生成器
类仍然在Pharo中。谢谢你,伯特!我已经检查过了,
生成器
类仍然在Pharo中。