Hi Arup Rakshit,
The Ruby documentation gives a clue ...
class_eval(string [, filename [, lineno]]) → obj
Evaluates the string or block in the context of mod, except that when
a block is given, constant/class variable lookup is not affected.
Source: Class: Module (Ruby 2.1.0)
So, when you do
Foo.class_eval { @@x }
.. with a block given, the scope of @@x doen't change and @@x is
"scoped" on Object.
I try to think this as simply as an iterator having access to the
surrounding local vars.
collection = [ "bananas", "oranges", "apples"]
local_var = "I like "
collection.each { |fruit| puts local_var + fruit }
So, class_eval just "try" to get the "@@x" from the outermost context
(not inside the Foo class).
class Foo
@@x = 10
end
# The context where this @@x bellow is it is Object
Foo.class_eval { @@x }
# => NameError: uninitialized class variable @@x in Object
class Bar
Foo.class_eval { @@x }
end
# => NameError: uninitialized class variable @@x in Bar
# Inside the "class Bar" definition, @@x is scoped on Bar, not Object.
More...
At Dave Thomas book we can read...
"Class variables belong to the innermost enclosing class or module.
Class variables used at the top level are defined in Object, and
behave like global variables. Class variables defined within singleton
methods belong to the receiver if the receiver is a class or a module;
otherwise, they belong to the class of the receiver."
Source: Programming Ruby: The Pragmatic Programmer's Guide
In a newer version it says "Class variables defined within singleton
methods belong to the top level (although this usage is deprecated and
generates a warning)."
# Try this also:
class Foo
@@x
end
# I think this is like class_eval with a String
Foo.class_eval("@@x")
class << Foo # The eingenclass of the Foo class
@@x
end
# (ruby 1.8.7) warning: class variable access from toplevel singleton method
# (ruby 2.1.0) warning: class variable access from toplevel
# NameError: uninitialized class variable @@x in Object
# I think this is like class_eval with a block
Foo.class_eval { @@x }
More important than the above is to remember that we should favor
class instance variables rather than class variables when possible.
http://jvans1.github.io/blog/2013/01/06/class-variables-vs-class-instance-variables/
It's just less complicated! ![:wink: :wink:](https://emoji.discourse-cdn.com/twitter/wink.png?v=12)
Abinoam Jr.
···
On Fri, Jan 3, 2014 at 9:11 PM, Ryan Cook <cookrn@gmail.com> wrote:
Here's a snippet I wrote while playing around:
class Foo; class_eval{ @@x }; end
=> 10
This leads me to believe it might be a scoping or lookup issue? There seems
to be a rule at play here that I can't put my finger on. I'm a bit confused
only because the following works:
class Foo; @x = 42; end
=> 42
Foo.class_eval{ @x }
=> 42
On Fri, Jan 3, 2014 at 2:15 PM, Arup Rakshit <lists@ruby-forum.com> wrote:
class Foo
@@x = 10
end
Foo.class_eval('@@x') # => 10 # Part-I
Foo.class_eval{ @@x } # => # Part - II
# ~> -:5:in `block in <main>': uninitialized class variable @@x in
Object (NameError)
# ~> from -:5:in `class_eval'
# ~> from -:5:in `<main>'
Why does Part-I and Part-II behave differently ?
--
Posted via http://www.ruby-forum.com/\.
--
Ryan Cook
720.319.7660