In a tutorial, there are examples querying constants using const_get:
class This
end
p Module.const_get('This').new
and
A_CONSTANT = 42
p Module.const_get('A_CONSTANT')
I can't see any module definition. Why is Module used? Why isn't const_get('This') or self.const_get('This') enough? The class where all this is written in is Object, ancestor of BasicObject.
Does the fact that This is a constant mean that it holds the class definition inside of it? Like as it just could hold the number 42? Or to be clearer, is it the same as:
This = class
end
like an unnamed method so I can write p This and get the class definition?
Some nice knowledge you have acquired. But I don't know why are you mentioning metaprogramming in your title, when your question is all about constants. Metaprogramming is something else.
In any case, #const_get is an instance method of Module class, so it won't work at the top level, where the implicit receiver is of Object class. When you write
class Foo; end
Constant Foo gets added to Object:
Object::Foo #=> Foo
Object::Bar #=> error (we didn't define constant Bar)
This constant is available also in other classes, such as
Module::Foo #=> Foo, but with a warning
Array::Foo #=> same Foo with the same warning
Fixnum::Foo #=> ditto
In other words, your Foo defined at toplevel is visible from almost every module. But accessing toplevel constants like this is frowned upon, as this is often not what the programmer intended. You can indeed see that the constant is defined on Object:
Object.constants( false ).include? :Foo #=> true
and not on eg. Module:
Module.constants( false ).include? :Foo #=> false
However, if you use #const_get, the warning message is suppressed and you may come to think that Module::Foo actually exists:
Module.const_get( :Foo ) #=> Foo
It doesn't.
Related
To test, whether a constant (say: a class) is known at a certain point in the code, I can write for instance:
if defined? :String
or I can write
if self.class.const_defined? :String
Is there a situation where I these two ways of testing would make a difference? Note that I don't ask about the case where I have an explicit receiver, such as MyModule.const_defined? :Something, but only for the case where I want to test whether a certain constant (which in my case happens to be a constant denoting a class) is already defined.
First things first, defined? is a keyword which behaves a bit similar similar to a method. It receives the name of the thing (variable, constant, ...) to check. What makes this method different from all others is that the parser will not resolve the value of the given name but rather check directly for whether it is defined (hence the keyword property). To check if a constant is defined, you thus have to pass the actual name (rather than a Symbol):
if defined?(String)
The const_defined? on the oither hand is more regular. It expects a Symbol or String with the name of a constant and checks whether it is defined on the receiver.
Now as for the differences between the two (when used correctly): if you use them both within the context of an instance method to check for the existence of a constant, they work the same.
When running e.g. in a class definition (such that self is e.g. a class), you need to make sure to use the correct receiver for your const_defined method, e.g. if self.const_defined? :String.
Also, defined? can check for a lot more than just constants (e.g. methods, expressions, variables, ...)
If you want to use this to make sure you actually have the name of a constant at hand in a given variable, you need to use const_defined?. If you want to "statically" check whether an constant was defined, you can use defined?.
defined? is a keyword that will check if an expression exists in the current scope.
const_defined? is a method that will check if a constant exists through the ancestor chain of the receiver.
planet = "Earth"
class Experiment
def diff
""
end
def show
puts "defined" if defined?(diff)
puts "Earth not found" if !defined?(planet)
puts "String constant defined" if self.class.const_defined?(:String)
end
end
Experiment.new.show
#=> defined
#=> Earth not found
#=> String constant defined
p Experiment.ancestors #=> [Experiment, Object, Kernel, BasicObject]
p String.superclass #=> Object
Here's an example of situations where this will make a difference:
Using defined?(Nothing's printed)
class Lab
class Coco
end
end
class Experiment
def diff
""
end
def show
puts "defined" if defined?(Coco) #=> Nothing printed
end
end
Experiment.new.show
Using self.class.const_defined? (Something's printed)
class Lab
class Coco
end
end
class Experiment < Lab
def diff
""
end
def show
puts "defined" if self.class.const_defined? :Coco #=> defined
end
end
Experiment.new.show
p Experiment.ancestors #=> [Experiment, Lab, Object, Kernel, BasicObject] We find 'Lab' class in the ancestor chain.
To test, whether a constant (say: a class) is known at a certain point in the code, I can write for instance:
if defined? :String
or I can write
if self.class.const_defined? :String
Is there a situation where I these two ways of testing would make a difference?
These two really do two completely different things. The first tests whether the Symbol literal :String is defined. Obviously, a literal will always be defined, so this expression will always be true.
The second will check whether the constant String is defined, but not starting at the current constant lookup scope, instead starting at the class of self.
TL;DR
There may be cases where you can use them interchangeably, but one is a keyword and the other a method. In addition, the semantics and return values of the two are quite different.
Keywords vs. Methods
Among other things, one key difference is that Module#const_defined? is a method on a class or module that looks up constants in a class and its ancestors, while defined? is a keyword that determines whether its argument is currently known at the calling point in your code.
For example:
char = 'a'
char.const_defined?
#=> NoMethodError (undefined method `const_defined?' for "a":String)
defined? char
#=> "local-variable"
Exceptions vs. Return Values
If you're only concerned about constants, then the main difference is that you can use defined? to determine whether a constant is currently in scope without triggering a NoMethodError exception. For example:
defined? String
#=> "constant"
defined? FooBarBaz
#=> nil
As a bonus, defined? will tell what type of object you're passing as an argument (e.g. "constant"), while #const_defined? returns a truthy value.
Float.constants
#=> [:ROUNDS, :RADIX, :MANT_DIG, :DIG, :MIN_EXP, :MAX_EXP, :MIN_10_EXP, :MAX_10_EXP, :MIN, :MAX, :EPSILON, :INFINITY, :NAN]
defined? Float::NAN
#=> "constant"
Float.const_defined? :NAN
#=> true
As a rule of thumb, it's often considered best practice to reserve exceptions for handling something unexpected that may require your application to halt. Introspection or branching should generally rely on return values or Booleans, so defined? is usually a better choice if you aren't already expecting a given class to already be defined and available within the current scope.
Is there a situation where I these two ways of testing would make a difference?
const_defined? only checks the receiver and its ancestors, but it doesn't take the current module nesting into account:
module Foo
ABC = 123
class Bar
def self.test
p defined?(ABC) #=> "constant"
p const_defined?(:ABC) #=> false
end
end
end
In order to do so, you have to traverse Module.nesting:
module Foo
ABC = 123
class Bar
def self.test
p defined?(ABC) #=> "constant"
p Module.nesting.any? { |m| m.const_defined?(:ABC) } #=> true
end
end
end
I have recently discovered that Ruby (2.2.1) has some "interesting" behavior.
module Foo
class Foo
end
class Bar
end
end
Foo.const_get('Foo') #=> Foo::Foo
Foo.const_get('Bar') #=> Foo::Bar
Foo.const_get('Foo::Foo') #=> Foo
Foo.const_get('Foo::Bar') #=> NameError: uninitialized constant Foo::Foo::Bar
Foo.const_get('Foo::Foo::Bar') #=> Foo::Bar
Foo.const_get('Foo::Foo::Foo::Bar') #=> NameError: uninitialized constant Foo::Foo::Bar
Foo.const_get('Foo::Foo::Foo::Foo::Bar') #=> Foo::Bar
Foo.const_get('Foo::Foo::Foo') #=> Foo::Foo
Foo.const_get('Foo::Foo::Foo::Foo') #=> Foo
Foo.const_get('Foo::Foo::Foo::Foo::Foo') #=> Foo::Foo
Foo.const_get('Foo::Foo::Foo::Foo::Foo::Foo') #=> Foo
This is a bit surprising. My understanding has been that const_get first looks for a constant in the receiver's collection of constants and then looks at Object's constants. OK, fine. Why then does the fourth Foo#const_get above fail and the third one doesn't?
I'm also curious as to why calling Foo#const_get alternates between the module and class depending on how many ::Foos you add.
The docs say:
This method will recursively look up constant names if a namespaced class name is provided.
So Foo.const_get('Foo::Bar') is basically the same as Foo.const_get('Foo').const_get('Bar'). Using this interpretation your results make sense.
Your third example:
Foo.const_get('Foo::Foo')
is the same as
Foo.const_get('Foo').const_get('Foo')
The first const_get looks at constants defined within the top level Foo (the module), and finds the nested class. So the whole thing effectively becomes:
Foo::Foo.const_get('Foo')
The second call then looks at the class, first looking the any contained constants (finding none) and then looking in its ancestors. Object is an ancestor, and has the top level Foo module as a constant, so this is found and returned.
This also explains the alternation when adding extra ::Foos. The alternation is between const_get on the top level module finding the nested class, and on the nested class looking up the inheritance chain and finding the top level module.
The fourth example, Foo.const_get('Foo::Bar'), which raises an exception, can also be explained. It is equivalent to
Foo.const_get('Foo').const_get('Bar')
The first part, Foo.const_get('Foo') is the same as the case above, evaluating to Foo::Foo, so the whole thing now effectively becomes:
Foo::Foo.const_get('Bar')
Now the nested Foo class doesn’t contain a Bar constant, and looking up the inheritance chain, neither does Object, so the result is a NameError.
I made a class with a constant & a method:
class A
FOO = 'hello'
def bar
puts FOO
end
end
A.new.bar
=> 'hello'
And everything works as expected. However when I do this:
A.class_eval do
def bar
puts FOO
end
end
A.new.bar
NameError: uninitialized constant FOO
Weirdness... To get around this I'm doing:
A.class_eval do
def bar
puts self.class::FOO
end
end
Any good explanation on why this is so?
Constants are looked up
outwards in the lexically enclosing module declarations
upwards in the inheritance chain of the current module declaration
So, let's just do what Ruby does:
look outwards in the lexically enclosing module declarations: easy – there are no module declarations
look upwards from the current module declaration: again, there is no current module declaration … or is there? Well, if there is no module declaration, it is implicitly assumed to be class Object – but Object doesn't have a constant named FOO and neither do its ancestors Kernel and BasicObject.
Ergo: Ruby is right. There is no constant named FOO within the constant lookup path. It didn't remove FOO from the scope, it was never in scope to begin with.
[Ruby's reflection API actually gives you access to anything you need: #1 is exactly the same as Module.nesting and #2 is (almost) the same as Module.nesting.first.ancestors.]
You might think: wait, isn't module_eval a module declaration? No, it isn't! It's just a method like any other method taking a block that's just like any other block. It doesn't alter the constant lookup rules in any way.
Note that that's not quite true: after all, e.g. instance_eval does change method lookup rules, for example, so it would not be inconceivable that module_eval changes constant lookup rules. And even more confusingly, when called with a String instead of a block, it actually does change Module.nesting and thus the constant lookup rules!
Just want to enquire what the right practice is.
My preference is to use procs, simply because I think that defining methods inside of methhods is a bit untidy and should be done only when necessary. To get around it, I simply use procs.
What is the right / better way to do it and why? (apart from the proc's ability to access the main method's variables defined before itself)
def meth( params_prime )
calculations = do_something_with_whatever
def sub_meth( params_sub )
do_something_with_params_sub
end
sub_meth_params(calculations) # is this better?
proc1 = proc{ |params_sub| do_something_with_params_sub }
proc1.call(calculations) # or is this?
end
It is not clear what your specific use-case is, but I would definitely go for procs or lambdas. There is less overhead when defining a proc or lambda dynamically, they are passable, so if needed you could return them and they could be used outside the function.
Using "def" exposes the method as an instance method outside of the current method scope (so in the containing class, which could be Object in your case). This may or may not be with you want. If you want to use an anonymous function only available in the local scope, use a lambda.
Also Proc vs Lambda: I generally prefer to use lambdas since they behave a little more "predictable", meaning: as you would expect (check passed variables, and return just returns from the lambda, proc returns from the called scope). But from your example it is hard to deduce what would apply. I think the key-difference is: lambas are ment to be passed around, and thus behave a little more sanely. If this is not your use-case, use Proc :) (a write-up of the difference).
If you want to use sub_func to encapsulate it from call from other methods you can use a class to group function and sub_func together and make sub_func private. Otherwise if you want to pass this function as a parameter further you can declare it as lamda.
def func params_prime
sub_func = ->(params_sub){do_something_with_params}
sub_func.call(params_prime)
end
Defining methods inside methods is a feature of Ruby that may have its use. But something is telling me that you are asking a very advanced question while you are still a beginner level Rubyist. Do you know what default definee is? If not, check this article by Yugui.
Procs are very important in Ruby, but newbies tend to use them instead of defining methods in appropriate objects, which is the exact smell I'm getting from your question. The normal way of doing things in OO languages of Ruby family is to define methods on objects:
class Foo
def bar *params
# do something with params
end
end
Since you do not understand the meaning of defining methods inside methods, refrain from doing it for the next 6 months. Once you understand objects, you can start experimenting with this very advanced feature again.
APPENDIX:
Since you demonstrated intrest, let me show you that using def in def at the top level is a frownable-upon thing to do. Normally, when you define a method on some class without further adornment, it becomes a public instance method of that class:
class X
def foo; "foo" end
end
X.instance_methods.include? :foo
#=> true
When you use def in a def, the definee for the inner def is going to be X:
class X
def bar
def baz
"baz"
end
"bar"
end
end
When you execute the above code, instance method #bar becomes defined on X:
X.instance_methods.include? :bar
#=> true
But #baz not yet:
X.instance_methods.include? :baz
#=> false
Only after you call #bar at least once does the method become defined on X:
X.new.bar
#=> "bar"
X.instance_methods.include? :baz
#=> true
And now I would like to ask you to appreciate how terrible thing just happened: An instance just modified its mother class. That's a violation. A violation of such a basic principle of OO design, that I'm not even sure it has a name. This technique is great for obfuscated coding competitions, but in production, it's taboo. Ruby gives you the freedom to break that taboo, gives you the rope to hang yourself on, but you don't do it under any kind of normal circumstances.
So what can be worse than a def inside a def in a class definition? The answer is, a def inside a def at the top level. Let me show you why. Normally, when you define methods with def at the top level, the default definee is Object, but the top level defnitions become private instance methods of object. This is to prevent the unintended consequence of top level defs, because almost all Ruby objects inherit from Object. For example, if you define:
class Object
def foo; "foo" end
end
Now all your objects will respond to foo:
foo #=> "foo"
1.foo #=> "foo"
[].foo #=> "foo
When we define methods at the top level, we usually just intend to use the method at the top level, and don't want every single object to inherit it. For that reason, top level defs become private:
hello #=> NameError: undefined local variable or method `hello' for main:Object
1.hello #=> NoMethodError: undifined method 'hello' for 1:Fixnum
Now we use def at the top level:
def hello; "hello" end
We can see that method #hello is has not become an instance methods of Object:
Object.instance_methods.include? :hello
#=> false
Mysteriously, it became its private method:
Object.private_instance_methods.include? :hello
#=> true
This way, we avoid the unintended consequence of defining #hello method for every single object. But the inheritance is there. The error message has changed:
1.hello #=> NoMethodError: private method 'hello' called for 1:Fixnum
And we can forcibly call the method via #send:
1.send :hello
#=> "hello"
Mysteriously, at the top level, we are allowed to call this private method without #send:
hello
#=> "hello"
And now, what happens when you do def in def at the top level:
def bar
def baz; "baz" end
"bar"
end
You define a private instance method Object#bar in an expected way. But when you call it, alas, the top level magic no longer works and a public method Object#baz gets defined:
bar #=> "bar"
This way, not just the top level, but every single Ruby object got polluted with your #baz method:
1.baz #=> "baz"
Class.baz #=> "baz"
This is why I told you to refrain from using this idiom until you progress from the level of unconscious incompetence to the level of conscious incompetence. I recommend you to read more about top level methods in Ruby.
According to the documentation mod.const_get(sym) "Returns the value of the named constant in mod."
I also know that const_get by default may look up the inheritance chain of the receiver. So the following works:
class A; HELLO = :hello; end
class B < A; end
B.const_get(:HELLO) #=> :hello
I also know that classes in Ruby subclass Object, so that you can use const_get to look up 'global' constants even though the receiver is a normal class:
class C; end
C.const_get(:Array) #=> Array
However, and this is where i'm confused -- modules do not subclass Object. So why can I still look up 'global' constants from a module using const_get? Why does the following work?
module M; end
M.const_get(:Array) #=> Array
If the documentation is correct - const_get simply looks up the constant defined under the receiver or its superclasses. But in the code immediately above, Object is not a superclass of M, so why is it possible to look up Array ?
Thanks
You are correct to be confused... The doc didn't state that Ruby makes a special case for lookup of constants in Modules and has been modified to state this explicitly. If the constant has not been found in the normal hierarchy, Ruby restarts the lookup from Object, as can be found in the source.
Constant lookup by itself can be bit confusing. Take the following example:
module M
Foo = :bar
module N
# Accessing Foo here is fine:
p Foo # => bar
end
end
module M::N
# Accessing Foo here isn't
p Foo # => uninitialized constant M::N::Foo
end
p M::N.const_get :Foo # => uninitialized constant M::N::Foo
In both places, though, accessing Object level constants like Array is fine (thank god!). What's going on is that Ruby maintains a list of "opened Module definitions". If a constant has an explicit scope, say LookHereOnly::Foo, then only LookHereOnly and its included modules will be searched. If no scope is specified (like Foo in the example above), Ruby will look through the opened module definitions to find the constant Foo: M::N, then M and finally Object. The topmost opened module definition is always Object.
So M::N.const_get :Foo is equivalent to accessing Foo when the opened classes are only M::N and Object, like in the last part of my example.
I hope I got this right, coz I'm still confused by constant lookups myself :-)
I came up with the following script to load name spaced constants:
def load_constant(name)
parts = name.split('::')
klass = Module.const_get(parts.shift)
klass = klass.const_get(parts.shift) until parts.empty?
klass
end
As long as we are not checking for errors you can:
def load_constant(name)
name.split('::').inject(Module) do |mod_path, mod_to_find|
mod_path.const_get(mod_to_find)
end
end