Forum: Ruby What am I missing with this closure example?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ca0b18ec9e11dc777b2b8084fe5d5f90?d=identicon&s=25 Sam Kong (Guest)
on 2006-03-01 03:11
(Received via mailing list)
Hello!

Since my last question about
closure(http://groups.google.com/group/comp.lang.ruby/brow...)
I am testing my understanding making some examples.

Here's some code:

def f name
	x = 0

	case name
		when "one"
			lambda {x += 1; puts x}
		when "two"
			lambda {puts x}
	end
end

one = f "one"
two = f "two"

one.call
two.call
one.call
two.call

Result:

1
0
2
0


I expected the following.
1
1
2
2


I thought that x is shared between one and two but they don't seem to.
Or am I missing something?

Thanks.

Sam
2ffac40f8a985a2b2749244b8a1c4161?d=identicon&s=25 Mike Stok (Guest)
on 2006-03-01 03:23
(Received via mailing list)
On 28-Feb-06, at 8:58 PM, Sam Kong wrote:

> 	x = 0
> two = f "two"
> 2
> I thought that x is shared between one and two but they don't seem to.
> Or am I missing something?

Each time you call f you get a different x, so the lambda's x are
bound to different variables.  Does this do what you expect:

def f
	x = 0

   [lambda {x += 1; puts x}, lambda {puts x}]
end

one, two = f

one.call
two.call
one.call
two.call


Mike

--

Mike Stok <mike@stok.ca>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.
8b8e05733c1cd279f9e48e22405f4803?d=identicon&s=25 hitesh.jasani@gmail.com (Guest)
on 2006-08-03 13:46
(Received via mailing list)
Like konsu states, you have two different closures.  Here's a little
rewrite of your code that works with one closure.

def f
  x = 0
  one = lambda {x += 1; puts x}
  two = lambda {puts x}
  [one, two]
end

one, two = f

one.call
two.call
one.call
two.call


=> with results of
1
1
2
2


- Hitesh
http://www.jasani.org/
Ca0b18ec9e11dc777b2b8084fe5d5f90?d=identicon&s=25 Sam Kong (ssk)
on 2006-08-03 14:22
(Received via mailing list)
hitesh.jasani@gmail.com wrote:
> one, two = f
> 2
> 2

Aha~
Now I see the difference.
Thanks everyone.

Sam
Ec2a9a9da5c8a5f14a0fe2361ae4e08a?d=identicon&s=25 Mark J.Reed (Guest)
on 2006-08-15 14:09
(Received via mailing list)
"Sam Kong" <sam.s.kong@gmail.com> writes:
>def f name
>	x = 0

>	case name
>		when "one"
>			lambda {x += 1; puts x}
>		when "two"
>			lambda {puts x}
>	end
>end

>one = f "one"
>two = f "two"

The assignment "x = 0" gets executed every time you call f, creating a
new x
each time and initializing that new x to zero.

As far as I can tell, Ruby has no static scope, only dynamic scope,
which,
if I'm right, means there's no straightforward way to do what you're
trying.

In Perl, for instance, you could do this:

{
    my $x = 0;
    sub f
    {
        my $name = shift;
        return sub { $x += 1; print "$x\n"; } if ($name eq 'one');
        return sub { print "$x\n"; } if ($name eq 'two');
    }
}
my $one = f('one');
my $two = f('two');
$one->();
$two->();
$one->();
$two->();

And achieve the result you expected, but in Ruby, I don't know how to
achieve
something similar.  As a practical matter, I would just create an object
with
an attribute and use methods on that object in lieu of the closures.
B39c2415f51b64da5fdc5637a2e81a89?d=identicon&s=25 konsu (Guest)
on 2006-08-15 14:09
(Received via mailing list)
hello,

f("two") creates a lambda that sees 'x' as it was at the time of its
creation. zero that is.

the 'x' that f("one") uses is in a different closure.

konstantin

"Sam Kong" <sam.s.kong@gmail.com> wrote in message
news:1141155782.675003.313420@e56g2000cwe.googlegroups.com...
This topic is locked and can not be replied to.