Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > eval, bindings and scope

Reply
Thread Tools

eval, bindings and scope

 
 
hellfeuer@gmail.com
Guest
Posts: n/a
 
      06-22-2007
hey

i have a question:
if i do this in the top level:
> foo = lambda {p a}
> eval "a=1"
> foo.call


It doesn't work, giving me a NameError: undefined variable or method in
main:Object

but whats perhaps wierder, is if i do this:
> foo = lambda {p b}
> eval "b=1", foo
> foo.call


it gives the same error, but
> p b

now works. that is, b is bound in the global scope

now my understanding is:
1) the first version should bind 'a' in the global scope (it does), and
foo should now be able to access it (it cant)
2) the second version should bind 'b' in the context of foo's binding
therefore making it local to foo, so foo should still be able to access
b, but it should not be visible in the top level.. yet the opposite
behaviour is observed

how come?? what am i missing here?

thnx

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

 
Reply With Quote
 
 
 
 
Morton Goldberg
Guest
Posts: n/a
 
      06-22-2007
On Jun 22, 2007, at 11:33 AM, wrote:

> if i do this in the top level:
>> foo = lambda {p a}
>> eval "a=1"
>> foo.call

>
> It doesn't work, giving me a NameError: undefined variable or
> method in
> main:Object


It will work if the local variable has been defined before the Proc
object is created. That is, the local variable must exist before the
closure is made.

<code>
a = nil
foo = lambda { a }
eval("a = 42")
foo.call # => 42
</code>

Regards, Morton

 
Reply With Quote
 
 
 
 
Hell Feuer
Guest
Posts: n/a
 
      06-22-2007
hmmm.. thnx. ur right. but even accepting that thats just how closures
are, what about my second version?

> foo = lambda {p b}
> eval "b=1", foo
> foo.call


1) why does b get bound in the global scope??? shouldn't it become local
to to foo?

2) and in any case, since b=1 is being evaluated in the context of foo's
binding, and foo is being called later, shouldn't this be equivalent to
defining b before foo is called (and therefore this shouldn't give an
error)??

3) if not, what does passing foo to eval actually do, since the
behaviour seems to be the same whether or not i pass foo (i.e. the
variable is bound in the global scope, and the closure cannot see it)


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

 
Reply With Quote
 
Morton Goldberg
Guest
Posts: n/a
 
      06-23-2007
On Jun 22, 2007, at 5:57 PM, Hell Feuer wrote:

> hmmm.. thnx. ur right. but even accepting that thats just how closures
> are, what about my second version?
>
>>> foo = lambda {p b}
>>> eval "b=1", foo
>>> foo.call

>
> 1) why does b get bound in the global scope???


There is nothing in your lambda to establish a binding for b.

> shouldn't it become local to to foo?


No.

> 2) and in any case, since b=1 is being evaluated in the context of
> foo's
> binding, and foo is being called later, shouldn't this be
> equivalent to
> defining b before foo is called (and therefore this shouldn't give an
> error)??


Only assignment brings b into existence.

> 3) if not, what does passing foo to eval actually do, since the
> behaviour seems to be the same whether or not i pass foo (i.e. the
> variable is bound in the global scope, and the closure cannot see it)


The binding of the Proc object is passed to eval.

Your second example suffers from the same problem as your first.

Also, consider the following tow examples:

<code>
bar = lambda { |b| b = b }
b = 0
bar.call(42) # => 42
b # => 0
</code>

<code>
b = 0
bar = lambda { |b| b = b }
bar.call(42) # => 42
b # => 42
</code>

In the first case, b is local to the block because no previous
definition is visible, but in the second b is not local to the block
because a previous definition is visible.

Finally, here is a quote from the pickaxe book that might clarify
things for you:

<quote>
As of Ruby 1.8,local variables assigned within an eval are available
after the eval
only if they were defined at the outer scope before the eval
executed. In this way eval
has the same scoping rules as blocks.
</quote>

Regards, Morton

 
Reply With Quote
 
Sami Samhuri
Guest
Posts: n/a
 
      06-23-2007
On 6/22/07, <> wrote:
> hey

Hi!

> i have a question:

A nice one too. I learned quite a bit from it so thank you.

After reading up on procs, evals, and lambdas in the pickaxe book I
think I understand your question. This irb snippet is where I realised
exactly what was going on so maybe it will help you as well.

sjs@tuono% ruby -v
ruby 1.8.6 (2007-03-13 patchlevel 0) [x86_64-linux]
sjs@tuono% irb
irb(main):001:0> p = lambda {a=:a; binding}
=> #<Proc:0x00002b17e252f1a0@(irb):1>
irb(main):002:0> binding = p.call
=> #<Binding:0x2b17e252a2b8>
irb(main):003:0> eval "p a", binding
:a
=> nil
irb(main):004:0> p a
NameError: undefined local variable or method `a' for main:Object
from (irb):4
irb(main):005:0> eval "b=:b", binding
=> :b
irb(main):006:0> b
NameError: undefined local variable or method `b' for main:Object
from (irb):6

> 2) the second version should bind 'b' in the context of foo's binding
> therefore making it local to foo, so foo should still be able to access
> b, but it should not be visible in the top level.. yet the opposite
> behaviour is observed
>
> how come?? what am i missing here?


This is how you you would define b in a given context, local to that
context. I don't think you were misunderstanding the expected
behaviour, just the method of describing that behaviour.

sjs@tuono% irb
irb(main):001:0> p = lambda {a=:inside; binding}
=> #<Proc:0x00002b321f1aee48@(irb):1>
irb(main):002:0> binding = p.call
=> #<Binding:0x2b321f1a9c40>
irb(main):003:0> p a # this is the same as: eval "p a"
NameError: undefined local variable or method `a' for main:Object
from (irb):3
irb(main):004:0> eval "p a", binding
:inside
=> nil
irb(main):005:0> a = utside
=> utside
irb(main):006:0> b = a
=> utside
irb(main):007:0> eval "c = a", binding
=> :inside
irb(main):008:0> c
NameError: undefined local variable or method `c' for main:Object
from (irb):9
irb(main):009:0> eval "b = a", binding
=> :inside
irb(main):010:0> b
=> :inside

Hope this helps!

--
Sami Samhuri

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Lexical scope vs. dynamic scope Xah Lee Java 0 02-26-2009 10:08 AM
Having trouble understanding function scope and variable scope Andrew Falanga Javascript 2 11-22-2008 09:23 PM
Scope - do I need two identical classes, each with different scope? ann Java 13 09-13-2005 03:07 AM
How do namespace scope and class scope differ? Steven T. Hatton C++ 9 07-19-2005 06:07 PM
IMPORT STATIC; Why is "import static" file scope? Why not class scope? Paul Opal Java 12 10-10-2004 11:01 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57