help-smalltalk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-smalltalk] Defining methods within a block


From: Paolo Bonzini
Subject: Re: [Help-smalltalk] Defining methods within a block
Date: Mon, 12 Nov 2007 10:59:59 +0100
User-agent: Thunderbird 2.0.0.6 (Macintosh/20070728)


My question is this:  Instead of providing Object#objectSpecificMethod
a string, would it be possible to provide it a block?

Yes, but it is not in the basic class library. You can define a subclass of CompiledMethod that will forward the message to a block. Something like this (I'm using 2.95x syntax; if you have an older version as I think, it will be easy to convert it to the old syntax; or it will whet your appetite so you'll download the latest version and compile it).

CompiledMethod subclass: MethodBlock [
    | closure |
    MethodBlock class >> on: aBlock [
        ^(self numArgs: aBlock numArgs) closure: aBlock
    ]
    closure: aBlock [
        closure := aBlock
    ]
    valueWithReceiver: anObject withArguments: args [
        ^closure valueWithArguments: args
    ]
]

Behavior subclass: ObjectSpecificBehavior [
    Behavior >> isObjectSpecific [ ^false ]
    isObjectSpecific [ ^true ]
]

Object extend [
    implantObjectSpecificBehavior [
        | subclass |
        self class isObjectSpecific ifFalse: [
            subclass := ObjectSpecificBehavior new.
            subclass superclass: self class.
            self changeClassTo: subclass ]
    ]

    objectSpecificMethod: aString [
        self implantObjectSpecificBehavior.
        self class compile: aString
    ]

    objectSpecificMethod: selector do: aBlock [
        self implantObjectSpecificBehavior.
        self class
            addSelector: selector
            withMethod: (MethodBlock on: aBlock )
    ]
]

| obj |
obj := 1 to: 20.
obj
    objectSpecificMethod: #every:
    do: [ :n | obj atAll: (n to: obj size by: 3) ].
(obj every: 3) printNl "(3 6 9 12 15 18 )"


As you can see from the example, blocks don't have access to "self" and instance variables available. This is by design. In Ruby, @abc syntax is resolved at run-time, while in Smalltalk it is resolved at compile-time (you need to know the list of instance variables at compile-time). On the other hand, 99% of the time you can access self from the enclosing environment ("obj" in the example), and you gain the possibility to access the enclosing environment's "self" and instance variables.

Paolo




reply via email to

[Prev in Thread] Current Thread [Next in Thread]