[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Bug in lambda?

kevin cline

9/9/2007 3:13:00 AM

This looks like a pretty serious bug. It seems that lambda-
expressions are not properly localizing their formal arguments:

bash-3.2$ ruby --version
ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]

bash-3.2$ cat lambda-bug.rb
a = 0
f = lambda { |a| a }
puts "a = #{a}"
puts "f.call(1) => #{f.call(1)}"
puts "now a = #{a}"

bash-3.2$ ruby lambda-bug.rb
a = 0
f.call(1) => 1
now a = 1

33 Answers

Wilson Bilkovich

9/9/2007 3:31:00 AM

0

On 9/8/07, kevin cline <kevin.cline@gmail.com> wrote:
> This looks like a pretty serious bug. It seems that lambda-
> expressions are not properly localizing their formal arguments:
>
> bash-3.2$ ruby --version
> ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]
>
> bash-3.2$ cat lambda-bug.rb
> a = 0
> f = lambda { |a| a }
> puts "a = #{a}"
> puts "f.call(1) => #{f.call(1)}"
> puts "now a = #{a}"
>
> bash-3.2$ ruby lambda-bug.rb
> a = 0
> f.call(1) => 1
> now a = 1
>

This is the expected behavior of Ruby 1.8.
'lambda' and 'proc' are expected to diverge further in future versions.

Logan Capaldo

9/9/2007 3:39:00 AM

0

On 9/8/07, kevin cline <kevin.cline@gmail.com> wrote:
> This looks like a pretty serious bug. It seems that lambda-
> expressions are not properly localizing their formal arguments:
>
> bash-3.2$ ruby --version
> ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]
>
> bash-3.2$ cat lambda-bug.rb
> a = 0
> f = lambda { |a| a }
> puts "a = #{a}"
> puts "f.call(1) => #{f.call(1)}"
> puts "now a = #{a}"
>
> bash-3.2$ ruby lambda-bug.rb
> a = 0
> f.call(1) => 1
> now a = 1

Not a bug, it's a "feature". I don't like it either.

foo = lambda { |$this_works_too| }

foo.call(2)

p $this_works_too

class SoDoesThis
attr_reader :foo
def setter
lambda { |@foo| }
end
end

bar = SoDoesThis.new
bar.setter["this is sparta"]
p bar.foo

Konrad Meyer

9/9/2007 3:41:00 AM

0

On Saturday 08 September 2007 08:15:06 pm kevin cline wrote:
> This looks like a pretty serious bug. It seems that lambda-
> expressions are not properly localizing their formal arguments:
>
> bash-3.2$ ruby --version
> ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]
>
> bash-3.2$ cat lambda-bug.rb
> a = 0
> f = lambda { |a| a }
> puts "a = #{a}"
> puts "f.call(1) => #{f.call(1)}"
> puts "now a = #{a}"
>
> bash-3.2$ ruby lambda-bug.rb
> a = 0
> f.call(1) => 1
> now a = 1

IIRC this is a ruby 1.8.x thing; it will be fixed in 1.9. Don't depend on
this behaviour / try to avoid repeating variable names :D.

Cheers,
--
Konrad Meyer <konrad@tylerc.org> http://konrad.sobertil...

dblack

9/9/2007 8:28:00 AM

0

Logan Capaldo

9/9/2007 11:15:00 AM

0

On 9/9/07, Bernardo Monteiro Rufino <bermonruf@gmail.com> wrote:
> In 1.9 it won't be able to access local scope?
>
>
No, just not the arguments. The following will still work:

a = 1
foo = lambda { a = 99 }
foo.call
p a # prints 99
> --
> Bernardo Rufino
>

7stud 7stud

9/9/2007 11:29:00 AM

0

> This looks like a pretty serious bug.

I guess you didn't read p. 51 of "Programming Ruby (2nd Ed)". You can
read the first edition online. See the section Implementing Iterators
here:

http://www.rubycentral.com/pickaxe/tut_conta...


>
> As far as remember, Guy Decoux and I are the only two people who think
> that this makes perfect sense, once you learn it, and should not be
> changed :-)
>

The behavior in question seems consistent with the way closures work in
Ruby:

def func(x)
y = 10
lambda {puts x+y; y += 1}
end

p = func(5)
p.call
p.call
p.call

--output:--
15
16
17

Is there something inconsistent with the way a block defined outside of
any functions behaves versus a closure?


--
Posted via http://www.ruby-....

7stud 7stud

9/9/2007 11:32:00 AM

0

7stud -- wrote:
>
> Is there something inconsistent with the way a block defined outside of
> any functions behaves versus a closure?

Whoops. Methods, methods.....

--
Posted via http://www.ruby-....

7stud 7stud

9/9/2007 11:39:00 AM

0

7stud -- wrote:
> The behavior in question seems consistent with the way closures work in
> Ruby:
>
> def func(x)
> y = 10
> lambda {puts x+y; y += 1}
> end
>
> p = func(5)
> p.call
> p.call
> p.call
>
> --output:--
> 15
> 16
> 17
>
> Is there something inconsistent with the way a block defined outside of
> any functions behaves versus a closure?

I guess this would be a more complete example:

$z = 100

def func(x)
y = 10

lambda {
puts x+y+$z
x+=1
y += 1
$z+=100
}
end

p = func(5)
p.call
p.call
p.call

--output:--
115
217
319


--
Posted via http://www.ruby-....

Logan Capaldo

9/9/2007 3:47:00 PM

0

On 9/9/07, Bernardo Monteiro Rufino <bermonruf@gmail.com> wrote:
> On 9/9/07, dblack@wobblini.net <dblack@wobblini.net> wrote:
>
> > As far as remember, Guy Decoux and I are the only two people who think
> > that this makes perfect sense, once you learn it, and should not be
> > changed :-)
> >
>
> I think it shouldn't be changed too...
>
I just think it has icky semantics.
a.rb:

fib = lambda do |a|
if a == 1 or a == 0
1
else
fib[a - 1] + fib[a - 2]
end
end

p fib.call(10)

C:\Documents and Settings\Logan>ruby a.rb
89

vs.

b.rb:
a = nil
fib = lambda do |a|
if a == 1 or a == 0
1
else
fib[a - 1] + fib[a - 2]
end
end

p fib.call(10)


C:\Documents and Settings\Logan>ruby b.rb
b.rb:6: stack level too deep (SystemStackError)
from b.rb:6
from b.rb:6
from b.rb:6
from b.rb:6
from b.rb:6
from b.rb:6
from b.rb:6
from b.rb:6
... 633 levels...
from b.rb:6
from b.rb:6
from b.rb:6
from b.rb:10

Am I the only one who makes use of recursive lambdas? ;) If we keep
assignment semantics for block arguments, I think we should disallow
recursive blocks. I don't want recursive blocks to go away personally.
I think it's reasonable to give block arguments argument semantics
(especially in light of the addition of &block arguments to blocks)
instead of assignment semantics. You don't lose any power, although
you do lose some "expressivity", eg:

a = nil
set_a = lambda { |b| a = b }

instead of
a = nil
set_a = lambda { |a| }

> --
> Bernardo Rufino
>

Wilson Bilkovich

9/9/2007 7:01:00 PM

0

On 9/9/07, Logan Capaldo <logancapaldo@gmail.com> wrote:
> On 9/9/07, Bernardo Monteiro Rufino <bermonruf@gmail.com> wrote:
> > On 9/9/07, dblack@wobblini.net <dblack@wobblini.net> wrote:
> >
> > > As far as remember, Guy Decoux and I are the only two people who think
> > > that this makes perfect sense, once you learn it, and should not be
> > > changed :-)
> > >

This one is my favorite.
P.S. Don't use this in 'real' code or I will be forced to hunt you
like a wild animal through the streets of your city. =(

hydra>cat eye_of_terror.rb
h = {}
f = lambda {|h[:x]| }
f[7]
p h

hydra>ruby eye_of_terror.rb
{:x=>7}