Problem with closure/block

There are past threads that discuss this, but, basically, no, it's not
a bug, that's just how Ruby does it.

···

On Jan 9, 3:42 pm, "levili...@gmail.com" <levili...@gmail.com> wrote:

###########################
y=5
print "y: " + y.to_s + "\n"
text_at_the_end = lambda do |y|
print y + " text at the end\n"
end

print "y: " + y.to_s + "\n"

def oneparam
yield("oneparam")
end

oneparam(&text_at_the_end)
print "y: " + y + "\n"

########################
It gives the following output:

y: 5
y: 5
oneparam text at the end
y: oneparam

Is this a bug? Shouldn't "y" be in a local scope in "text_at_the_end"?
I just downloadad Ruby yesterday:

Ruby Version 1\.8\.6
Installer Version 186\-26

"However, if at the time the block executes a local variable
already exists with the same name as that of a variable in
the block, the existing local variable will be used in the
block. Its value will therefore be available after the block
finishes."

"Programming Ruby" p. 106

Whether this is a "bug" or a "feature" is in the eye of the beholder,
but it is something you should be aware of.

Has this changed in 1.9, or is it anticipated to change in 2.0 ?

···

On Jan 9, 4:42 pm, "levili...@gmail.com" <levili...@gmail.com> wrote:

###########################
y=5
print "y: " + y.to_s + "\n"
text_at_the_end = lambda do |y|
  print y + " text at the end\n"
end

print "y: " + y.to_s + "\n"

def oneparam
  yield("oneparam")
end

oneparam(&text_at_the_end)
print "y: " + y + "\n"

########################
It gives the following output:

y: 5
y: 5
oneparam text at the end
y: oneparam

Is this a bug? Shouldn't "y" be in a local scope in "text_at_the_end"?
I just downloadad Ruby yesterday:

    Ruby Version 1.8.6
    Installer Version 186-26

levilista@gmail.com wrote:

###########################
y=5
print "y: " + y.to_s + "\n"
text_at_the_end = lambda do |y|
  print y + " text at the end\n"
end

print "y: " + y.to_s + "\n"

def oneparam
  yield("oneparam")
end

oneparam(&text_at_the_end)
print "y: " + y + "\n"

########################
It gives the following output:

y: 5
oneparam text at the end
y: oneparam

Is this a bug? Shouldn't "y" be in a local scope in "text_at_the_end"?
I just downloadad Ruby yesterday:

    Ruby Version 1.8.6
    Installer Version 186-2

Blocks in Ruby are closures, so they save the context in which they were created, but new variables inside the closure are local.

irb(main):001:0> x = 1
=> 1
irb(main):002:0> l = lambda do |y|
irb(main):003:1* puts x
irb(main):004:1> puts y
irb(main):005:1> end
=> #<Proc:0x00002ae970650e58@(irb):2>
irb(main):006:0> l['hello']
1
hello
=> nil
irb(main):007:0> y
NameError: undefined local variable or method `y' for main:Object
        from (irb):7
irb(main):008:0> x
=> 1
irb(main):009:0> x += 1
=> 2
irb(main):010:0> l['again']
2
again
=> nil

Take a look here:
http://ruby-doc.org/docs/ProgrammingRuby/html/tut_containers.html#UG

-Justin

···

from :0

Has this changed in 1.9, or is it anticipated to change in 2.0 ?

With small change (added .to_s method)

$ cat proc.rb

···

###########################
y=5
print "y: " + y.to_s + "\n"
text_at_the_end = lambda do |y|
print y + " text at the end\n"
end

print "y: " + y.to_s + "\n"

def oneparam
yield("oneparam")
end

oneparam(&text_at_the_end)
print "y: " + y.to_s + "\n"

########################

$ ruby1.8 proc.rb
y: 5
y: 5
oneparam text at the end
y: oneparam

$ ruby1.9 proc.rb
y: 5
y: 5
oneparam text at the end
y: 5
--
Radosław Bułat

http://radarek.jogger.pl - mój blog

"Blocks in Ruby are closures, so they save the context in which they
were
created, but new variables inside the closure are local. "

I just expected, that if the head of the closure has x, it will create
a new local variable with the same name.

···

On Jan 10, 2:33 am, Justin Collins <justincoll...@ucla.edu> wrote:

levili...@gmail.com wrote:
> ###########################
> y=5
> print "y: " + y.to_s + "\n"
> text_at_the_end = lambda do |y|
> print y + " text at the end\n"
> end

> print "y: " + y.to_s + "\n"

> def oneparam
> yield("oneparam")
> end

> oneparam(&text_at_the_end)
> print "y: " + y + "\n"

> ########################
> It gives the following output:

> y: 5
> y: 5
> oneparam text at the end
> y: oneparam

> Is this a bug? Shouldn't "y" be in a local scope in "text_at_the_end"?
> I just downloadad Ruby yesterday:

> Ruby Version 1.8.6
> Installer Version 186-2

Blocks in Ruby are closures, so they save the context in which they were
created, but new variables inside the closure are local.

irb(main):001:0> x = 1
=> 1
irb(main):002:0> l = lambda do |y|
irb(main):003:1* puts x
irb(main):004:1> puts y
irb(main):005:1> end
=> #<Proc:0x00002ae970650e58@(irb):2>
irb(main):006:0> l['hello']
1
hello
=> nil
irb(main):007:0> y
NameError: undefined local variable or method `y' for main:Object
        from (irb):7
        from :0
irb(main):008:0> x
=> 1
irb(main):009:0> x += 1
=> 2
irb(main):010:0> l['again']
2
again
=> nil

Take a look here:Programming Ruby: The Pragmatic Programmer's Guide

-Justin

And if you use the -w option ruby 1.9 will warn that the semantics have changed.

$ ruby1.9 -w proc.rb
proc.rb:4: warning: shadowing outer local variable - y
y: 5
y: 5
oneparam text at the end
y: 5

$ ruby -w proc.rb
y: 5
y: 5
oneparam text at the end
y: oneparam

···

On 1/9/08, Radosław Bułat <radek.bulat@gmail.com> wrote:

> Has this changed in 1.9, or is it anticipated to change in 2.0 ?

With small change (added .to_s method)

$ cat proc.rb
###########################
y=5
print "y: " + y.to_s + "\n"
text_at_the_end = lambda do |y|
print y + " text at the end\n"
end

print "y: " + y.to_s + "\n"

def oneparam
yield("oneparam")
end

oneparam(&text_at_the_end)
print "y: " + y.to_s + "\n"

########################

$ ruby1.8 proc.rb
y: 5
y: 5
oneparam text at the end
y: oneparam

$ ruby1.9 proc.rb
y: 5
y: 5
oneparam text at the end
y: 5

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

I think it's an advantage in javascript, that you have to mark new
variables with "var", so the scope of a variable is always obvious.

···

On Jan 10, 9:13 am, "zsl...@gmail.com" <levili...@gmail.com> wrote:

"Blocks in Ruby are closures, so they save the context in which they
were
created, but new variables inside the closure are local. "

I just expected, that if the head of the closure has x, it will create
a new local variable with the same name.

On Jan 10, 2:33 am, Justin Collins <justincoll...@ucla.edu> wrote:

> levili...@gmail.com wrote:
> > ###########################
> > y=5
> > print "y: " + y.to_s + "\n"
> > text_at_the_end = lambda do |y|
> > print y + " text at the end\n"
> > end

> > print "y: " + y.to_s + "\n"

> > def oneparam
> > yield("oneparam")
> > end

> > oneparam(&text_at_the_end)
> > print "y: " + y + "\n"

> > ########################
> > It gives the following output:

> > y: 5
> > y: 5
> > oneparam text at the end
> > y: oneparam

> > Is this a bug? Shouldn't "y" be in a local scope in "text_at_the_end"?
> > I just downloadad Ruby yesterday:

> > Ruby Version 1.8.6
> > Installer Version 186-2

> Blocks in Ruby are closures, so they save the context in which they were
> created, but new variables inside the closure are local.

> irb(main):001:0> x = 1
> => 1
> irb(main):002:0> l = lambda do |y|
> irb(main):003:1* puts x
> irb(main):004:1> puts y
> irb(main):005:1> end
> => #<Proc:0x00002ae970650e58@(irb):2>
> irb(main):006:0> l['hello']
> 1
> hello
> => nil
> irb(main):007:0> y
> NameError: undefined local variable or method `y' for main:Object
> from (irb):7
> from :0
> irb(main):008:0> x
> => 1
> irb(main):009:0> x += 1
> => 2
> irb(main):010:0> l['again']
> 2
> again
> => nil

> Take a look here:Programming Ruby: The Pragmatic Programmer's Guide

> -Justin

I think it's an advantage in javascript, that you have to mark new
variables with "var", so the scope of a variable is always obvious.

JS doesn't have it right... if anything, I've seen it cause MUCH MORE
confusion wrt closures.
'var' is context-specific (only applies INSIDE functions, but
syntactically valid outside) and it is just a hint, not a declaration.
These are the same:

function a(z) { var x = z; return function () {return x} }
function b(z) { x = z; return function () {return x}; var x }

and:

var x = 10; // outside a function

is both misleading and useless.