What difference between this things. I know about Eliots post
describing closures in Squeak, but it's too massive and so special to understand. Thanks. -- Andrey Larionov _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
On Friday 10 April 2009 3:24:42 am Andrey Larionov wrote:
> What difference between this things. I know about Eliots post > describing closures in Squeak, but it's too massive and so special to > understand Briefly, A closure tracks the full computational state of its block. A block is a executable entity with zero or more parameters. It may also use variables from an outside scope. The parameters of the block are bound to the arguments given when the block is evaluated. But what about variables like i from an outer scope like in the example given by Bert a few weeks back : multiply := Array new: 4. 1 to: 4 do: [:i | multiply at: i put: [:x | x * i]. ]. (multiply at: 3) value: 5. When the block is evaluated, will it have the value it had at the time the block was created or at the time it was evaluated? The behavior is unspecified. It is an open question :-). In Squeak, i in the block will refer to the i in the do: block and the last statement will print 25 because i would be 5 when do: terminates. A closure maintains its own store for variables like i. At the time of creation, the local store is initialized with i. At the time of invocation, i will refer to this local copy, so the correct value of 15 will be printed. HTH .. Subbu _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
>>>>> "K" == K K Subramaniam <[hidden email]> writes:
K> In Squeak, i in the block will refer to the i in the do: block and the last K> statement will print 25 because i would be 5 when do: terminates. Not necessarily. I could see an implementation where i would be 4. -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc. See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
On 10.04.2009, at 05:48, Randal L. Schwartz wrote:
>>>>>> "K" == K K Subramaniam <[hidden email]> writes: > > K> In Squeak, i in the block will refer to the i in the do: block > and the last > K> statement will print 25 because i would be 5 when do: terminates. > > Not necessarily. I could see an implementation where i would be 4. And how exactly does that statement help a beginner to understand the distinction between a BlockContext and a BlockClosure? ;) Andrey: Both are pretty much the same, there is no change in syntax. Closures simply are Blocks Done Right. Try to run the example Subbu mentioned, and see if you would have expected the result or not. With closures it does what one would expect. - Bert - _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Thanks. I'l try to experiment with this example
On Fri, Apr 10, 2009 at 11:54, Bert Freudenberg <[hidden email]> wrote: > On 10.04.2009, at 05:48, Randal L. Schwartz wrote: > >>>>>>> "K" == K K Subramaniam <[hidden email]> writes: >> >> K> In Squeak, i in the block will refer to the i in the do: block and the >> last >> K> statement will print 25 because i would be 5 when do: terminates. >> >> Not necessarily. I could see an implementation where i would be 4. > > > And how exactly does that statement help a beginner to understand the > distinction between a BlockContext and a BlockClosure? ;) > > Andrey: Both are pretty much the same, there is no change in syntax. > Closures simply are Blocks Done Right. > > Try to run the example Subbu mentioned, and see if you would have expected > the result or not. With closures it does what one would expect. > > - Bert - > > > _______________________________________________ > Beginners mailing list > [hidden email] > http://lists.squeakfoundation.org/mailman/listinfo/beginners > Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Bert Freudenberg
>>>>> "Bert" == Bert Freudenberg <[hidden email]> writes:
>> Not necessarily. I could see an implementation where i would be 4. Bert> And how exactly does that statement help a beginner to understand the Bert> distinction between a BlockContext and a BlockClosure? ;) It doesn't. I was just pointing out a presumption about "the residual value of things after they go out of scope" and/or "ways to implement a loop". :-) -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc. See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In the original Smalltalk, blocks were almost but not quite closures.
The ANSII standard says they are closures. As far as I know, all the Smalltalks except Squeak make blocks be closures. So, changing the way Squeak implements blocks will bring it into compliance with the standard and more like other implementations of Smalltalk I first ran into the problem of blocks not being closures when I tried to write a program like (1 to: 100) do: [:each | [self process: each] fork] This will fork 100 processes. If the first spawned process (the one running [self process: 1]) starts to run right away, it will behave like I expect. But suppose the main thread creates all 100 processes before it gives up control. Then the value of "each" will be 100 and so all 100 processes will execute [self process: 100], which is not at all what I expect. If blocks were closures then each execution of the block would have its own context to store its argument, i.e. there would be 100 versions of "each". You can see a similar problem if you try to implement factorial the way that Scheme programmers do it. |factBlock| factBlock := [:x | x <= 1 ifTrue: [1] ifFalse: [x * (factBlock value: x-1)]]. factBlock value: 100 Squeak complains that you are trying to evaluate a block recursively. Most Smalltalk programmers would never try this, so they don't care about Squeak's limitations. But people coming to Squeak from a functional programming language are annoyed, because they expect that they can do this with blocks, but blocks are not complete closures. -Ralph Johnson _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Thanks, all. Now I'm understood differences.
On Fri, Apr 10, 2009 at 20:09, Ralph Johnson <[hidden email]> wrote: > In the original Smalltalk, blocks were almost but not quite closures. > The ANSII standard says they are closures. As far as I know, all the > Smalltalks except Squeak make blocks be closures. So, changing the > way Squeak implements blocks will bring it into compliance with the > standard and more like other implementations of Smalltalk > > I first ran into the problem of blocks not being closures when I tried > to write a program like > > (1 to: 100) do: [:each | [self process: each] fork] > > This will fork 100 processes. If the first spawned process (the one > running [self process: 1]) starts to run right away, it will behave > like I expect. But suppose the main thread creates all 100 processes > before it gives up control. Then the value of "each" will be 100 and > so all 100 processes will execute [self process: 100], which is not at > all what I expect. If blocks were closures then each execution of the > block would have its own context to store its argument, i.e. there > would be 100 versions of "each". > > You can see a similar problem if you try to implement factorial the > way that Scheme programmers do it. > > |factBlock| > factBlock := [:x | x <= 1 ifTrue: [1] ifFalse: [x * (factBlock value: x-1)]]. > factBlock value: 100 > > Squeak complains that you are trying to evaluate a block recursively. > Most Smalltalk programmers would never try this, so they don't care > about Squeak's limitations. But people coming to Squeak from a > functional programming language are annoyed, because they expect that > they can do this with blocks, but blocks are not complete closures. > > -Ralph Johnson > _______________________________________________ > Beginners mailing list > [hidden email] > http://lists.squeakfoundation.org/mailman/listinfo/beginners > Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Ralph Johnson
> In the original Smalltalk, blocks were almost but not quite closures.
> The ANSII standard says they are closures. As far as I know, all the > Smalltalks except Squeak make blocks be closures. So, changing the I haven't yet met the Smalltalk implementation that has block closures without obvious bugs. Making block closures correct and fast is not trivial. Lukas -- Lukas Renggli http://www.lukas-renggli.ch _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Why is this particularly hard for smalltalk? Scheme implementations
manage to do it. Is it simply that it's an afterthought, when it needs to be designed in from the ground up? On Fri, Apr 10, 2009 at 7:59 PM, Lukas Renggli <[hidden email]> wrote: >> In the original Smalltalk, blocks were almost but not quite closures. >> The ANSII standard says they are closures. As far as I know, all the >> Smalltalks except Squeak make blocks be closures. So, changing the > > I haven't yet met the Smalltalk implementation that has block closures > without obvious bugs. Making block closures correct and fast is not > trivial. > > Lukas > > -- > Lukas Renggli > http://www.lukas-renggli.ch > _______________________________________________ > Beginners mailing list > [hidden email] > http://lists.squeakfoundation.org/mailman/listinfo/beginners > Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
> Why is this particularly hard for smalltalk? Scheme implementations
> manage to do it. Is it simply that it's an afterthought, when it needs > to be designed in from the ground up? Two common problems I observed are related to: (1) Smalltalk inlines some blocks, such as the ones involved in conditionals and loops. Even these loop blocks are no real blocks anymore, they should behave exactly like real ones. For example the following 2 expression should yield the same result #(1 2 3 4 5) when evaluating the blocks in the collection: " in this case the block is inlined " 1 to: 5 do: [ :index | collection add: [ index ] ] " in this case the block is not inlined " (1 to: 5) do: [ :index | collection add: [ index ] ] (2) Some closure implementations perform invalid optimizations on blocks and wrongly copy enclosed values when they think they are not written to after block creation (AFAIK). In some cases this results in very strange effects, such as that the following two expressions are not symmetrical. In both cases the result should be #(5 5 5 5 5). | index | index := 0. [ index < 5 ] whileTrue: [ collection add: [ index ]. index := index + 1 ]. | index | index := 0. [ index < 5 ] whileTrue: [ index := index + 1. collection add: [ index ] ]. Cheers, Lukas -- Lukas Renggli http://www.lukas-renggli.ch _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Randal L. Schwartz
On Friday 10 April 2009 9:18:29 am Randal L. Schwartz wrote:
> In Squeak, i in the block will refer to the i in the do: block and the > last statement will print 25 because i would be 5 when do: terminates. > > Not necessarily. I could see an implementation where i would be 4. Possible. I just used Squeak 3.8/Etoys 4.0 as examples where i becomes 5 when the iteration terminates. Subbu _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Lukas Renggli
Lukas Renggli <[hidden email]> wrote:
> Two common problems I observed are related to: Interestingly, those problems do not arise if evaluated as a DoIt, but they do come up in the Testcase in Pharo (latest patches from today). I had three failing tests in ClosureTest, one test went green when I changed & recompiled the method, two still failing. Does the Compiler treat methods and DoIts differently (apparently, it does, and I guess there are good reasons not to optimize simpe DoIts). _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
> Does the Compiler treat methods and DoIts differently (apparently, it does,
> and I guess there are good reasons not to optimize simpe DoIts). The compiler treats all code the same, however the semantics might be different than what you would expect. For example workspace variables share the semantics of global variables, thus they do not behave the same way as temporary variables do when used with closures. Lukas -- Lukas Renggli http://www.lukas-renggli.ch _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Free forum by Nabble | Edit this page |