When is a closure a real one? [was: Real closures]

J J azreal1977 at hotmail.com
Mon Oct 9 19:39:58 UTC 2006


+1.  Great email.  Thanks.


>From: "Klaus D. Witzel" <klaus.witzel at cobss.com>
>Reply-To: The general-purpose Squeak developers 
>list<squeak-dev at lists.squeakfoundation.org>
>To: squeak-dev at lists.squeakfoundation.org
>Subject: Re: When is a closure a real one? [was: Real closures]
>Date: Mon, 09 Oct 2006 12:54:53 +0200
>
>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