When is a closure a real one? [was: Real closures]
Klaus D. Witzel
klaus.witzel at cobss.com
Mon Oct 9 10:54:53 UTC 2006
Thank you master for making this crystal clear!
I think that distiguishing block locals and also scope of locals could
have been solved by the old (current) compiler+decompiler, but for the
rest I don't think so.
/Klaus
On Mon, 09 Oct 2006 12:13:15 +0200, Marcus Denker wrote:
>
> On 08.10.2006, at 10:51, Klaus D. Witzel wrote:
>
>> Thank you Mathieu and Phillipe for you pointers and example.
>>
>> Just out of curiosity (and as input for writing accurate yes/no test
>> cases :) let me ask what is expected by the community (apologies if
>> this sounds like a silly question ;-) when is a closure a real one:
>>
>> 1] after #fixTemps (or equivalent)
>
> no, fixtemps just copies the home context.
>
> Here is a quote from a mail that I send someone to explain this:
>
> ==============
>
> This brings some of the properties of a closure, but not all. In a way,
> it's too much.
>
> blocks1 := (1 to: 10) collect: [:ea | [ea]].
> blocks1 collect: [:each | each value]
>
> If you execute this in VW, you get #(1 2 3 4 5 6 7 8 9 10). But in
> Squeak, the :ea
> is just a temp in the method, so the blocks all reference the same
> variable. Thus you get #(10 10 10 10 10 10 10 10 10 10)
>
> Now that is sometimes really not what you like, so they implemented a
> hack (they are good at that!) called "fixTemps":
>
> blocks1 := (1 to: 10) collect: [:ea | [ea] fixTemps].
> blocks1 collect: [:each | each value]
>
> fixTemps
> "Fix the values of the temporary variables used in the block
> that are
> ordinarily shared with the method in which the block is defined."
>
> home _ home copy.
> home swapSender: nil
>
>
> Of course, this does not give you Closure semantics, too, as this now
> makes one new environment per block for all temps of the block...
> whereas with
> Closures, this is not always the case, e.g. when referencing outer
> temps:
>
> |a|
> a := 1.
> b1 := [a].
> b2 := [a] fixTemps.
> a := 3.
> b1 value + b2 value
>
> is Wrong: The fixTemps makes the a in b2 it's own variable, but even
> with Closures, it's the a of the method itself.
>
> Another aspect is that Block Locals like [ | a | ] are from the code
> that is generated indistiguishable from having the | a | defined as
> temps of the method.
>
> myMethod
> | a |
> [a].
>
> same as
>
> myMethod
> [ | a | a]
>
> Some versions ago, Lex Spoon at least fixed the compiler to not
> allow you to reference the block locals and arguments outside the
> block. which was perfectly ok before. But nevertheless, the semantics
> of scoping is Wrong:
>
> tt2
> | a b |
> a := [ | t | t := 1].
> b := [ | t | t ].
> a value.
> ^b value.
>
> returns 1, even if each block defines their own (new, completely
> different) t.
>
> ===================
>
>>
>> 2] after #blockCopy: (is this equivalent to 1?)
>>
>
> blockCopy: is the way to do generate BlockContexts in Squeak. No
> Clusures.
> Not equivalent to 1).
>
> blockCopy: numArgs
> "Primitive. Distinguish a block of code from its enclosing method by
> creating a new BlockContext for that block. The compiler inserts into
> all
> methods that contain blocks the bytecodes to send the message
> blockCopy:. Do not use blockCopy: in code that you write! Only the
> compiler can decide to send the message blockCopy:. Fail if numArgs is
> not a SmallInteger. Optional. No Lookup. See Object documentation
> whatIsAPrimitive."
>
> <primitive: 80>
> ^ (BlockContext newForMethod: self home method)
> home: self home
> startpc: pc + 2
> nargs: numArgs
>
>
>> 3] after #createBlock: (is this equivalent to 1? to 2?)
>>
>
> This gets you a real closure block (this is from the newcompiler's
> runtime):
>
> createBlock: env
>
> ^ BlockClosure new
> env: env;
> method: self
>
>
> So: old compiler generates code with 2, people add 1 by hand (randomly,
> as
> bugs show up). Newcompiler generates code with 3, 1 is not needed
> anymore.
>
>
> Marcus
>
>
>
>
More information about the Squeak-dev
mailing list
|