Is Passing a Binding with Parameters Possible?

J

John Sikora

Does anyone know how to pass a binding using parameters instead of a
code block? Is it even possible?

For various reasons (primarily syntactic sugar implementation), I need
to eval a string in one method in the scope of another method. The
following is a simplified version of the code (which works):


def called_method(*parameters, &code_block) # code_block handler
ignored.
parameters.each do |parameter|
eval(parameter, code_block.binding)
end
end

def calling_method
a = 3
string_to_evaluate = 'puts a'
called_method(string_to_evaluate){}
end

calling_method # => 3


Obviuosly, this requires a code block for 'called_method'. In the actual
code, whenever eval is used, parameters are always present. Code blocks
are optional. So when a code block is not needed, the empty code block
has to be included.

No big deal, but it would be nice to be able to use the parameters to
pass the binding (since they are always present when eval is used). Such
as:


def called_method(*parameters, &code_block) # code_block handler
ignored.
parameters.each do |parameter|
eval(parameter, parameters.binding)
end
end

def calling_method
a = 3
string_to_evaluate = 'puts a'
called_method(string_to_evaluate)
end

calling_method # => in 'called_method' private method 'binding'
called...


So I guess .binding is a private method for objects other than code
blocks, in this case an Array. If I change 'parameters.binding' to
'binding', it (of course) does not give the right binding, resulting in
variable 'a' being undefined. I have tried some other code snippets that
I thought might work, but to no avail.

I know a binding could be created inside of calling_method and it could
be could be passed, but the way it is now with the empty braces is
easier, which is the point of syntactic sugar.

Can it be made even easier by passing the binding 'automatically' with
the parameters instead of a code block?

John S.
 
7

7stud --

John said:
Obviuosly, this requires a code block for 'called_method'. In the actual
code, whenever eval is used, parameters are always present. Code blocks
are optional. So when a code block is not needed, the empty code block
has to be included.

No big deal, but it would be nice to be able to use the parameters to
pass the binding

How about:

def called_method(*parameters, &code_block)
if block_given?
#do something

elsif
b = parameters[-1]
params = parameters[0..-2]

params.each do |param|
eval(param, b)
end

end
end

def calling_method
a = 3
string_to_evaluate = 'puts a'
called_method(string_to_evaluate, binding)
end

calling_method # => 3
 
7

7stud --

Or this:

class Parameters
def initialize(bind_ing, *parameters)
@binding = bind_ing
@parameters = parameters
end

def each
@parameters.each {|param| yield [param, @binding]}
end

end

def called_method(parameters, &code_block)
if block_given?
#do something

elsif
parameters.each do |param, bind_ing|
eval(param, bind_ing)
end

end
end

def calling_method
a = 3
b = 4
eval_str1 = 'puts a'
eval_str2 = 'puts b'
params = Parameters.new(binding, eval_str1, eval_str2)
called_method(params)
end

calling_method # => 3, 4
 
J

John Sikora

7stud said:
def calling_method
a = 3
b = 4
eval_str1 = 'puts a'
eval_str2 = 'puts b'
params = Parameters.new(binding, eval_str1, eval_str2)
called_method(params)
end

calling_method # => 3, 4

7stud,

I was hoping to be able to do it w/o having to include the binding (in
any form)in calling_method. In other words, the binding could be
'attached' to the parameters similar to a code block.

Thanks,
John S.
 
J

John Sikora

Space said:
I like lmgtfy:

http://lmgtfy.com/?q=Binding+of_caller

Kind regards,
Samuel


SST,

Thanks for the link. No one has ever accused me of being particularly
adept at conducting a web search.

Unfortunately, I feel even more ignorant because I cannot get the code
to work. At first I tried adapting the code in my post to use
Binding.of_caller. When it did not work, I tried the example code from
the link:


require
'c:/Ruby/lib/ruby/gems/1.8/gems/extensions-0.6.0/lib/extensions/binding'

def inc_counter
Binding.of_caller do |b|
eval("counter += 1", b)
end
end

counter = 0
inc_counter
inc_counter
puts counter


I get an error message that says: in 'inc_counter': undefined method '+'
for nil:NilClass. So it is not getting the correct binding. Debugging
shows that Binding.of_caller returned a binding to inc_counter.

The code in the require file matches the source code of of_caller in the
link, so at least I know that is right.

Is there something obvious am I doing wrong? I am running Ruby 1.8.6 on
Windows. I will try to educate myself by studying the source code to
figure out what is wrong, but it will take some time (if I ever get
there).

Thanks,
John S.
 
C

Caleb Clausen

Thanks for the link. No one has ever accused me of being particularly
adept at conducting a web search.

Unfortunately, I feel even more ignorant because I cannot get the code
to work. At first I tried adapting the code in my post to use

Binding.of_caller is really a hack... Don't use it. You're better off
passing a binding explicitly, like 7stud says, or implicitly in a
block, like you had originally.
 
J

John Sikora

Caleb said:
Binding.of_caller is really a hack... Don't use it. You're better off
passing a binding explicitly, like 7stud says, or implicitly in a
block, like you had originally.

Caleb,

Thanks, I'll just leave it as is.

John S.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top