Ruby 1.8.7 Lambas: syntax and scoping issue (are these bugs?

I'm seeing two odd behaviours with using lambdas:

1. It seems as though having a lambda as a function argument with a
block causes a syntax error. It can be mitigated by adding a semicolon
or by using parentheses

def foo(rest)
   puts rest.inspect
   yield
end

# fails syntax error
foo :parm1=>1, :parm2=>lambda { puts "lambda" } do
   puts "In bar block"
end

# fails syntax error
foo :parm1=>lambda { puts "lambda" }, :parm2=>1 do
   puts "In bar block"
end

# fails syntax error
foo {:parm1=>1, :parm2=>lambda { puts "lambda" }} do
   puts "In bar block"
end

# succeeds???
foo :parm1=>1, :parm2=>lambda { puts "lambda"; } do
   puts "In bar block"
end

# succeeds???
foo (:parm1=>1, :parm2=>lambda { puts "lambda" }) do
   puts "In bar block"
end

2. I'm not understanding the scoping rules for lambda with
instance_evals inside a class:

# If these statements are added at the beginning the
# the lambda will evaluate them first
# a = 4 # stmt 1
# b = 5 # stmt 2
class Bar
   attr_accessor :a, :b
   def initialize
       @a = 1
       @b = 2
   end
   def foo(&block)
       instance_eval(&block)
   end
end

m = lambda{puts a + b}
Bar.new.foo(&m)

Without stmt1 and stmt2 above, the code correctly outputs 3. But if
stmt1 and stmt2 are incommented, the output is 9 which seems to be the
global scope rather than the scope of the instance of Bar expected
with instance_eval.

Am I missing something?

Thanks,
Charlton

···

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

Hi --

I'm seeing two odd behaviours with using lambdas:

I'm skipping to #2 if that's OK.

2. I'm not understanding the scoping rules for lambda with
instance_evals inside a class:

# If these statements are added at the beginning the
# the lambda will evaluate them first
# a = 4 # stmt 1
# b = 5 # stmt 2
class Bar
  attr_accessor :a, :b
  def initialize
      @a = 1
      @b = 2
  end
  def foo(&block)
      instance_eval(&block)
  end
end

m = lambda{puts a + b}
Bar.new.foo(&m)

Without stmt1 and stmt2 above, the code correctly outputs 3. But if
stmt1 and stmt2 are incommented, the output is 9 which seems to be the
global scope rather than the scope of the instance of Bar expected
with instance_eval.

Am I missing something?

When Ruby sees a and b, it favors the interpretation that they are
local variables. If you want to ensure that they're interpreted as
method calls, you can do:

   puts a() + b()

David

···

On Sat, 6 Dec 2008, Charlton Wang wrote:

--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS (Jan 12-15), Fort Lauderdale, FL
See http://www.rubypal.com for details
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2\)

Charlton Wang wrote:

I'm seeing two odd behaviours with using lambdas:

1. It seems as though having a lambda as a function argument with a
block causes a syntax error. It can be mitigated by adding a semicolon
or by using parentheses

def foo(rest)
   puts rest.inspect
   yield
end

# fails syntax error
foo :parm1=>1, :parm2=>lambda { puts "lambda" } do
   puts "In bar block"
end

The syntax is wrong whether or not you are passing
a Proc object as an argument.

def foo(rest)
  puts rest.inspect
  yield
end
    ==>nil
foo 'hello' { puts 'in block' }
SyntaxError: compile error
(irb):5: syntax error
foo 'hello' { puts 'in block' }
             ^
(irb):5: syntax error
        from (irb):5
foo( 'hello' ){ puts 'in block' }
"hello"
in block
    ==>nil
foo( proc{p "I'm neither sheep nor lambda."} ){ puts 'in block' }
#<Proc:0x02b14a5c@(irb):6>
in block
    ==>nil

···

from :0

Charlton Wang wrote:

# fails syntax error
foo :parm1=>1, :parm2=>lambda { puts "lambda" } do
   puts "In bar block"
end

Curiously, that works in 1.9.

I also noticed this succeeds in 1.8 (and 1.9):

  foo :parm1=>1, :parm2=>lambda { puts("lambda") } do
     puts "In bar block"
  end

···

--
Posted via http://www.ruby-forum.com/\.

Sorry, you lost me with your example.

My block is being bound with do/end rather than {}. In your examples,
you're using {} which has tighter binding and the syntax error is
expected.

foo 'hello' do puts 'in block'; end

works just find but this isn't the same as what I'm asking. I'm binding
the lambda function as a hash value.

Or...maybe I'm missing something obvious.

Charlton

William James wrote:

···

Charlton Wang wrote:

# fails syntax error
foo :parm1=>1, :parm2=>lambda { puts "lambda" } do
   puts "In bar block"
end

The syntax is wrong whether or not you are passing
a Proc object as an argument.

def foo(rest)
  puts rest.inspect
  yield
end
    ==>nil
foo 'hello' { puts 'in block' }
SyntaxError: compile error
(irb):5: syntax error
foo 'hello' { puts 'in block' }
             ^
(irb):5: syntax error
        from (irb):5
        from :0
foo( 'hello' ){ puts 'in block' }
"hello"
in block
    ==>nil
foo( proc{p "I'm neither sheep nor lambda."} ){ puts 'in block' }
#<Proc:0x02b14a5c@(irb):6>
in block
    ==>nil

--
Posted via http://www.ruby-forum.com/\.

The Higgs bozo wrote:

Charlton Wang wrote:

# fails syntax error
foo :parm1=>1, :parm2=>lambda { puts "lambda" } do
   puts "In bar block"
end

Curiously, that works in 1.9.

I also noticed this succeeds in 1.8 (and 1.9):

  foo :parm1=>1, :parm2=>lambda { puts("lambda") } do
     puts "In bar block"
  end

That's really interesting. So the parentheses as arguments to the puts
make it work. How odd!

···

--
Posted via http://www.ruby-forum.com/\.