views:

162

answers:

4

In the following two examples I do the same thing, creating a constant String and using the concat method to modify it. Because it's a constant, I expect a compiler warning but only receive one in the second example when I use the assignment operator. Why is this?

X = "hello"
X.concat(" world")
puts X # no warning

X = "hello"
X = X.concat(" world")
puts X # warning: already initialized

Since the concat method modifies the string in place, that's normally what I would do, since there's no need to use an assigment operator. So, why does the presence of the assignment operator cause the compiler to identify these two operations as being different?

+5  A: 

In Ruby, variables are essentially pointers to a place in a memory containing an object -- not the object itself. In the second example, you are initializing a constant X to point to an object in the first line (X = "hello"), and in the second line, you are again initializing the constant -- but it already points to an object, so you get the error.

A constant's immutability doesn't mean you can't alter the object -- it just means you can't change the constant to point to another object.

mipadi
+6  A: 

This is because you're re-defining a new X. When you redefine a constant it gives you the "already initialized" error. The first example does not give this error because you're not redefining X, you're modifying it.

Ryan Bigg
Right, ruby constants are not immutable, it just means you don't switch objects.
rampion
A: 

This is because the constant X is storing a reference to a String object. In your first example, you are modifying the internal state of the String object, but not the reference stored by the constant. In the second example, you are changing the reference stored by the constant to a new String object which is returned from the concat method.

The PickAxe book explains this here.

floehopper
+3  A: 

If you want to make your string "real" constant, try 'freeze':

X = "foo".freeze        # => "foo" 
X.concat("bar")

TypeError: can't modify frozen string
    from (irb):2:in `concat'
    from (irb):2

I really encourage you to read The Ruby Programming Languge.

Marcin Urbanski
Thanks for the link to the book, I've just added it to my Safari bookshelf.
Matt Haley
It will help you to understand some "strange" and probably unintuitive (at least for C++/Java programmer) ruby corners. The "Ruby Hacking Guide" (http://rhg.rubyforge.org/) is also a great place to look at - especially when you want to understand how does Ruby metaprogramming works under the hood.
Marcin Urbanski