strange local variable problem

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

strange local variable problem

Tudor Girba
Hi,

I have a method that takes OBCommands and returns Actions:

actionsFrom: aCollectionOfOBCommandClasses on: aTarget for: aRequestor
        | command |
        ^ aCollectionOfOBCommandClasses collect: [ :each |
                command := each on: aTarget for: aRequestor.
                GLMAction new
                        icon: command icon;
                        title: command label;
                        action: [:presentation | command execute ];
                        yourself
                ]

These actions have a block that will be executed at a later time. The  
problem here was that the command in the action block was always  
pointing to the same command object, even at each point the command  
variable was populated correctly.

However, when the command is defined inside the block, everything  
works as expected.

actionsFrom: aCollectionOfOBCommandClasses on: aTarget for: aRequestor
        ^ aCollectionOfOBCommandClasses collect: [ :each |
                | command |
                command := each on: aTarget for: aRequestor.
                GLMAction new
                        icon: command icon;
                        title: command label;
                        action: [:presentation | command execute ];
                        yourself
                ]

I believe this is a bug.

Cheers,
Doru

--
www.tudorgirba.com

"Obvious things are difficult to teach."




_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: strange local variable problem

Levente Uzonyi-2
On Sun, 17 Jan 2010, Tudor Girba wrote:

> Hi,
>
> I have a method that takes OBCommands and returns Actions:
>
> actionsFrom: aCollectionOfOBCommandClasses on: aTarget for: aRequestor
> | command |
> ^ aCollectionOfOBCommandClasses collect: [ :each |
> command := each on: aTarget for: aRequestor.
> GLMAction new
> icon: command icon;
> title: command label;
> action: [:presentation | command execute ];
> yourself
> ]
>
> These actions have a block that will be executed at a later time. The
> problem here was that the command in the action block was always
> pointing to the same command object, even at each point the command
> variable was populated correctly.
>
> However, when the command is defined inside the block, everything
> works as expected.
>
> actionsFrom: aCollectionOfOBCommandClasses on: aTarget for: aRequestor
> ^ aCollectionOfOBCommandClasses collect: [ :each |
> | command |
> command := each on: aTarget for: aRequestor.
> GLMAction new
> icon: command icon;
> title: command label;
> action: [:presentation | command execute ];
> yourself
> ]
>
> I believe this is a bug.

This is exactly how it should work, it's a feature that I used to use.


Levente

>
> Cheers,
> Doru
>
> --
> www.tudorgirba.com
>
> "Obvious things are difficult to teach."
>
>
>
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: strange local variable problem

Lukas Renggli
In reply to this post by Tudor Girba
> I believe this is a bug.

That's the correct behavior. This is exactly how closures should
behave. The variable declaration is outside the block you store thus
one variable slot is shared among multiple block definitions inside.
See ClosureTests for more examples of that behavior.

Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: strange local variable problem

Tudor Girba
Indeed, my bad.

Cheers,
Doru


On 17 Jan 2010, at 09:57, Lukas Renggli wrote:

>> I believe this is a bug.
>
> That's the correct behavior. This is exactly how closures should
> behave. The variable declaration is outside the block you store thus
> one variable slot is shared among multiple block definitions inside.
> See ClosureTests for more examples of that behavior.
>
> Lukas
>
> --
> Lukas Renggli
> http://www.lukas-renggli.ch
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

--
www.tudorgirba.com

"Problem solving should be concentrated on describing
the problem in a way that is relevant for the solution."




_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: strange local variable problem

csrabak
In reply to this post by Lukas Renggli
Levente and Lukas,

You both agree that this is not a bug, them we have to ascertain that 'average Smalltalker' will understand that using closures in Pharo changes the Smalltalk language definition.



Em 17/01/2010 06:57, Lukas Renggli < [hidden email] > escreveu:


> I believe this is a bug.

That's the correct behavior. This is exactly how closures should
behave. The variable declaration is outside the block you store thus
one variable slot is shared among multiple block definitions inside.
See ClosureTests for more examples of that behavior.

Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: strange local variable problem

Stéphane Ducasse
Soon there will be a chapter on a nice book on that :)


> Levente and Lukas,
>
> You both agree that this is not a bug, them we have to ascertain that 'average Smalltalker' will understand that using closures in Pharo changes the Smalltalk language definition.
>
>
>
> Em 17/01/2010 06:57, Lukas Renggli < [hidden email] > escreveu:
>
>
>> I believe this is a bug.
>
> That's the correct behavior. This is exactly how closures should
> behave. The variable declaration is outside the block you store thus
> one variable slot is shared among multiple block definitions inside.
> See ClosureTests for more examples of that behavior.
>
> Lukas
>
> --
> Lukas Renggli
> http://www.lukas-renggli.ch
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: strange local variable problem

Levente Uzonyi-2
In reply to this post by csrabak
On Sun, 17 Jan 2010, [hidden email] wrote:

> Levente and Lukas,
>
> You both agree that this is not a bug, them we have to ascertain that 'average Smalltalker' will understand that using closures in Pharo changes the Smalltalk language definition.

The semantics change in various ways. The trivial example that everyone
knows is this:

factorial := [ :n |
  n > 1
  ifTrue: [ n * (factorial value: n - 1) ]
  ifFalse: [ 1 ] ].
factorial value: 10.

Without closures you get an error, with closures you get the expected
result.

Another significant change is the existence of local variables in blocks.
Without closures blocks don't have local variables, with closures they do:

b := [ :p |
  | t |
  t ifNil: [ t := p ] ].
{ b value: 1. b value: 2 }

In a non-closure image you get #(1 1) as result, because t is not a block
local variable even if it looks like one. In a closure image you get #(1 2)
because t is a block local variable.


Levente

>
>
>
> Em 17/01/2010 06:57, Lukas Renggli < [hidden email] > escreveu:
>
>
>> I believe this is a bug.
>
> That's the correct behavior. This is exactly how closures should
> behave. The variable declaration is outside the block you store thus
> one variable slot is shared among multiple block definitions inside.
> See ClosureTests for more examples of that behavior.
>
> Lukas
>
> --
> Lukas Renggli
> http://www.lukas-renggli.ch
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: strange local variable problem

Lukas Renggli
In reply to this post by csrabak
> You both agree that this is not a bug, them we have to ascertain that
> 'average Smalltalker' will understand that using closures in Pharo
> changes the Smalltalk language definition.

The point is Pharo finally has real closures and sane execution
semantics. The same semantics that all other Smalltalk dialects
already had for decades, and the same semantics that Lisp, Scheme and
even Javascript programmers trusted on in the last 40 years.

The previous block semantics on Pharo (and Squeak) were completely
broken. The 'average Smalltalker' had to understand how contexts were
setup and how the source is compiled to bytecode to explain the
numerous hacks that were required for example in get the blocks behave
sanely in Seaside. This is no longer necessary. The 'average
Smalltalker' can just read the wikipedia page on closures.

Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: strange local variable problem

csrabak
Em 18/01/2010 14:59, Lukas Renggli < [hidden email] > escreveu:

>  The point  is Pharo  finally has real  closures and  sane execution
> semantics.  The same  semantics  that all  other Smalltalk  dialects
> already had  for decades, and  the same semantics that  Lisp, Scheme
> and even Javascript programmers trusted on in the last 40 years.

I agree with the sane semantics w.r.t. closures.  However, Turba's post:

> > Em 16/01/2010 23:07, Tudor Girba <[hidden email]> escreveu:

> > > I have a method that takes OBCommands and returns Actions:
> > >
> > > actionsFrom: aCollectionOfOBCommandClasses on: aTarget for: aRequestor
> > > | command |
> > > ^ aCollectionOfOBCommandClasses collect: [ :each |
> > > command := each on: aTarget for: aRequestor.
> > > GLMAction new
> > > icon: command icon;
> > > title: command label;
> > > action: [:presentation | command execute ];
> > > yourself
> > > ]
> > >
> > > These actions have a block that will be executed at a later time. The
> > > problem here was that the command in the action block was always
> > > pointing to the same command object, even at each point the command
> > > variable was populated correctly.
> > >
> > > However, when the command is defined inside the block, everything
> > > works as expected.
> > >

Makes me think the method would be work invariably of the position of
the variable command (which is temporary for the method), because I
see this analogous to (pls bear with me that in order to simplify the
example I'm probably missing something!):

temp :=  1000.
#(99 17 1 2 3 4 5 0 6 7 8 9) do: [:ea | temp := temp min: ea].

which after execution leaves temp with zero.
   

>  The previous block semantics  on Pharo (and Squeak) were completely
> broken.  The 'average  Smalltalker' had  to understand  how contexts
> were setup and how the source is compiled to bytecode to explain the
> numerous  hacks that  were required  for example  in get  the blocks
> behave sanely in Seaside. This  is no longer necessary. The 'average
> Smalltalker' can just read the wikipedia page on closures.
>

OK about that!

I'm obviously missing something, but perhaps being able to read this mailing only at night and tired is not helpin'!!

[]s

--
Cesar Rabak

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project