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
|