kernal::binding problem

T

Tom Cloyd

Trying this for the first time, and, as usual, not quite getting it.

Everything I can find on kernal::binding tells me that I just call it
and will get back a binding object which can be passed in a call to
eval. But...it doesn't work for me.

In my main, I have a module required which contains a method I'm trying
to call. For reasons irrelevant to this current problem, I'm using an
eval of a string to do it, and want the method to execute in the
environment of the main program. So...

eval( "moduleName.methodName", binding)

Causes *crash* due to by attempt to access a variable which exists in
the calling environment but not in the module. In spite of passing the
binding, the method knows nothing of the variable. It's not working.

All examples I can find just do something like..

def meth_x
y = 1
return binding
end

Then 'y' is accessed using the binding. Well, if one can return a
binding to initialize a variable -

z = meth_x
eval( "y", z ) # => "1"

Then why can't I simply pass 'binding' in an eval call FROM the calling
environment?

I must be missing something, to state the obvious.

Can someone explain?

Thanks,

t.

--

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
Bellingham, Washington, U.S.A: (360) 920-1226
<< (e-mail address removed) >> (email)
<< TomCloyd.com >> (website)
<< sleightmind.wordpress.com >> (mental health weblog)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
J

Joel VanderWerf

Tom said:
Trying this for the first time, and, as usual, not quite getting it.

Everything I can find on kernal::binding tells me that I just call it
and will get back a binding object which can be passed in a call to
eval. But...it doesn't work for me.

In my main, I have a module required which contains a method I'm trying
to call. For reasons irrelevant to this current problem, I'm using an
eval of a string to do it, and want the method to execute in the
environment of the main program. So...

eval( "moduleName.methodName", binding)

Causes *crash* due to by attempt to access a variable which exists in
the calling environment but not in the module. In spite of passing the
binding, the method knows nothing of the variable. It's not working.

All examples I can find just do something like..

def meth_x
y = 1
return binding
end

Then 'y' is accessed using the binding. Well, if one can return a
binding to initialize a variable -

z = meth_x
eval( "y", z ) # => "1"

Then why can't I simply pass 'binding' in an eval call FROM the calling
environment?

You've got something like this, right?

module M
def M.meth
p x
end
end

x = 1
eval "M.meth", binding # Undefined variable x


The binding that you pass into eval here only affects variables that are
unbound in the string. In this case there are none. The x in M.meth is a
bound variable in the scope of the method. Compare:

module M
def M.meth arg
p arg
end
end

x = 1
eval "M.meth(x)", binding # ==> 1

Also:

x = 1
eval %{
p x # ==> 1
def foo
p defined?(x)
end
foo # ==> nil
}, binding

Of course, it's quite possible I didn't understand the question...

What are you trying to do?
 
R

Rick DeNatale

Tom Cloyd wrote:

You've got something like this, right?

module M
=A0def M.meth
=A0 =A0p x
=A0end
end

x =3D 1
eval "M.meth", binding # Undefined variable x


The binding that you pass into eval here only affects variables that are
unbound in the string. In this case there are none. The x in M.meth is a
bound variable in the scope of the method.

And to stress the obvious

eval "some string"

which uses the current binding, is exactly equivalent to

eval "some string", binding

Assuming that binding is a call to Kernel#binding and not a local variable.

So

eval "M.meth"
and
eval "M.meth", binding

will both do the same thing, including throwing any exceptions.

--=20
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
 
T

Tom Cloyd

Joel said:
You've got something like this, right?

module M
def M.meth
p x
end
end

x = 1
eval "M.meth", binding # Undefined variable x Yes,


The binding that you pass into eval here only affects variables that
are unbound in the string.
Man. Never read THAT anywhere else. Seems like essential information to
associate with 'binding' method documentation, but it doesn't seem to
be, anywhere I've looked.
In this case there are none. The x in M.meth is a bound variable in
the scope of the method. Compare:

module M
def M.meth arg
p arg
end
end

x = 1
eval "M.meth(x)", binding # ==> 1
Interesting example. But it puzzles me. Why isn't 'x' considered bound
in the scope of self? It's then passed in to M.meth as an argument, so
why is 'binding' needed at all in this case? I don't understand why you
did it this way - can you explain?
[...]

What are you trying to do?
I'm trying to execute a module method in the namespace of my main
program which calls it. In outline:

I have a class which requires two files, each of which contains a
module. I then include each module:

utilname = '../lib/setnet/Utils_' + File.basename( name ) + '.rb'
#'name' passed in when class in instantiated
if File.exist?( utilname ) # it may not exist
require utilname
include Utils_db
end
require '../lib/setnet/Utilities' # will always exist
include Utils

While I haven't found any authority who says this, it appears that
'include' can only occur at the top of a class definition. I only just
figured this out, so I have about an hour+ experience with 'include'.

I thought the 'include' would essentially move my module methods into my
main, as if they were physically there already. But that's not
happening. I still have my namespace isolation problem:

When I call a module method from my main, it executes fine, until it
tries to access a variable which would be plainly available of the
module code were physically residing my class. It then crashes, as it
finds only 'nil'.

I don't know how to fix this. I thought using 'include' would do it, but
it seems to have no effect.

I don't want to just pass the method the data it needs, since in theory
I won't know what that is. I want the method to take care of itself - to
just have access to the calling program's namespace, which would solve
all problems.

Can anyone suggest a solution?

Tom
 
T

Tom Cloyd

Rick said:
And to stress the obvious

eval "some string"

which uses the current binding, is exactly equivalent to

eval "some string", binding

Assuming that binding is a call to Kernel#binding and not a local variable.

So

eval "M.meth"
and
eval "M.meth", binding

will both do the same thing, including throwing any exceptions.
So, how do I get M.meth to execute in the namespace of my main? I
thought 'binding' packaged up that namespace and I could then pass it to
the method. Wrong, apparently.

I want M.meth to have access to all variables in main's namespace -
well, instance variables, anyway. How do I do that?

t.
 
C

Christopher Dicely

So, how do I get M.meth to execute in the namespace of my main? I thought
'binding' packaged up that namespace and I could then pass it to the meth=
od.

No, it packages it so you can pass it to eval, which is useful if you
want to call eval from a different point than where you capture the
binding.
I want M.meth to have access to all variables in main's namespace - well,
instance variables, anyway. How do I do that?

If you want to access instance variables from the calling scope inside
a method call (on a different object), you could pass self from the
calling point as an argument to the method, and use instance_eval in
the method. E.g.:

irb(main):001:0> module M
irb(main):002:1> def M.meth
irb(main):003:2> end
irb(main):004:1> end
=3D> nil
irb(main):005:0> module M
irb(main):006:1> def M.meth(target)
irb(main):007:2> puts target.instance_eval { @foo }
irb(main):008:2> end
irb(main):009:1> end
=3D> nil
irb(main):010:0> class C
irb(main):011:1> def initialize(val)
irb(main):012:2> @foo =3D val
irb(main):013:2> end
irb(main):014:1> def test
irb(main):015:2> M.meth(self)
irb(main):016:2> end
irb(main):017:1> end
=3D> nil
irb(main):018:0> c =3D C.new(1)
=3D> #<C:0x2bbd440 @foo=3D1>
irb(main):019:0> c.test
1
=3D> nil
 
T

Tom Cloyd

Christopher said:
No, it packages it so you can pass it to eval, which is useful if you
want to call eval from a different point than where you capture the
binding.



If you want to access instance variables from the calling scope inside
a method call (on a different object), you could pass self from the
calling point as an argument to the method, and use instance_eval in
the method. E.g.:

irb(main):001:0> module M
irb(main):002:1> def M.meth
irb(main):003:2> end
irb(main):004:1> end
=> nil
irb(main):005:0> module M
irb(main):006:1> def M.meth(target)
irb(main):007:2> puts target.instance_eval { @foo }
irb(main):008:2> end
irb(main):009:1> end
=> nil
irb(main):010:0> class C
irb(main):011:1> def initialize(val)
irb(main):012:2> @foo = val
irb(main):013:2> end
irb(main):014:1> def test
irb(main):015:2> M.meth(self)
irb(main):016:2> end
irb(main):017:1> end
=> nil
irb(main):018:0> c = C.new(1)
=> #<C:0x2bbd440 @foo=1>
irb(main):019:0> c.test
1
=> nil
Thanks! That's very interesting, and is exactly what I was looking for.
I was beginning to think it wasn't possible. I would not likely soon
have found this solution on my own, so I'm very grateful for your
assistance. Thanks for taking the time to respond.

t.

--

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
Bellingham, Washington, U.S.A: (360) 920-1226
<< (e-mail address removed) >> (email)
<< TomCloyd.com >> (website)
<< sleightmind.wordpress.com >> (mental health weblog)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

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

No members online now.

Forum statistics

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

Latest Threads

Top