List Info

Thread: Defining methods within a block




Defining methods within a block
country flaguser name
United States
2007-11-12 03:38:29
Hello Smalltalkers,

I've been trying to immerse myself in Smalltalk for a
project I'm
working on, so I've been dabbling in the reflective and
introspective
capabilities of the GNU Smalltalk system.  I've written a
method for
Object that mimics Ruby's "Object-specific class"
feature (if you're
not familiar with it, here's a pretty good explanation:
http://www.ruby-doc.org/docs/ProgrammingRuby/ht
ml/classes.html#UB), and
here it is, along with some example usage code:

!Object methodsFor: 'my methods'!
objectSpecificMethod: aMethod
    | klass className newClassName |

    klass := self class.
    className := klass name.
    newClassName := className , '_1'. "This will have
to be changed"
    klass subclass: (newClassName asSymbol)
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: (klass category).
    (Smalltalk at: (newClassName asSymbol)) compile:
aMethod.
    self changeClassTo: (Smalltalk at: (newClassName
asSymbol)).
    ^self.
! !

|obj|
obj := Foo new: 1 next: 2 last: 3.
Transcript print: (obj doStuff: 6); cr.
obj objectSpecificMethod: '
doStuff: arg
    ^(three + arg).
'.
Transcript print: (obj doStuff: 6); cr.

My question is this:  Instead of providing
Object#objectSpecificMethod
a string, would it be possible to provide it a block?  How
would one
define a method within a block?  I tried

obj objectSpecificMethod: [
doStuff: arg
  ^(three + args).
].

but that generates a syntax error.  Please let me know what
you think.

Thanks,
Rob Hoelz


_______________________________________________
help-smalltalk mailing list
help-smalltalkgnu.org

http://lists.gnu.org/mailman/listinfo/help-smalltalk

Re: Defining methods within a block
country flaguser name
Switzerland
2007-11-12 03:59:59
> 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


_______________________________________________
help-smalltalk mailing list
help-smalltalkgnu.org

http://lists.gnu.org/mailman/listinfo/help-smalltalk

[1-2]

about | contact  Other archives ( Real Estate discussion Medical topics )