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
Related
What's the point of instance_variable_set? Aren't these two lines the same?
instance_variable_set(#name, value)
#name = value"
In the case of a "simple" variable assignment for an instance variable like:
#foo = "foo"
You couldn't do
"##{foo}" = "bar" # syntax error, unexpected '=', expecting end-of-input
But you could do something similar with instance_variable_set:
instance_variable_set("##{foo}", "bar")
p #foo # "bar"
As per your question Aren't these two lines the same?, for that example they're similar, but isn't the use people tend to give to instance_variable_set.
I wonder why there is no mention of another obvious difference: they have different scopes.
While #name = value is accessible only from within the scope where the instance variable is defined (read: from inside the instance,) instance_variable_set is available from everywhere to set instance variables from outside:
class C
attr_reader :name
def initialize(name)
#name = name
end
end
C.new("foo").tap do |c|
c.instance_variable_set(:#name, 42)
c.name
end
#⇒ 42
I'm pretty new to Ruby and have this question when I'm reading some tutorial. I'm curious what's the point of instance_variable_set?
The point of Object#instance_variable_set is to dynamically reflectively set an instance variable whose name may not be known at design time, only at run time.
Aren't these two lines the same?
instance_variable_set(#name, value)
#name = value
No, these lines are completely different, and they perfectly illustrate what I wrote above:
The first line sets the instance variable whose name is stored inside #name to value.
The second line sets the instance variable #name to value.
From the fine manual:
instance_variable_set(symbol, obj) → obj
instance_variable_set(string, obj) → obj
Sets the instance variable named by symbol to the given object, thereby frustrating the efforts of the class's author to attempt to provide proper encapsulation. The variable does not have to exist prior to this call. If the instance variable name is passed as a string, that string is converted to a symbol.
So the first argument isn't #name, it is :#name (i.e. a Symbol) or '#name' (a String).
The result is that instance_variable_set, as noted in the documentation, can be used to set an instance variable when you know its name even if you don't know the name until your code is running.
Here is an example of how the methods Object#instance_variable_set and Object#instance_variable_get could be used to increment the values of all instance variables by one.
class Klass
attr_accessor :a, :b, :cat
def initialize
#a, #b, #c, #d = 1, 2, 3, 4
end
end
k = Klass.new
#=> #<Klass:0x0000000001d70978 #a=1, #b=2, #c=3, #cat=4>
k.instance_variables.each { |v| k.instance_variable_set(v, k.instance_variable_get(v)+1) }
#=> [:#a, :#b, :#c, :#cat]
k #=> #<Klass:0x0000000001d70978 #a=2, #b=3, #c=4, #cat=5>
See also Object#instance_variables.
Compared to having four separate assignment statements, fewer lines of code are needed, but there are two other, more important advantages:
there is less chance of introducing a bug (k.cut += 1); and
adding, removing or renaming instance variables does not require the value-incrementing code to be changed.
A variant of this is to substitute a dynamically-constructed array of instance variable names (e.g., [:#a, :#b]) for instance_variables above.
These may seem like unusual examples, but they are representative of a large class of operations involving instance variables in which this kind of batch processing can be used to advantage.
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.
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.
Getter methods can be used without an explicit receiver unless there is a local variable with the same name:
class A; attr_reader :foo end
A.new.instance_eval do
#foo = :foo
p foo
end
# => :foo
This will not hold when there is a local variable with the same name, due to the principle that interpretation as a local variable has priority than as a method call whenever there is an ambiguity.
class A; attr_reader :foo end
A.new.instance_eval do
foo = :bar
#foo = :foo
p foo
end
# => :bar
However, setter methods cannot be used without an explicit receiver even when a local variable with the same name is not assigned prior to the expression in question:
class A; attr_writer :foo end
A.new.instance_eval do
foo = :foo # <= No local variable named `foo` has been assigned before this point
p #foo
end
# => nil
How is this "anti-private" property of setter method justified?
If ruby interpreted your assignment in your last statement as an assignment to self, you would have no way left to set a local variable.
The way it is leaves no ambiguity for the interpreter to deal with: assignments without self are always local variables, assignments to self are always trying to use a writer on the object.
If it were the other way around
The interpreter would have to look up the contexts writer methods and assign it via the writer if there is one, which almost certainly would have a negative impact on performance
class A
attr_writer :foo
end
A.new.instance_eval do
# for each of these assignments, the interpreter has to look up if there's
# a writer method defined
foo = 'bar'
bar = 'baz'
fib = 'buz'
end
It would also leave the programmer with the rather stupid task to find out every setter method of the context he's in before assigning local variables to make absolutely sure he does not unintentionally use a setter.
class C
attr_writer :something
end
class B < C
attr_writer :foo
end
class A < B
attr_writer :bar
end
A.new.instance_eval
something = 'something'
#you just (almost certainly with no intention) assigned a value to an attribute
end
Also, your question reads:
setter methods cannot be used without an explicit receiver even when a
local variable with the same name is not assigned prior to the
expression in question:
If it were the other way around, you could not assign a local variable with the same name prior to the expression in question, because the assignment would use the setter (as stated in the first paragraph of this answer)
Concerning the implementation / the access to variables the attribute methods use: Getter and Setters work with instance variables. So, for example attr_accessor actually defines something like this:
def foo
#foo
end
def foo=(data)
#foo = data
end
So, the attribute is declared as a instance variable and not as a local variable, why should the programmer be able to assign it like a local variable? This would leave the wrong impression that you could assign instance variables of an object via assigning local variables. If ruby would do this, it would almost certainly lead to a serious memory management problem. To make it short: foo = 'bar' and #foo = 'bar' are not the same, and exactly because the attr methods use #foo = 'bar', you can not call them via using foo = 'bar'.
I think #sawa finally clarified what is meant by "anti-private".
sawa's comment:
Private means it cannot have an explicit receiver. Negation of that would be that it may have an explicit receiver, which is not what I am mentioning. I am mentioning a case where a method must have an explicit receiver, which is against private. I think you are confused.
I was confused, apparently along with all the other commenters, because "anti-private" and "against private" aren't standard terminology, nor was the meaning immediately obvious.
I think the meaning of the original question is: "Since setters require an explicit receiver, and private forbids explicit receivers, how can I call a private setter?" In other words, "anti-private" means "incompatible with private", or "unusable with private".
Jörg W Mittag eloquently explains an exception to the normal private rules. Basically, setters can be called on self even if they are private, because there's no other way to call them (unless you use the cumbersome send).
So, a setter's requirement of an explicit receiver is perfectly compatible with the setter being private, only because of the exception to the rule.
Beat Richartz's answer is pretty complete already, but I want to highlight one point about the behavior you're proposing.
In your question you have this sample code:
class A; attr_writer :foo end
A.new.instance_eval do
foo = :foo # <= No local variable named `foo` has been assigned before this point
p #foo
end
You are proposing that the assignment call the setter method. And you want this to happen if the local-variable foo hasn't been assigned yet.
But what syntax would you use to assign the local before that point?
If the receiverless assignment foo = :foo means call the setter (when it exists), you'd need yet another syntax construct to mean "assign this local-variable, disregarding whether there is a setter".
I honestly do want to hear your proposal (I'm not being sarcastic) if you have one. It would be interesting to hear alternative views on language design.
I'm not saying your way would be necessarily "worse" than the current ruby way. But at some point a language designer has to decide default behaviors for ambiguous situations, and Matz decided that receiverless assignment assigns the local.
class MyClass
def mymethod
MYCONSTANT = "blah"
end
end
gives me the error:
SyntaxError: dynamic constant assignment error
Why is this considered a dynamic constant? I'm just assigning a string to it.
Your problem is that each time you run the method you are assigning a new value to the constant. This is not allowed, as it makes the constant non-constant; even though the contents of the string are the same (for the moment, anyhow), the actual string object itself is different each time the method is called. For example:
def foo
p "bar".object_id
end
foo #=> 15779172
foo #=> 15779112
Perhaps if you explained your use case—why you want to change the value of a constant in a method—we could help you with a better implementation.
Perhaps you'd rather have an instance variable on the class?
class MyClass
class << self
attr_accessor :my_constant
end
def my_method
self.class.my_constant = "blah"
end
end
p MyClass.my_constant #=> nil
MyClass.new.my_method
p MyClass.my_constant #=> "blah"
If you really want to change the value of a constant in a method, and your constant is a String or an Array, you can 'cheat' and use the #replace method to cause the object to take on a new value without actually changing the object:
class MyClass
BAR = "blah"
def cheat(new_bar)
BAR.replace new_bar
end
end
p MyClass::BAR #=> "blah"
MyClass.new.cheat "whee"
p MyClass::BAR #=> "whee"
Because constants in Ruby aren't meant to be changed, Ruby discourages you from assigning to them in parts of code which might get executed more than once, such as inside methods.
Under normal circumstances, you should define the constant inside the class itself:
class MyClass
MY_CONSTANT = "foo"
end
MyClass::MY_CONSTANT #=> "foo"
If for some reason though you really do need to define a constant inside a method (perhaps for some type of metaprogramming), you can use const_set:
class MyClass
def my_method
self.class.const_set(:MY_CONSTANT, "foo")
end
end
MyClass::MY_CONSTANT
#=> NameError: uninitialized constant MyClass::MY_CONSTANT
MyClass.new.my_method
MyClass::MY_CONSTANT #=> "foo"
Again though, const_set isn't something you should really have to resort to under normal circumstances. If you're not sure whether you really want to be assigning to constants this way, you may want to consider one of the following alternatives:
Class variables
Class variables behave like constants in many ways. They are properties on a class, and they are accessible in subclasses of the class they are defined on.
The difference is that class variables are meant to be modifiable, and can therefore be assigned to inside methods with no issue.
class MyClass
def self.my_class_variable
##my_class_variable
end
def my_method
##my_class_variable = "foo"
end
end
class SubClass < MyClass
end
MyClass.my_class_variable
#=> NameError: uninitialized class variable ##my_class_variable in MyClass
SubClass.my_class_variable
#=> NameError: uninitialized class variable ##my_class_variable in MyClass
MyClass.new.my_method
MyClass.my_class_variable #=> "foo"
SubClass.my_class_variable #=> "foo"
Class attributes
Class attributes are a sort of "instance variable on a class". They behave a bit like class variables, except that their values are not shared with subclasses.
class MyClass
class << self
attr_accessor :my_class_attribute
end
def my_method
self.class.my_class_attribute = "blah"
end
end
class SubClass < MyClass
end
MyClass.my_class_attribute #=> nil
SubClass.my_class_attribute #=> nil
MyClass.new.my_method
MyClass.my_class_attribute #=> "blah"
SubClass.my_class_attribute #=> nil
SubClass.new.my_method
SubClass.my_class_attribute #=> "blah"
Instance variables
And just for completeness I should probably mention: if you need to assign a value which can only be determined after your class has been instantiated, there's a good chance you might actually be looking for a plain old instance variable.
class MyClass
attr_accessor :instance_variable
def my_method
#instance_variable = "blah"
end
end
my_object = MyClass.new
my_object.instance_variable #=> nil
my_object.my_method
my_object.instance_variable #=> "blah"
MyClass.new.instance_variable #=> nil
In Ruby, any variable whose name starts with a capital letter is a constant and you can only assign to it once. Choose one of these alternatives:
class MyClass
MYCONSTANT = "blah"
def mymethod
MYCONSTANT
end
end
class MyClass
def mymethod
my_constant = "blah"
end
end
Constants in ruby cannot be defined inside methods. See the notes at the bottom of this page, for example
You can't name a variable with capital letters or Ruby will asume its a constant and will want it to keep it's value constant, in which case changing it's value would be an error an "dynamic constant assignment error". With lower case should be fine
class MyClass
def mymethod
myconstant = "blah"
end
end
Ruby doesn't like that you are assigning the constant inside of a method because it risks re-assignment. Several SO answers before me give the alternative of assigning it outside of a method--but in the class, which is a better place to assign it.
Many thanks to Dorian and Phrogz for reminding me about the array (and hash) method #replace, which can "replace the contents of an array or hash."
The notion that a CONSTANT's value can be changed, but with an annoying warning, is one of Ruby's few conceptual mis-steps -- these should either be fully immutable, or dump the constant idea altogether. From a coder's perspective, a constant is declarative and intentional, a signal to other that "this value is truly unchangeable once declared/assigned."
But sometimes an "obvious declaration" actually forecloses other, future useful opportunities. For example...
There are legitimate use cases where a "constant's" value might really need to be changed: for example, re-loading ARGV from a REPL-like prompt-loop, then rerunning ARGV thru more (subsequent) OptionParser.parse! calls -- voila! Gives "command line args" a whole new dynamic utility.
The practical problem is either with the presumptive assumption that "ARGV must be a constant", or in optparse's own initialize method, which hard-codes the assignment of ARGV to the instance var #default_argv for subsequent processing -- that array (ARGV) really should be a parameter, encouraging re-parse and re-use, where appropriate. Proper parameterization, with an appropriate default (say, ARGV) would avoid the need to ever change the "constant" ARGV. Just some 2¢-worth of thoughts...