[squeak-dev] A question about block closures.

Eliot Miranda eliot.miranda at gmail.com
Wed Jul 8 18:30:53 UTC 2009


On Wed, Jul 8, 2009 at 11:13 AM, David Goehrig <dave at nexttolast.com> wrote:

>
>
> On Wed, Jul 8, 2009 at 12:55 PM, Eliot Miranda <eliot.miranda at gmail.com>wrote:
>>
>> Well the obvious way to clean up those closures is to pass the self
>> reference as an argument, so
>>
>> (An object named: #Casper) has: #greets: of: [ :theSelf :x | Transcript
>> show: 'Hi ', x name , '! My name is ', theSelf name; cr].
>>
>
> That's an even worse hack. :)
>

I disagree :)  Reaching into a closure's home in a completely unthread-safe
manner is a horrible hack.  Using closures to implement properties is an
implementation detail and one is free to compile to those closures as one
sees fit.  Better to make the soft binding explicit.

But I guess (your original message wasn't clear on the subject) that what
you do when you want to reuse one of these closures is that you copy the
closure and its enclosing MethodContext (remember this is a chain and blocks
could be nested) and assign the new receiver in the copy.  That's not too
bad but its still very heavyweight because you're not sharing code between
instances.



>  doesNotUnderstand: aMessage
>
>>  "Generic catch all that performs all selectors"
>> (self can: aMessage selector) ifTrue:
>> [^( self s: aMessage selector ) valueWithEffectiveReceiver: self
>> andEnoughArguments: aMessage arguments ].
>>  ^ self s: aMessage selector.
>>
>
> I take it you'd have to define
> #valueWithEffectiveReceiver:andEnoughArguments: as BlockClosure has no such
> beast.  If  the closure was promoted to a CompiledMethod, then I guess you could use #valueWithReceiver:arguments: and
> another patched Array.  Or did I miss something?
>

No, that's it.  You could also write it as
    ^self evaluate: ( self s: aMessage selector ) withEffectiveReceiver:
self andEnoughArguments: aMessage arguments
and have the extension in your framework not on BlockClosure.
And of course your suggestion with CompiledMethod would work.


>  As regards more generic property handling I don't know of a better way
> than the doesNotUnderstand: handler for handling properties held in
> per-instance dictionaries if the constraint is that you definitely don't
> want to compile accessors for the property and you are using the vanilla VM.
>
> I figured the dNU approach was close enough to what Morphic did, that it
> was "good enough".  But I was surprised how
> weird the code got.
>
> But methods are cheap and so I don't see the benefit of avoiding methods in
>> favour of blocks.
>>
>
> It largely has to do with not being able to get methods to actually work :)
>  I originally was trying to patch in CompiledMethods but ran into too many
> of the blowing up in bizarre ways, and the semantics drifting too far
> from the JS version of the API.
>
>   Vassili came up with the great idea of generating bytecode for slot
>> accessors directly and minting a set of 256 accessors that traversed the
>> parent chain in a loop.  Effectively each accessor method looked like
>>
>> accessSlot0
>>     | object |
>>     object := self.
>>     [object slot0 ifNotNil: [:value| ^value].
>>      (object := object parentSlot) ~~ nil] whileTrue.
>>     ^#undefined
>>
>
> I have a OO Forth that does the exact same thing, except it rolls native
> x86 machine code :)
>

Cool :)  But note that the JIT does produce x86 code for you so at the metal
there's not a lot of difference :)



>  Both Claus Gittinger and Dan Ingalls have had the idea of creating an
> object that is an instance of itself.  One way, without VM mods (and
> ignoring issues with compact classes), is to do something like
>
>>
>> prototype: aPrototype numNewSlots: numNewSlots
>>     | format object |
>>     object := (Array new: aPrototype numberOfSlots + numNewSlots + 3).
>>     object
>>          at: 1 "superclass" put: aPrototype;
>>          at: 2 "methods"    put: MethodDictionary new;
>>          at: 3 "format"       put: (self formatOf: aPrototype format
>> withAdditionalSlots: numNewSlots).
>>    object changeClassTo: object.
>>    ^object
>>
>
> I did something similar with another project, but I've found doing the deep
> copies on the MethodDictionary ends up
> failing in weird ways.
>

But you don't need to copy the MethodDictionaries.  With the above approach
they're shared/inherited.  So when a message is sent to a subinstance the
lookup machinery will follow the prototype chain until it finds a method or
triggers dNU.  In the activation self is bound to the original receiver.
 The issue is hence making sure that slot layouts in subinstances match
their parents so that parent methods work correctly on subinstances.  But
that's not a new problem, Smalltalk does exactly that :)



>  Combine one with the other and you have the potential for a lean and mean
> prototype-based system using the existing VM technology, which would mean an
> efficient JavaScript implementation within Smalltalk.
>
> I guess I know what the next set of experiments I'm going to do are :)
>
> Thanks Eliot for thinking through this with me.
>
> The main reason I'm building this, is I've got this very fluid ad hoc
> Javascript editing environment I wrote that I'm trying to port to Squeak.
>  I've been writing a book on programming that runs the reader through the
> process of designing a simple 8bit CPU, that has been implemented as step by
> step drag and drop examples on top of it.
>
> The only problem is that the only JS + HTML5 implementation out there in
> the wild that can actually handle it is Safari, and I can't bundle that with
> the book :)
>
> If I can get it ported to Squeak, I can add an additional appendix and give
> the code listings in both Smalltalk and Javascript.  But I want the code to
> have direct analogues, so the translations of concepts between languages are
> clear.
>

Please keep me in the loop.  This is interesting and I'm happy to review.

cheers
Eliot


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


More information about the Squeak-dev mailing list