|
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
[Prev in Thread] | Current Thread | [Next in Thread] |