I can define an anonymous class within an anonymous module:
c = nil
m = Module.new do
c = Class.new
end
m #=> #<Module:0x007fad3a055660>
c #=> #<Class:0x007fad3a0555e8>
Is the above equivalent to:
m = Module.new
c = Class.new
In other words: does the concept of "nesting" actually apply to anonymous modules?
It is not about being anonymous. Assigning a dynamically created class to a constant makes it named:
Foo = Class.new # => Foo
foo = Class.new # => #<Class:0x007fe5dd45d650>
Yet it still doesn't nest further:
module Bar
Baz = Module.new do
p Module.nesting # => [Bar]
end
end
Or even about being dynamic for that matter:
module Quz
eval 'module Qux; p Module.nesting; end' # => [Quz::Qux, Quz]
end
It's about scope gates.
As far as constants are concerned, there are only two scope gates - the keywords class and module.
Nesting is done purely syntactically. That is why you get the weird:
module Do
X = 42
end
module Do
module Re
p Module.nesting # => [Do::Re, Do]
p X # => 42
end
end
module Do::Mi
p Module.nesting # => [Do::Mi]
p X # => uninitialized constant
end
Do.module_eval { p X } # => uninitialized constant
Do.instance_eval { p X } # => uninitialized constant
So if Ruby sees the keywords class or module, it nests the "current node" further. When the closing end is found, it goes up the tree. When a new constant is being defined, it places it in the current node.
Related
My understanding of instance_eval was that if I have module M then the following were equivalent:
module M
def foo
:foo
end
end
class C
class << self
include M
end
end
puts C.foo
equivalent to:
module M
def foo
:foo
end
end
class C
end
C.instance_eval do
include M
end
puts C.foo
However, the first example prints :foo and the second throws a NoMethodError? (Ruby 2.3.0)
In both cases above, if I had replaced:
include M
with:
def foo
:foo
end
ie directly defining the method rather than including a module then both cases would have resulted in a C.foo method being defined. Should I be surprised at this difference between include and defining the method directly?
Or does it ever even make sense to call include within the context of instance_eval? Should it only ever be called within a class_eval?
In each of these cases, what object are you calling include on? In your first example, you're calling include on C's singleton class:
class C
class << self
p self == C.singleton_class
include M
end
end
# => true
p C.foo
# => :foo
...so your include line is equivalent to C.singleton_class.include(M).
In your second example, however, you're calling include on C itself:
class C
end
C.instance_eval do
p self == C
include M
end
# => true
p C.foo
# => NoMethodError: undefined method `foo' for C:Class
p C.new.foo
# => :foo
...so you're doing the equivalent of C.include(M), which is the same as:
class C
p self == C
include M
end
# => true
p C.new.foo
# => :foo
What would work like you want would be to call instance_eval on C's singleton class:
class D
end
D.singleton_class.instance_eval do
p self == D.singleton_class
include M
end
# => true
p D.foo
# => :foo
Module#class_eval() is very different from Object#instance_eval(). The instance_eval() only changes self, while class_eval() changes both self and the current class.
Unlike in your example, you can alter class_instance vars using instance_eval though, because they are in the object scope as MyClass is a singleton instance of class Class.
class MyClass
#class_instance_var = 100
##class_var = 100
def self.disp
#class_instance_var
end
def self.class_var
##class_var
end
def some_inst_method
12
end
end
MyClass.instance_eval do
#class_instance_var = 500
def self.cls_method
##class_var = 200
'Class method added'
end
def inst_method
:inst
end
end
MyClass.disp
#=> 500
MyClass.cls_method
#=> 'Class method added'
MyClass.class_var
#=> 100
MyClass.new.inst_method
# undefined method `inst_method' for #<MyClass:0x0055d8e4baf320>
In simple language.
If you have a look in the upper class defn code as an interpreter, you notice that there are two scopes class scope and object scope. class vars and instance methods are accessible from object scope and does not fall under jurisdiction of instance_eval() so it skips such codes.
Why? because, as the name suggests, its supposed to alter the Class's instance(MyClass)'s properties not other object's properties like MyClass's any object's properties. Also, class variables don’t really belong to classes—they belong to class hierarchies.
If you want to open an object that is not a class, then you can
safely use instance_eval(). But, if you want to open a class definition and define methods with def or include some module, then class_eval() should be your pick.
By changing the current class, class_eval() effectively reopens the class, just like the class keyword does. And, this is what you are trying to achieve in this question.
MyClass.class_eval do
def inst_method
:inst
end
end
MyClass.new.inst_method
#=> :inst
How can I programmatically get the class on which the currently executing code is defined? I need to find the class when control flow runs through multiple method definitions due to super():
class A
def foo
puts(get_current_class)
end
end
class B < A
def foo
puts(get_current_class)
super
end
end
class C < B
def foo
puts(get_current_class)
super
end
end
C.new.foo
# => C
# => B
# => A
I know how to get the method name (using __callee__, caller_locations or __method__); but what about the class?
Since classes in ruby are also modules, this could be achieved with Module#nesting:
class A
def foo
puts(Module.nesting.first)
end
end
class B < A
def foo
puts(Module.nesting.first)
super
end
end
class C < B
def foo
puts(Module.nesting.first)
super
end
end
C.new.foo
# => C
# => B
# => A
Alternatively, if the goal is to construct a list of which methods may be called by the object's ancestor chain, then you could use Method#owner and Method#super_method (available since ruby version 2.2.0):
c = C.new
c.method(:foo).owner # => C
c.method(:foo).super_method.owner # => B
c.method(:foo).super_method.super_method.owner # => A
c.method(:foo).super_method.super_method.super_method # => nil
As a quick off-the-cuff implementation to programatically print all classes then, how about:
c = C.new
method = c.method(:foo)
while(method)
puts m.owner
method = method.super_method
end
# => C
# => B
# => A
(However, there is no guarantee that all of these methods will actually be invoked - as this is determined at runtime via super!)
Is there my L constants?
module M
class Z
class << self
L = "foo"
end
end
end
=> M::Z::L
=> NameError: uninitialized constant M::Z::L
=> M::Z.constants
=> []
module B
class N
X = "bar"
end
end
=> B::N::X
=> "bar"
=> B::N.constants
=> [:X]
I read this but I do not understand.
You need to do as :
module M
class Z
class << self
L = "foo"
end
end
end
M::Z.singleton_class::L # => "foo"
L is defined inside the singleton class of Z.
"L" is stored in the set of constants of the singleton class of M::Z, You may call it S for now. M::Z::L it actually is searching this constant L, in the constant table of M::Z and its ancestors. since none of them is S, the look-up fails.
I thought there were no differences between methods declared within a class << self block and those declared with a self. prefix, but there are:
module A
VAR = 'some_constant'
end
class B
extend A
class << self
def m1
puts VAR
end
end
def self.m2
puts VAR
end
end
B.m1 # => OK
B.m2 # => uninitialized constant B::VAR
Why are constants of A available in m1 but not in m2?
In Ruby, constant lookup is not the same as method lookup. For method lookup, calling foo is always the same as calling self.foo (assuming it isn't private). Calling a constant FOO is very different from self::FOO or singleton_class::FOO.
Using an unqualified constant (e.g. FOO) will do a lookup in the currently opened modules. A module is opened with module Mod, class Klass, class << obj, or module_eval and variants. When defining m1, these are B, and then B.singleton_class. When defining m2, only B is opened.
module Foo
X = 42
class Bar
def self.hello
X
end
end
end
In this code, Foo::Bar.hello will return 42, even though X is not a constant of Bar, its singleton class or ancestor. Also, if you later add a constant X to Bar, then that value will be returned. Finally, the following definition is not equivalent:
module Foo
X = 42
end
class Foo::Bar
def self.hello
X
end
end
Foo::Bar.hello # => uninitialized constant Foo::Bar::X
Indeed, when hello is defined, only the class Foo::Bar is opened, while in the previous example, both Foo and Foo::Bar where opened.
A last example, to show the difference an explicit scope can have with inheritance:
class Base
X = 42
def self.foo
X
end
def self.bar
self::X
end
end
class Parent < Base
X = :other
end
Parent.foo # => 42
Parent.bar # => :other
In your case, you probably want to include your module, instead of extending it, no?
Otherwise, you could use singleton_class::VAR, your code will work as you expect it.
module A
VAR = 'some_constant'
end
class B
extend A
class << self
def m1
puts singleton_class::VAR # not necessary here, as singleton_class is opened
end
end
def self.m2
puts singleton_class::VAR # necessary here!
end
end
B.m1 # => OK
B.m2 # => OK
I'm new to programming. Right now I'm studying Ruby. To my understanding, global variables are defined in the global namespace (so outside of any classes or functions). I'm reading something and it says global variables have a $ sign before them. What does that mean? Does it mean when I define a function or class and want to reference my global variable (let's say it is edmund = 123) I would have to reference it like this: $edmund?
so:
edmund = 123
def my_function()
456 + $edmund
end
Also are class variables (the ones that begin with ##) like instance variables (#) where you can access them by calling them through Class.classvariable? What is their purpose?
Global scope is scope that covers the entire program. Global scope is enjoyed by global variables, which are recognizable by their initial dollar-sign ($) character. They’re available everywhere and creating your own global variables can be tempting, especially for beginning programmers. But they’re not always a good idea.
$gvar = "I'm a global!"
class C
def examine_global
puts $gvar
end
end
c = C.new
c.examine_global # I'm a global!
Class variables begin with two at signs: ##var, for example. Despite their name, class variables aren’t class scoped. Rather, they’re class-hierarchy scoped. At its simplest, the idea behind a class variable is that it provides a storage mechanism that’s shared between a class and instances of that class, and that’s not visible to any other objects.
class Parent
##value = 100
end
class Child < Parent
##value = 200
end
class Parent
puts ##value
end
What gets printed is 200. The Child class is a subclass of Parent, and that means Parent and Child share the same class variables—not different class variables with the same names, but the same actual variables. When you assign to ##value in Child, you’re setting the one and only ##value variable that’s shared throughout the hierarchy—
that is, by Parent and Child and any other descendant classes of either of them.
And to give credit where its due - This explanation comes from "The Well Grounded Rubyist" by David A Black, one of the best resources to learn about Ruby.
Excellent question. Unfortunately, you just jumped down a rabbit hole, but it's one that you have to fall through eventually in ruby to start understanding the real intricacies.
For your first question, regarding the $-prefixed global variables. They are truly global:
def mk_foo() $foo ||= "foo"; end
$foo # => nil
mk_foo # => "foo"
$foo # => "foo"
mk_foo.object_id # => 70299647799620
$foo.object_id # => 70299647799620
As you can see, when $foo is defined within the mk_foo method, it is defined in the global space, and you can access it anywhere:
class CanSeeFoo
def see_foo() $foo; end
end
CanSeeFoo.new.can_see_foo
# => "foo"
CanSeeFoo.new.can_see_foo.object_id
# => 70299647799620
As for the class variable question, this is where the rabbit-hole begins. First, you are correct that ##-prefixed variables are referred to as "class variables" and #-prefixed variables are referred to as "instance variables".
Class variables are static across all subclasses (at all sub-levels of the inheritance tree) of the defining class. The implication here is that if any subclass changes the class variable, it will change in all related subclasses and up to the defining class.
class A; end
class B < A; ##foo = "foo"; end
B.class_variable_get(:##foo) # => "foo"
A.class_variable_get(:##foo)
# => raises NameError "uninitialized class variable ##foo in A"
class C < B; end
C.class_variable_get(:##foo) # => "foo"
class D < C
def self.change_foo(); ##foo = "bar"; end
def change_foo(); ##foo = "baz"; end
end
D.class_variable_get(:##foo) # => "foo"
class E < D; end
E.class_variable_get(:##foo) # => "foo"
D.change_foo # => "bar"
D.class_variable_get(:##foo) # => "bar"
E.class_variable_get(:##foo) # => "bar"
C.class_variable_get(:##foo) # => "bar"
B.class_variable_get(:##foo) # => "bar"
D.new.change_foo # => "baz"
D.class_variable_get(:##foo) # => "baz"
E.class_variable_get(:##foo) # => "baz"
C.class_variable_get(:##foo) # => "baz"
B.class_variable_get(:##foo) # => "baz"
A.class_variable_get(:##foo)
# => raises NameError "uninitialized class variable ##foo in A"
As for accessing class and instance variables, neither is accessible without the use of #instance_variable_get or ::class_variable_get until an accessor is defined. At present, ruby only has methods for defining accessors on instance variables, but it is simple enough to define the appropriate methods for the class variables:
class A
##foo = "foo"
# the second argument `true` adds the writer method `#bar=`
attr :bar, true
def self.foo(); ##foo; end
def self.foo=(v); ##foo = v; end
def initialize()
#bar = "bar"
end
end
class B < A; end
A.foo # => "foo"
B.foo = "foobar"
A.foo # => "foobar"
B.foo # => "foobar"
a = A.new
a.bar # => "bar"
a.bar = "baz"
a.bar # => "baz"
a.foo
# => raises NoMethodError: undefined method `foo' for #<A:0x ...
You can see the attribute accessor methods here in the ruby core docs: http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-attr. Also, ActiveSupport (http://rubygems.org/gems/activesupport) has "cattr" methods for defining class variable accessors http://api.rubyonrails.org/v3.2.5/classes/Class.html#method-i-cattr_accessor.
That's the simple stuff. The next step is understanding the "singleton class" also known as the "eigenclass" or "metaclass" (Wikipedia: Metaclass) (remember, everything in ruby is an Object, including the Class and Module constructs). Here I will point you to an excellent post by Yehuda Katz: Metaprogramming in Ruby: It’s All About the Self, and another Stack Overflow question: class << self idiom in Ruby.
As a preview: The singleton class (not to be confused with the singleton design pattern) allows you to access methods and instance data for a specific class or module. For some related documentation, see the core docs: http://www.ruby-doc.org/core-1.9.3/Object.html#method-i-singleton_class
class A; end
class B < A;
class << self
def foo() #foo end
def foo=(v) #foo = v; end
end
end
B.foo = "foo"
class C < B; end
A.foo
# => raises NoMethodError: undefined method `foo' for A:Class
B.foo # => "foo"
C.foo # => nil
B.foo = "baz"
B.foo # => "baz"
C.foo # => nil
C.foo = "foo"
C.foo # => "foo"
B.foo # => "baz"
Lastly, remember to make use of the Ruby-Core docs. Most useful for understanding the above are:
http://www.ruby-doc.org/core-1.9.3/Object.html
http://www.ruby-doc.org/core-1.9.3/Module.html
http://www.ruby-doc.org/core-1.9.3/Class.html
The dollar sign is part of the variable name, so it has to be declared like this:
$edmund = 123
This is the same things for the instance and class variables: their names begin with # or ##.