What does Ruby constant mean? - ruby

What does Ruby constants really mean? The following code doesn't show any 'constant' attribute. The warning is there, but I still get to change what A refers to.
A = 1
puts A # => 1
A = 2 # warning: already initialized constant A
puts A # => 2
Or is Ruby constants are just an indication without any enforcement?

That's right, constants are just like variables in ruby, but you get a warning if you change them.
Also, there's one difference with mere variables: You can access constants even if they are defined inside another class or module, for example given this snippet:
module Constants
PI = 3,1415
other = "variable"
end
You can reach PI doing Constants::PI while Constants::other will not work.

Yes, Ruby constants aren't enforced, other than printing that warning.

That's right -- assigning to a constant is a warning, not an error; "constants" are just an indicator of how you should use something, not a rule that you do use it that way.
That may sound horrendous coming from a static-programming world, but it's immensely useful in various metaprogramming facilities, and it enables things that would otherwise be completely impossible in static languages.
That said, if you really want to make sure people keep their grubby hands off your references, you can use Object#freeze. It's still okay to change what a reference points to with this; you just can't change the contents of the reference itself:
irb(main):001:0> class Fruit; attr_accessor :name; end
=> nil
irb(main):002:0> f = Fruit.new
=> #<Fruit:0xb7e06570>
irb(main):003:0> f.name = "apple"
=> "apple"
irb(main):004:0> f.freeze # After freeze, can't touch this Fruit.
=> #<Fruit:0xb7e06570 #name="apple">
irb(main):005:0> f.name = "banana"
TypeError: can't modify frozen object # Kablammo!
from (irb):5:in `name='
from (irb):5
But this is okay:
irb(main):006:0> f = Fruit.new
=> #<Fruit:0xb7dfed84>
irb(main):007:0> f.name = "banana"
=> "banana"

"Constant" is really a misnomer, the most important aspect of Ruby's "Constants" is not their immutability but their lookup rules.
see: http://coderrr.wordpress.com/2008/03/11/constant-name-resolution-in-ruby/

Constants are used to store values that should not be changed. Their names must start with an uppercase letter. By convention, most constant names are written in all uppercase letters with an underscore as word separator, such as SOME_CONSTANT.
Constants defined within classes can be accessed by all methods of that class. Those created outside a class can be accessed globally (within any method or class).
class Car
WHEELS = 4
def initialize
puts WHEELS
end
end
c = Car.new # Output: 4
Note that Ruby does not stop us from changing the value of a constant, it only issues a warning.
SOME_CONSTANT = "foo"
SOME_CONSTANT = "bar"
warning: already initialized constant SOME_CONSTANT
warning: previous definition of SOME_CONSTANT was here
In Ruby, all class and module names are constants, but convention dictates they should be written in camel case, such as SomeClass.
Constants can be accessed from outside the class, even within another class, by using the :: (double colon) operator. To access the WHEELS constant from outside the Car class, we would use Car::WHEELS. The :: operator allows constants, public instance methods and class methods to be accessed from outside the class or module on which they are defined.
A built-in method called private_constant makes constants private (accessible only within the class on which they were created). The syntax is as follows:
class Car
WHEELS = 4
private_constant:WHEELS
end
Car::WHEELS # Output: NameError: private constant Car::WHEELS referenced

If you're coming from other programming languages, Ruby handles constants differently than what you may be used to. Constants, in general, take values that do not change through the entire application. The syntax is to use all capital letters while naming your constant so that the application knows how to handle it. For example, to set a constant to hold a baseball team you would declare it this way:
TEAM = "Angels"
I know you know this much, bear with me here. Typically, other programming languages will not allow you to change the value of TEAM. However, Ruby does not hold you back and takes the last value assigned to the constant. In the above example, I can change its value to:
TEAM = "Athletics"
Other programming languages would either throw an error or would print the value of Angels. However, Ruby prints the value Athletics because that is the last value assigned to the variable TEAM. Also, it gives a warning message that says that the constant was already initialized and was changed because changing a constant is considered a poor programming practice. But, it still allows you to make the change and follows the Ruby convention of trusting the developer to make the right programming decision. So, be careful while using constants in Ruby since they can be overridden.

Related

"NoMethodError: undefined method '-#' for ["some-text"]:Array" when inside while loop [duplicate]

The pre/post increment/decrement operator (++ and --) are pretty standard programing language syntax (for procedural and object-oriented languages, at least).
Why doesn't Ruby support them? I understand you could accomplish the same thing with += and -=, but it just seems oddly arbitrary to exclude something like that, especially since it's so concise and conventional.
Example:
i = 0 #=> 0
i += 1 #=> 1
i #=> 1
i++ #=> expect 2, but as far as I can tell,
#=> irb ignores the second + and waits for a second number to add to i
I understand Fixnum is immutable, but if += can just instanciate a new Fixnum and set it, why not do the same for ++?
Is consistency in assignments containing the = character the only reason for this, or am I missing something?
Here is how Matz(Yukihiro Matsumoto) explains it in an old thread:
Hi,
In message "[ruby-talk:02706] X++?"
on 00/05/10, Aleksi Niemelä <aleksi.niemela#cinnober.com> writes:
|I got an idea from http://www.pragprog.com:8080/rubyfaq/rubyfaq-5.html#ss5.3
|and thought to try. I didn't manage to make "auto(in|de)crement" working so
|could somebody help here? Does this contain some errors or is the idea
|wrong?
(1) ++ and -- are NOT reserved operator in Ruby.
(2) C's increment/decrement operators are in fact hidden assignment.
They affect variables, not objects. You cannot accomplish
assignment via method. Ruby uses +=/-= operator instead.
(3) self cannot be a target of assignment. In addition, altering
the value of integer 1 might cause severe confusion throughout
the program.
matz.
One reason is that up to now every assignment operator (i.e. an operator which changes a variable) has a = in it. If you add ++ and --, that's no longer the case.
Another reason is that the behavior of ++ and -- often confuse people. Case in point: The return value of i++ in your example would actually be 1, not 2 (the new value of i would be 2, however).
It's not conventional in OO languages. In fact, there is no ++ in Smalltalk, the language that coined the term "object-oriented programming" (and the language Ruby is most strongly influenced by). What you mean is that it's conventional in C and languages closely imitating C. Ruby does have a somewhat C-like syntax, but it isn't slavish in adhering to C traditions.
As for why it isn't in Ruby: Matz didn't want it. That's really the ultimate reason.
The reason no such thing exists in Smalltalk is because it's part of the language's overriding philosophy that assigning a variable is fundamentally a different kind of thing than sending a message to an object — it's on a different level. This thinking probably influenced Matz in designing Ruby.
It wouldn't be impossible to include it in Ruby — you could easily write a preprocessor that transforms all ++ into +=1. but evidently Matz didn't like the idea of an operator that did a "hidden assignment." It also seems a little strange to have an operator with a hidden integer operand inside of it. No other operator in the language works that way.
I think there's another reason: ++ in Ruby wouldn't be remotely useful as in C and its direct successors.
The reason being, the for keyword: while it's essential in C, it's mostly superfluous in Ruby. Most of the iteration in Ruby is done through Enumerable methods, such as each and map when iterating through some data structure, and Fixnum#times method, when you need to loop an exact number of times.
Actually, as far as I have seen, most of the time +=1 is used by people freshly migrated to Ruby from C-style languages.
In short, it's really questionable if methods ++ and -- would be used at all.
You can define a .+ self-increment operator:
class Variable
def initialize value = nil
#value = value
end
attr_accessor :value
def method_missing *args, &blk
#value.send(*args, &blk)
end
def to_s
#value.to_s
end
# pre-increment ".+" when x not present
def +(x = nil)
x ? #value + x : #value += 1
end
def -(x = nil)
x ? #value - x : #value -= 1
end
end
i = Variable.new 5
puts i #=> 5
# normal use of +
puts i + 4 #=> 9
puts i #=> 5
# incrementing
puts i.+ #=> 6
puts i #=> 6
More information on "class Variable" is available in "Class Variable to increment Fixnum objects".
I think Matz' reasoning for not liking them is that it actually replaces the variable with a new one.
ex:
a = SomeClass.new
def a.go
'hello'
end
# at this point, you can call a.go
# but if you did an a++
# that really means a = a + 1
# so you can no longer call a.go
# as you have lost your original
Now if somebody could convince him that it should just call #succ! or what not, that would make more sense, and avoid the problem. You can suggest it on ruby core.
And in the words of David Black from his book "The Well-Grounded Rubyist":
Some objects in Ruby are stored in variables as immediate values. These include
integers, symbols (which look like :this), and the special objects true, false, and
nil. When you assign one of these values to a variable (x = 1), the variable holds
the value itself, rather than a reference to it.
In practical terms, this doesn’t matter (and it will often be left as implied, rather than
spelled out repeatedly, in discussions of references and related topics in this book).
Ruby handles the dereferencing of object references automatically; you don’t have to
do any extra work to send a message to an object that contains, say, a reference to
a string, as opposed to an object that contains an immediate integer value.
But the immediate-value representation rule has a couple of interesting ramifications,
especially when it comes to integers. For one thing, any object that’s represented
as an immediate value is always exactly the same object, no matter how many
variables it’s assigned to. There’s only one object 100, only one object false, and
so on.
The immediate, unique nature of integer-bound variables is behind Ruby’s lack of
pre- and post-increment operators—which is to say, you can’t do this in Ruby:
x = 1
x++ # No such operator
The reason is that due to the immediate presence of 1 in x, x++ would be like 1++,
which means you’d be changing the number 1 to the number 2—and that makes
no sense.
Some objects in Ruby are stored in variables as immediate values. These include integers, symbols (which look like :this), and the special objects true, false, and nil. When you assign one of these values to a variable (x = 1), the variable holds the value itself, rather than a reference to it.
Any object that’s represented as an immediate value is always exactly the same object, no matter how many variables it’s assigned to. There’s only one object 100, only one object false, and so on.
The immediate, unique nature of integer-bound variables is behind Ruby’s lack of pre-and post-increment operators—which is to say, you can’t do this in Ruby:
x=1
x++ # No such operator
The reason is that due to the immediate presence of 1 in x, x++ would be like 1++, which means you’d be changing the number 1 to the number 2—and that makes no sense.
Couldn't this be achieved by adding a new method to the fixnum or Integer class?
$ ruby -e 'numb=1;puts numb.next'
returns 2
"Destructive" methods seem to be appended with ! to warn possible users, so adding a new method called next! would pretty much do what was requested ie.
$ ruby -e 'numb=1; numb.next!; puts numb'
returns 2 (since numb has been incremented)
Of course, the next! method would have to check that the object was an integer variable and not a real number, but this should be available.

Why can't I overwrite self in the Integer class?

I want to be able to write number.incr, like so:
num = 1; num.incr; num
#=> 2
The error I'm seeing states:
Can't change the value of self
If that's true, how do bang! methods work?
You cannot change the value of self
An object is a class pointer and a set of instance methods (note that this link is an old version of Ruby, because its dramatically simpler, and thus better for explanatory purposes).
"Pointing" at an object means you have a variable which stores the object's location in memory. Then to do anything with the object, you first go to the location in memory (we might say "follow the pointer") to get the object, and then do the thing (e.g. invoke a method, set an ivar).
All Ruby code everywhere is executing in the context of some object. This is where your instance variables get saved, it's where Ruby looks for methods that don't have a receiver (e.g. $stdout is the receiver in $stdout.puts "hi", and the current object is the receiver in puts "hi"). Sometimes you need to do something with the current object. The way to work with objects is through variables, but what variable points at the current object? There isn't one. To fill this need, the keyword self is provided.
self acts like a variable in that it points at the location of the current object. But it is not like a variable, because you can't assign it new value. If you could, the code after that point would suddenly be operating on a different object, which is confusing and has no benefits over just using a variable.
Also remember that the object is tracked by variables which store memory addresses. What is self = 2 supposed to mean? Does it only mean that the current code operates as if it were invoked 2? Or does it mean that all variables pointing at the old object now have their values updated to point at the new one? It isn't really clear, but the former unnecessarily introduces an identity crisis, and the latter is prohibitively expensive and introduce situations where it's unclear what is correct (I'll go into that a bit more below).
You cannot mutate Fixnums
Some objects are special at the C level in Ruby (false, true, nil, fixnums, and symbols).
Variables pointing at them don't actually store a memory location. Instead, the address itself stores the type and identity of the object. Wherever it matters, Ruby checks to see if it's a special object (e.g. when looking up an instance variable), and then extracts the value from it.
So there isn't a spot in memory where the object 123 is stored. Which means self contains the idea of Fixnum 123 rather than a memory address like usual. As with variables, it will get checked for and handled specially when necessary.
Because of this, you cannot mutate the object itself (though it appears they keep a special global variable to allow you to set instance variables on things like Symbols).
Why are they doing all of this? To improve performance, I assume. A number stored in a register is just a series of bits (typically 32 or 64), which means there are hardware instructions for things like addition and multiplication. That is to say the ALU, is wired to perform these operations in a single clock cycle, rather than writing the algorithms with software, which would take many orders of magnitude longer. By storing them like this, they avoid the cost of storing and looking the object in memory, and they gain the advantage that they can directly add the two pointers using hardware. Note, however, that there are still some additional costs in Ruby, that you don't have in C (e.g. checking for overflow and converting result to Bignum).
Bang methods
You can put a bang at the end of any method. It doesn't require the object to change, it's just that people usually try to warn you when you're doing something that could have unexpected side-effects.
class C
def initialize(val)
#val = val # => 12
end # => :initialize
def bang_method!
"My val is: #{#val}" # => "My val is: 12"
end # => :bang_method!
end # => :bang_method!
c = C.new 12 # => #<C:0x007fdac48a7428 #val=12>
c.bang_method! # => "My val is: 12"
c # => #<C:0x007fdac48a7428 #val=12>
Also, there are no bang methods on integers, It wouldn't fit with the paradigm
Fixnum.instance_methods.grep(/!$/) # => [:!]
# Okay, there's one, but it's actually a boolean negation
1.! # => false
# And it's not a Fixnum method, it's an inherited boolean operator
1.method(:!).owner # => BasicObject
# In really, you call it this way, the interpreter translates it
!1 # => false
Alternatives
Make a wrapper object: I'm not going to advocate this one, but it's the closest to what you're trying to do. Basically create your own class, which is mutable, and then make it look like an integer. There's a great blog post walking through this at http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html it will get you 95% of the way there
Don't depend directly on the value of a Fixnum: I can't give better advice than this without knowing what you're trying to do / why you feel this is a need.
Also, you should show your code when you ask questions like this. I misunderstood how you were approaching it for a long time.
It's simply impossible to change self to another object. self is the receiver of the message send. There can be only one.
If that's true, how do bang! methods work?
The bang (!) is simply part of the method name. It has absolutely no special meaning whatsoever. It is a convention among Ruby programmers to name surprising variants of less surprising methods with a bang, but that's just that: a convention.

Can somebody please explain ruby constant lookup for me?

More specifically:
When do you need to prefix the scope with :: (like ::Foo::Bar)
When is directly referring to a scoped const ok? (just Foo::Bar)
Is there a good reason why this behavior is so confusing?
EDIT: I am talking about stuff like this
module Foo
THING = 'thing'
module Bar
puts THING
end
end
#=> thing
module Foo::Bar
puts THING
end
#=> NameError: uninitialized constant Foo::Bar::THING
When do you need to prefix the scope
with :: (like ::Foo::Bar)
When there's another constant with the same name in the current namespace.
When is directly referring to a scoped
const ok? (just Foo::Bar)
When there isn't another constant with the same name in the current namespace. Ie. when that identifier is unambiguous. Similarly, you could just use Bar to aid readability if it was unambiguous.
Is there a good reason why this
behavior is so confusing?
It's balancing readability and ease of use against specificity. You don't always want to have to do ::Foo::Bar::Baz::Boo (the globally unique identifier) when you're deep down in your namespace.
In as far as I've understood/experienced it: when in a module/class Foo, then Bar refers to Foo::Bar unless it doesn't exist -- in which case it means ::Bar.)
Please take it with a grain of salt, though, because I'm new to ruby as well. :-P

Throw exception when re-assigning a constant in Ruby?

I've long been aware that "constants" in Ruby (i.e., variable names that are capitalized) aren't really constant. Like other programming languages, a reference to an object is the only thing stored in the variable/constant. (Sidebar: Ruby does have the facility to "freeze" referenced objects from being modified, which as far as I know, isn't an ability offered in many other languages.)
So here's my question: when you re-assign a value into a constant, you get a warning like so:
>> FOO = 'bar'
=> "bar"
>> FOO = 'baz'
(irb):2: warning: already initialized constant FOO
=> "baz"
Is there a way to force Ruby to throw an exception instead of printing a warning? It's tough to figure out why reassignments happen sometimes.
Look at Can you ask ruby to treat warnings as errors? to see how it is possible in some cases to treat warnings as errors.
Otherwise I guess you'd have to write a custom method to assign constants and raise the exception if already assigned.
If you know that a reassignment happens to a specific constant, you can also add a sanity check just before the assignment.
You can't intercept it directly, no.
If you really need to do this, I can think of a very dirty hack, though. You could redirect the standard error IO to a custom IO object. The write method could then check for what is being written; if it contains "warning: already initialized constant", then you raise, otherwise you forward the call to the standard error's write.
If the constant is within a class or a module, then you could freeze the class or module:
# Normal scenario
$VERBOSE = true
class Foo
BAR = 1
end
Foo::BAR = 2 # warning: already initialized constant BAR
# Using freeze
Foo.freeze
Foo::BAR = 3
RuntimeError: can't modify frozen Class
from (irb):8
from /Users/agrimm/.rbenv/versions/1.9.3-p194/bin/irb:12:in `<main>'
For your scenario, you could freeze Object, but that sounds kind of scary.

What is the real reason for Ruby class names being capitalised?

Ok, so everyone knows that capitalised identifiers are seen to be ‘constant’ in Ruby.
However, it is possible to assign a new value to constants, so the following works
class A
def self.hi; "hi"; end
end
class B
def self.hi; "ho"; end
end
A.hi # => "hi"
B.hi # => "ho"
A = B
# warning: already initialized constant A
# => B
A.hi # => "ho"
and also does assigning to a lowercase identifier work:
a = B
a.hi # => "ho"
However, the internal name is set to ‘B’ in all cases and the new identifier names are also only referencing ‘B’.
But if it’s technically okay for the identifier to have a lowercase name, why is this restriction on the internal name for the class? It can’t be that it needs to be constant, because it isn’t constant; so the other reason could be that lowercase identifiers have a different scope. But then: why not having a class with lowercase scope?
I’m wondering because the parser even allows for method names in unicode and such, so it seems strange that for classes it’s so much more restricted.
As you said, the name of a class is that of the first constant it has been assigned to. You can only use constants with the class keyword because it has been decided that the class keyword should only be used to create named classes.
The rationale probably being that allowing local variables would confuse uses, who would use class lowercase_class_name, not knowing the difference between lower case and upper case identifiers and then wonder why the classname was not visible everywhere (i.e. why def foo() lowercase_class_name.new end did not work).
By making the default way to create classes specific to constants, classes defined this way will be visible everywhere and there is at least a suggestion that the value associated with that name should not change (i.e. you get a warning otherwise).
People who know what they're doing can still do local_variable = Class.new { ... } if they need to.
The interpreter needs one way to find out if it is a Class name or a member variable of the current class/module.
The interpreter has to lookup class names in a global hash table while the member variables are in the class hash table. Local variables are different as they can be resolved by the interpreter without looking up hash tables at all (they have precedence over member variables).
And the only thing the interpreter knows about an identifier are the characters. Therefore there is the notational difference. Thats also the reason why global variables have a preceding $ and class variables an # character. For this the interpreter has other hash tables it has to search.
Other script languages have similar restrictions, for example PHP needs a dollar in front of each variable.

Resources