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

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.
8cca6d920b14abea10bfd4e298106ad8?d=identicon&s=25 Charlton Wang (charlton)
on 2008-12-05 18:00
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
F53b05cdbdf561cfe141f69b421244f3?d=identicon&s=25 David A. Black (Guest)
on 2008-12-05 18:27
(Received via mailing list)
Hi --

On Sat, 6 Dec 2008, Charlton Wang wrote:

> I'm seeing two odd behaviours with using lambdas:

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

>       @a = 1
> 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
2ee1a7960cc761a6e92efb5000c0f2c9?d=identicon&s=25 William James (Guest)
on 2008-12-06 21:57
(Received via mailing list)
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
8cca6d920b14abea10bfd4e298106ad8?d=identicon&s=25 Charlton Wang (charlton)
on 2008-12-07 03:20
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
Beb77c4602c3cac7a12149431366ed11?d=identicon&s=25 The Higgs bozo (higgsbozo)
on 2008-12-07 08:48
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
8cca6d920b14abea10bfd4e298106ad8?d=identicon&s=25 Charlton Wang (charlton)
on 2008-12-07 16:18
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!
This topic is locked and can not be replied to.