Issue with block and getting to local variables

Ok I'm new to ruby and want to do the following, I want to define a
function that is a ble to call a block and I want that block to have
access to the calling function's local variables. Also I'd like that
block of code to be attached to a variable so I can call it were and
when ever.

Thanks

···

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

Also I'd like that
block of code to be attached to a variable so I can call it were and
when ever.

irb(main):001:0> bl = lambda {|a,b| puts a, b}
=> #<Proc:0x7ff98cf4@(irb):1>

> Ok I'm new to ruby and want to do the following, I want to define a
> function that is a ble to call a block and I want that block to have
> access to the calling function's local variables.

irb(main):002:0> def fun
irb(main):003:1> x = 1
irb(main):004:1> y = 2
irb(main):005:1> yield x,y
irb(main):006:1> end
=> nil
irb(main):007:0> fun &bl
1
2
=> nil
irb(main):008:0>

Kind regards

  robert

···

On 12.11.2008 21:31, Tarek Other wrote:

Robert Klemme wrote:

···

On 12.11.2008 21:31, Tarek Other wrote:

Also I'd like that
block of code to be attached to a variable so I can call it were and
when ever.

irb(main):001:0> bl = lambda {|a,b| puts a, b}
=> #<Proc:0x7ff98cf4@(irb):1>

> Ok I'm new to ruby and want to do the following, I want to define a
> function that is a ble to call a block and I want that block to have
> access to the calling function's local variables.

irb(main):002:0> def fun
irb(main):003:1> x = 1
irb(main):004:1> y = 2
irb(main):005:1> yield x,y
irb(main):006:1> end
=> nil
irb(main):007:0> fun &bl
1
2
=> nil
irb(main):008:0>

Kind regards

  robert

Thank you Robert but the problem with that approach is the need to pass
the variables into the block (in this case x,y has to be passed in). I
wanted to avoid that because I would have ton of local variables that I
would have to pass in. Is there any way to do what I want?
--
Posted via http://www.ruby-forum.com/\.

x, y (and a, b) are objects. They don't have to be integers. They
could be arrays, hashes, etc.

Todd

···

On Wed, Nov 12, 2008 at 3:43 PM, Tarek Other <cashew250@yahoo.com> wrote:

Robert Klemme wrote:

On 12.11.2008 21:31, Tarek Other wrote:

Also I'd like that
block of code to be attached to a variable so I can call it were and
when ever.

irb(main):001:0> bl = lambda {|a,b| puts a, b}
=> #<Proc:0x7ff98cf4@(irb):1>

> Ok I'm new to ruby and want to do the following, I want to define a
> function that is a ble to call a block and I want that block to have
> access to the calling function's local variables.

irb(main):002:0> def fun
irb(main):003:1> x = 1
irb(main):004:1> y = 2
irb(main):005:1> yield x,y
irb(main):006:1> end
=> nil
irb(main):007:0> fun &bl
1
2
=> nil
irb(main):008:0>

Kind regards

  robert

Thank you Robert but the problem with that approach is the need to pass
the variables into the block (in this case x,y has to be passed in). I
wanted to avoid that because I would have ton of local variables that I
would have to pass in. Is there any way to do what I want?

Todd Benson wrote:

···

On Wed, Nov 12, 2008 at 3:43 PM, Tarek Other <cashew250@yahoo.com> > wrote:

> function that is a ble to call a block and I want that block to have
2

would have to pass in. Is there any way to do what I want?

x, y (and a, b) are objects. They don't have to be integers. They
could be arrays, hashes, etc.

Todd

Yes I understand that. I dont want to have to do this because I dont
want to have to pass any variables:

yield x,y

i.e.) I want to know if there is a way to call the block such that it
knows or has access to all the local variables of the caller without
having to pass those local variables in.
--
Posted via http://www.ruby-forum.com/\.

Hi Tarek,

Yes, this is the standard behavior of blocks. Blocks are closures,
which means that they have access to the surrounding environment.

For example, this code works just fine, even though "y" is a local
variable used set outside the block and used inside the block:

···

On Nov 12, 5:59 pm, Tarek Other <cashew...@yahoo.com> wrote:

i.e.) I want to know if there is a way to call the block such that it
knows or has access to all the local variables of the caller without
having to pass those local variables in.

====

def method1(&block)
  0.upto(12) do |v|
    yield v
  end
end

def method2(y)
  method1 do |z|
    puts "#{y} * #{z} = #{y * z}"
  end
end

puts "Let's do the 3 times tables:"
method2(3)

====

I hope that helps,

Eric

====

Are you looking for on-site Ruby or Ruby on Rails training
that's been highly reviewed by former students?
http://LearnRuby.com

block.call

this is just how blocks work - they enclose the scope from which they were called

a @ http://codeforpeople.com/

···

On Nov 12, 2008, at 3:59 PM, Tarek Other wrote:

i.e.) I want to know if there is a way to call the block such that it
knows or has access to all the local variables of the caller without
having to pass those local variables in.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

One thing with locals that got me is that you have to define them first so the /parser?/ doesn't bail.

I.e

### breaks:
lamb = lambda { a+b }
a = 1
b = 2
p lamb.call

You must put a,b = nil,nil before the lambda definition :-/

( sorry for top post, on iphone just realized it, no clipboard )

···

On Nov 12, 2008, at 10:47 PM, "Eric I." <rubytraining@gmail.com> wrote:

On Nov 12, 5:59 pm, Tarek Other <cashew...@yahoo.com> wrote:

i.e.) I want to know if there is a way to call the block such that it
knows or has access to all the local variables of the caller without
having to pass those local variables in.

Hi Tarek,

Yes, this is the standard behavior of blocks. Blocks are closures,
which means that they have access to the surrounding environment.

For example, this code works just fine, even though "y" is a local
variable used set outside the block and used inside the block:

====

def method1(&block)
0.upto(12) do |v|
   yield v
end
end

def method2(y)
method1 do |z|
   puts "#{y} * #{z} = #{y * z}"
end
end

puts "Let's do the 3 times tables:"
method2(3)

====

I hope that helps,

Eric

====

Are you looking for on-site Ruby or Ruby on Rails training
that's been highly reviewed by former students?
http://LearnRuby.com

Hi and thanks to all for the help.

Can someone explain why this doesnt work

def foo
  x = 5
  yield
end

foo{puts x}

Q1) The only way to get it to work is to pass x into it when calling the
yield. Why is that, according to above the block does/should have access
to it because it is being called withing the scope of the variable

Q2) This is ultimately what I want to do (psuedo code below):

def my_function(&block)
  x = 5
  s = 15
  block.call
end

my_block = lamda{ puts "#{s+x}" }
my_function(&my_block)

But it complains about not knowing what s and x are, ie out of scope.
Why and how can this be resolved?

···

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

ara.t.howard wrote:

this is just how blocks work - they enclose the scope from which they
were called

No, they don't. They enclose the scope from where they were created.
def foo(&block)
  bar = 5
  block.call
end
will NOT make bar accessible within the block.
You can't do that. Best you can do is block.call(binding) and then get the
variables from the binding object using eval in the block, but don't do that.

HTH,
Sebastian

···

--
NP: In Flames - Dark Signs
Jabber: sepp2k@jabber.org
ICQ: 205544826

I believe with "caller" OP means the method that invokes the block. Not the bit of code where the block is defined (variable "v" in your example). And the local variables defined in the method invoking the block are *invisible* to the block unless, of course, the method invoking and defining the block is the same as in

def f
   x = 10
   b = lambda { puts x }
   b.call
end

Kind regards

  robert

···

On 13.11.2008 04:47, Eric I. wrote:

On Nov 12, 5:59 pm, Tarek Other <cashew...@yahoo.com> wrote:

i.e.) I want to know if there is a way to call the block such that it
knows or has access to all the local variables of the caller without
having to pass those local variables in.

Yes, this is the standard behavior of blocks. Blocks are closures,
which means that they have access to the surrounding environment.

Tarek Other wrote:

Q2) This is ultimately what I want to do (psuedo code below):

def my_function(&block)
  x = 5
  s = 15
  block.call
end

my_block = lamda{ puts "#{s+x}" }
my_function(&my_block)

But it complains about not knowing what s and x are, ie out of scope.
Why and how can this be resolved?

Turn it around:

  def my_function(&block)
    x = 5
    s = 15
    block.call(x,s)
  end

  my_block = lambda { |x,s| puts "#{s+x}" }
  my_function(&my_block)

This is a clean solution. my_block is a genuine function - it accepts
arguments, and returns a result.

It is possible for my_block to have access to local variables defined
within its own scope. But it's hard for it to have access to local
variables which didn't exist at the time it was created. 'def' and
'class' start their own clean scopes.

An alternative approach is using instance variables and objects, but you
may need to use instance_eval to set the context within which the
instance variables are looked up.

class MyClass
  def initialize(x=5, s=15)
    @x = x
    @s = s
  end
  def my_function(&blk)
    instance_eval(&blk)
  end
end

obj = MyClass.new
my_block = lambda { puts "#{@s+@x}" }
obj.my_function(&my_block)

But that any method calls in the lambda will also be calls to MyClass
methods, not to methods defined on the 'main' object.

···

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