Why is the shovel operator () preferred over plus-equals (+=) when building a string in Ruby?
Proof:
a = 'foo'
a.object_id #=> 2154889340
a << 'bar'
a.object_id #=> 2154889340
a += 'quux'
a.object_id #=> 2154742560
So <<
alters the original string rather than creating a new one. The reason for this is that in ruby a += b
is syntactic shorthand for a = a + b
(the same goes for the other <op>=
operators) which is an assignment. On the other hand <<
is an alias of concat()
which alters the receiver in-place.
Trying to understand the shovel operator with strings
When you set hi = original_string
your hi
variable is just a new variable pointed at the same object. If you look at hi.object_id
and original_string.object_id
you will find they are the same. If you want a clone of an object that you can manipulate without impacting theoriginal_string
, you'll need to say something like hi = original_string.clone
or hi = original_string.dup
.
I'd like an explanation of a behavior in Ruby that I ran across in the Koans
In ruby, everything is a reference. If you do foo = bar
, now foo
and bar
are two names for the same object.
If, however, you do foo = foo + bar
(or, equivalently, foo += bar
), foo
now refers to a new object: one that is the result of the computation foo + bar
.
Ruby differences between += and to concatenate a string
The shovel operator <<
performs much better than +=
when dealing with long strings because the shovel operator is allowed to modify the original string, whereas +=
has to copy all the text from the first string into a new string every time it runs.
There is no +=
operator defined on the String class, because +=
is a combined operator. In short x += "asdf"
is exactly equivalent to x = x + "asdf"
, so you should reference the +
operator on the string class, not look for a +=
operator.
Why does double shovel in Ruby not mutate state?
If we convert your a << b << c
construct to a more method-ish form and throw in a bunch of implicit parentheses the behavior should be clearer. Rewriting:
greeting = "Hi there, " << name << "?"
yields:
greeting = ("Hi there, ".<<(name)).<<("?")
String#<<
is modifying things but name
never appears as the target/LHS of <<
, the "Hi there ," << name
string does but name
doesn't. If you replace the first string literal with a variable:
hi_there = 'Hi there, '
greeting = hi_there << name << '?'
puts hi_there
you'll see that <<
changed hi_there
; in your "Hi there, "
case, this change was hidden because you were modifying something (a string literal) that you couldn't look at afterwards.
The following program prints the value of the variable. Why?
In case of ambiguity when compiler finds a variable and method with same name in same scope, it gives precedence to the variable.
To call the method explicitly, send empty parens ()
hello_world = 'Hello Ruby World'
def hello_world
'Hello World'
end
puts hello_world()
or provider an explicit receiver to the method, in this case, using self
self.hello_world
Edit:
As sepp2k
advised in comments below, self.hello_world
would not work with a ruby(.rb
) file. Just to try, you can dynamically dispatch the method with send
:
send(:hello_world) #or
method(:hello_world).call
Why I get +1 of my string length when I use gets?
I just to use the .chomp after the gets.
I'm feeling so dumb...
str = gets.chomp
Without it the gets method includes a newline character at the end
Array equation explanation
To break anything down line by line one could use REPL:
*a, b = [1, 2, 3, 4]
#⇒ [1, 2, 3, 4]
a
#⇒ [1, 2, 3]
b
#⇒ 4
Using splat operator, we have decomposed the original array to new array and the single value. Now everything is crystal clear: a[b-2]
which is a[2]
, which is in turn 3
(check a
array.) and b is still 4
.
3 + 4
#⇒ 7
Related Topics
How to Break Out from a Ruby Block
In Rails, How to Render Json Using a View
Difference Between Ruby 1.8 and Ruby 1.9
How to Get a Specific Output Iterating a Hash in Ruby
How to Count Duplicate Elements in a Ruby Array
Error to Install Nokogiri on Osx 10.9 Maverick
Which Ruby on Rails Is Compatible With Which Ruby Version
Ruby - Print the Variable Name and Then Its Value
Rails 5: Activerecord or Query
What's the Best Way to Model Recurring Events in a Calendar Application
Difference Between "And" and && in Ruby
Suppress Ruby Warnings When Running Specs