Variable capture in block closure

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

Variable capture in block closure

Stéphane Rollandin
Hello all,

Is it expected that

        | blocks x |

        blocks := OrderedCollection new.

        (1 to: 3) do: [:n |
                x := n.
                blocks add: [Transcript showln: x]].

        blocks do: #value


prints 3 three times, while

        | blocks |

        blocks := OrderedCollection new.

        (1 to: 3) do: [:n |
                | x |
                x := n.
                blocks add: [Transcript showln: x]].

        blocks do: #value

prints 1, 2, 3 ?

Stef

Reply | Threaded
Open this post in threaded view
|

Re: Variable capture in block closure

Bob Arning-2
just curious - which of those surprises you?

On 1/21/19 12:47 PM, Stéphane Rollandin wrote:
Hello all,

Is it expected that

    | blocks x |

    blocks := OrderedCollection new.

    (1 to: 3) do: [:n |
        x := n.
        blocks add: [Transcript showln: x]].

    blocks do: #value


prints 3 three times, while

    | blocks |

    blocks := OrderedCollection new.

    (1 to: 3) do: [:n |
        | x |
        x := n.
        blocks add: [Transcript showln: x]].

    blocks do: #value

prints 1, 2, 3 ?

Stef




Reply | Threaded
Open this post in threaded view
|

Re: Variable capture in block closure

Tony Garnock-Jones-5
In reply to this post by Stéphane Rollandin
Hi Stef,

On 1/21/19 5:47 PM, Stéphane Rollandin wrote:

> Is it expected that
>
>     | blocks x |
>     blocks := OrderedCollection new.
>     (1 to: 3) do: [:n |
>         x := n.
>         blocks add: [Transcript showln: x]].
>     blocks do: #value
>
> prints 3 three times, while
>
>     | blocks |
>     blocks := OrderedCollection new.
>     (1 to: 3) do: [:n |
>         | x |
>         x := n.
>         blocks add: [Transcript showln: x]].
>     blocks do: #value
>
> prints 1, 2, 3 ?

I would expect to see that, yes. I expect the first snippet to update a
single `x`-variable, while the second snippet creates (and then
immediately updates) a fresh `x`-variable within the scope of each
execution of the block argument to `#do:`.

I'd also expect

     | blocks |
     blocks := OrderedCollection new.
     (1 to: 3) do: [:n | blocks add: [Transcript showln: n]].
     blocks do: #value

to print 1, 2, 3, since I would expect a fresh `n` for each invocation
of the `#do:` block.

But then my mind has been poisoned by decades of exposure to high levels
of ambient Scheme.

Regards,
  Tony

Reply | Threaded
Open this post in threaded view
|

Re: Variable capture in block closure

Stéphane Rollandin
In reply to this post by Bob Arning-2
> just curious - which of those surprises you?

The first one. I expected the block to capture the variable value at the
block creation time, but from Tony's answer I now see why it does not
work that way.

Stef

Reply | Threaded
Open this post in threaded view
|

Re: Variable capture in block closure

Eliot Miranda-2
Hi Stef,

On Jan 21, 2019, at 10:43 AM, Stéphane Rollandin <[hidden email]> wrote:

>> just curious - which of those surprises you?
>
> The first one. I expected the block to capture the variable value at the block creation time, but from Tony's answer I now see why it does not work that way.

But the second example *does* capture x at block creation time. In the second example a single block is evaluated three times, each time creating a new x (x being a variable that comes into existence when the block is evaluated) and then three times a block nested within it is created, capturing x at block creation time.

>
> Stef
>

Reply | Threaded
Open this post in threaded view
|

Re: Variable capture in block closure

Eliot Miranda-2
In reply to this post by Tony Garnock-Jones-5

On Jan 21, 2019, at 10:10 AM, Tony Garnock-Jones <[hidden email]> wrote:

Hi Stef,

On 1/21/19 5:47 PM, Stéphane Rollandin wrote:
Is it expected that

    | blocks x |
    blocks := OrderedCollection new.
    (1 to: 3) do: [:n |
        x := n.
        blocks add: [Transcript showln: x]].
    blocks do: #value

prints 3 three times, while

    | blocks |
    blocks := OrderedCollection new.
    (1 to: 3) do: [:n |
        | x |
        x := n.
        blocks add: [Transcript showln: x]].
    blocks do: #value

prints 1, 2, 3 ?

I would expect to see that, yes. I expect the first snippet to update a
single `x`-variable, while the second snippet creates (and then
immediately updates) a fresh `x`-variable within the scope of each
execution of the block argument to `#do:`.

I'd also expect

    | blocks |
    blocks := OrderedCollection new.
    (1 to: 3) do: [:n | blocks add: [Transcript showln: n]].
    blocks do: #value

to print 1, 2, 3, since I would expect a fresh `n` for each invocation
of the `#do:` block.

As should
    | blocks |
    blocks := OrderedCollection new.
    1 to: 3 do: [:n | blocks add: [Transcript showln: n]].
    blocks do: #value

and

    ((1 to: 3) collect: [:n | [Transcript showln: n]]) do: #value


But then my mind has been poisoned by decades of exposure to high levels
of ambient Scheme.

Purified and elevated ;-)

Closures are closures :-)

Regards,
 Tony