Deferring proc bindings

Hi all,

I'm re-joining to the ruby-talk mailing list and this time I hope I
can get some spare time to read some threads :slight_smile:

BTW, here's my first question. It is about procs and scopes:

聽聽my_proc = lambda { |arg1| puts arg1; puts user }

AFAIK, arg1 is passed as a parameter (ie. when calling Proc#call) and user is
taken from the scope where my_proc is declared.

So, my question is: how could I do that 'user' was deferred until proc
is called?

聽聽def call_my_proc(&some_proc)
聽聽聽聽user = 'me'
聽聽聽聽some_proc.call("Hi, it's")
聽聽end

聽聽my_proc = lambda { |arg1| puts arg1; puts user }
聽聽call_my_proc(&my_proc) # "Hi, it's me"

I think I could do using eval with a string, but I'd like to solve in
block-like form.

Is that possible? Any ideas?

Thank you in advance.

路路路

--
Imobach Gonz谩lez Sosa
imobachgs at gmail dot com

my_proc = lambda { |arg1| puts arg1; puts user }

AFAIK, arg1 is passed as a parameter (ie. when calling Proc#call) and user is
taken from the scope where my_proc is declared.

More precisely, it's taken from the scope where the lambda is created.
This does not make a difference in your example but consider this:

def create
  user = "Mr. X"
  lambda { |arg1| puts arg1; puts user }
end

user = "Mrs. Smith"
my_proc = create

So, my question is: how could I do that 'user' was deferred until proc
is called?

def call_my_proc(&some_proc)
user = 'me'
some_proc.call("Hi, it's")
end

my_proc = lambda { |arg1| puts arg1; puts user }
call_my_proc(&my_proc) # "Hi, it's me"

This won't work - ever. The reason is that the binding the proc uses
is outside of the method. It will never see the local variable "user"
defined inside the method body.

I think I could do using eval with a string, but I'd like to solve in
block-like form.

Well you could but then again: what's the point? What problem are you
trying to solve? If the binding needs to be flexible then it really
is a case for a proc parameter. You would need to do the assignment
*somewhere* anyway so why not just pass the value as parameter and be
done? The closure is really more useful for preserving state from the
point in time when the proc was created:

def curry(*a, f)
  lambda {|*x| f[*a.concat(x)]}
end

irb(main):004:0> plus = lambda {|a,b| a + b}
=> #<Proc:0x10039930@(irb):4 (lambda)>
irb(main):005:0> plus2 = curry 2, plus
=> #<Proc:0x100371e4@(irb):2 (lambda)>
irb(main):006:0> puts plus2[100]
102
=> nil
irb(main):007:0>

What problem are you really trying to solve? It seems you may attempt
to use the wrong hammer. :wink:

Kind regards

robert

路路路

2011/1/12 Imobach Gonz谩lez Sosa <imobachgs@gmail.com>:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Hi Robert,

More precisely, it's taken from the scope where the lambda is created.
This does not make a difference in your example but consider this:

def create
user = "Mr. X"
lambda { |arg1| puts arg1; puts user }
end

user = "Mrs. Smith"
my_proc = create

Ok.

So, my question is: how could I do that 'user' was deferred until proc
is called?

def call_my_proc(&some_proc)
user = 'me'
some_proc.call("Hi, it's")
end

my_proc = lambda { |arg1| puts arg1; puts user }
call_my_proc(&my_proc) # "Hi, it's me"

This won't work - ever. The reason is that the binding the proc uses
is outside of the method. It will never see the local variable "user"
defined inside the method body.

Right.

I think I could do using eval with a string, but I'd like to solve in
block-like form.

Well you could but then again: what's the point? What problem are you
trying to solve? If the binding needs to be flexible then it really
is a case for a proc parameter. You would need to do the assignment
*somewhere* anyway so why not just pass the value as parameter and be
done? The closure is really more useful for preserving state from the
point in time when the proc was created:

def curry(*a, f)
lambda {|*x| f[*a.concat(x)]}
end

irb(main):004:0> plus = lambda {|a,b| a + b}
=> #<Proc:0x10039930@(irb):4 (lambda)>
irb(main):005:0> plus2 = curry 2, plus
=> #<Proc:0x100371e4@(irb):2 (lambda)>
irb(main):006:0> puts plus2[100]
102
=> nil
irb(main):007:0>

What problem are you really trying to solve? It seems you may attempt
to use the wrong hammer. :wink:

Yeah, you're right. Sure I'm using the wrong approach :slight_smile: Indeed, I
think I've found my way through a totally different approach.

Kind regards

Thank you for your instructive response! :slight_smile:

路路路

2011/1/12 Robert Klemme <shortcutter@googlemail.com>:

2011/1/12 Imobach Gonz谩lez Sosa <imobachgs@gmail.com>:

--
Imobach Gonz谩lez Sosa
imobachgs at gmail dot com