[squeak-dev] A question about block closures.

Eliot Miranda eliot.miranda at gmail.com
Wed Jul 8 06:04:31 UTC 2009


On Tue, Jul 7, 2009 at 3:58 PM, David Goehrig <dave at nexttolast.com> wrote:

> Dear Squeakers,
> I have a question for some of Squeak gurus on the list.  I've been porting
> a javascript project I did a couple months back to Squeak, and in the
> process of porting it, added an ad hoc object class that handled the
> prototype based inheritance I used in the javascript version.
>
> One of the issues I encountered was that when I did a copy of my object,
> the block closures supplied for various properties required a bit of a hack
> so I have a method:
>
> doesNotUnderstand: aMessage
> "Generic catch all that performs all selectors"
> (self can: aMessage selector) ifTrue: [
>  (self s: aMessage selector ) outerContext receiver: self.
> ^( self s: aMessage selector )valueWithEnoughArguments: aMessage arguments
> ].
>  ^ self s: aMessage selector.
>
> Now this seems to do exactly what I wanted 99% of the time.  It mimics the
> behavior of using a block closure as a javascript function() {} object, and
> all other objects are returned as intended.  The #s: method returns nil if
> the property is not found in the object's dictionary as well, and #can: is
> just a fancy way to test if the property is a block
> closure.  By using valueWithEnoughArguments: it even gets padded out with nils like JS would.
>
>
> I'm not entirely happy with how hackish this seems, patching the outerContext and then re-rolling the arguments array to one of the proper size just to copy into a MethodContext.
>
> My question is "Is there a better way?"
>

You could do something analogous with messages and methods an d have the Vm
associate the receiver with the activation in... a message send :)
If you had a dictionary that cached translations form short forms of
selectors, e.g. myJSFunc:with: -> myJSFunc:with:with: then your code might
look something like

doesNotUnderstand: aMessage
"Generic catch all that performs all selectors"
(self can: aMessage selector) ifTrue:
[actualSelector := self s: aMessage selector.
^self perform: actualSelector
withArguments: (aMessage arguments, (Array new: actualSelector numArgs -
aMessage selector numArgs))]

Would this be better?

You can then adapt this pattern and compile adaptors on the fly to something
like

doesNotUnderstand: aMessage
"Generic catch all that performs all selectors"
(self can: aMessage selector) ifTrue:
[self compile: (self adapt: aMessage selector to: (self s: aMessage
selector) classified: #'message adaptors'.
^self perform: aMessage selector withArguments: aMessage arguments

or

doesNotUnderstand: aMessage
"Generic catch all that performs all selectors"
(self can: aMessage selector) ifTrue:
[self compileAdaptorFor: aMessage selector to: (self s: aMessage selector).
^self perform: aMessage selector withArguments: aMessage arguments

so the doesNotUnderstand: would be invoked first-time only (echos of the
Borning-Ingalls multiple inheritance implementation). adapt:to: would return
the text of a method that supplied nils for missing arguments (note it is
pretty trivial to add default values with this pattern). Decorate the method
with a pragma to mark it as auto-generated, e.g. adapt: #myMessage: to:
#myMessage:with: might answer
'myMessage: arg1
<adaptorFor: #myMessage:with:>
^self myMessage: arg1 with: nil'

Then you can easily flush generated adaptors (e.g. before writing out an MC
package, could also merely use the category to corral adaptors).

Yes?

best
Eliot

>
> Dave
>
> --
> -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20090707/a2aacb72/attachment.htm


More information about the Squeak-dev mailing list