Reputation: 11110
Before judging me for an irrelevant question, I'll safeguard myself, that I know << is a bitwise operator. However, in both cases (array, string) it operates as just adding / concatenating values.
Any tip for clarifying whether there's difference if we use array<
Thanks
Upvotes: 1
Views: 68
Reputation: 110675
Firstly, <<
is not a bit-wise operator. Nor is :<<
or "<<"
. The first is not a Ruby object or keyword. :<<
is a symbol and "<<"
is a string. Fixnum#<<, by constrast, is a bit-wise operator, implemented as an instance method on the class Fixnum
.
You may argue that it's obvious what you meant, but it's not. Many classes have instance methods of the same name that are unrelated. Several classes, for example, have methods called "<<"
, "+"
, "size"
, "replace"
, "select"
, "each"
and on and on. The only way to speak meaningfully of an instance method, therefore, is to also give the class on which it is defined.
What is an "operator" in Ruby? Frankly, I don't know. I've never found a definition. Whatever it is, however, most of them are implemented as instance methods.
Many of Ruby's core methods have names that may seem unusual to those coming from other languages. Examples are "<<"
, "+"
and "&"
. The important thing to remember is that these are perfectly-valid names. Let's try using them as you would any other method:
[1,2,3].<<(4) #=> [1, 2, 3, 4]
"cat".+("hat") #=> "cathat"
[1,2,3].&([2,4]) #=> [2]
The head Ruby monk knew that his disciples would prefer to write these as follows:
[1,2,3] << 4
"cat" + "hat"
[1,2,3] & [2,4]
so he said "OK", which when translated from Japanese to English means "OK". He simply designed the Ruby parser so that when it saw the later form it would convert the expression to the standard form before parsing it further (or something like that). This has come to be called syntactic sugar. (Syntactic sugar doesn't allow you to write "cat" concat "hat"
, however--it only applies to names that are made up of symbols.)
My point with Ruby's operators is that most are implement with garden-variety methods, albeit methods with odd-sounding names. Yes, there are methods String#+ and Array#+ but they are completely unrelated to each other. If they were instead named String#str_add
and Array#arr_add
and used like so:
"abc".str_add("def")
[1,2,3].arr_add([2,4])
you probably wouldn't be asking the question you've raised.
Upvotes: 0
Reputation: 52357
However, in both cases (array, string) it operates as just adding / concatenating values.
It makes no difference "result-wise" - in both cases you get a value containing both operands (in that or another form).
The difference shows up in the way operands are impacted:
Consider the following examples:
a = 'a'
b = 'b'
Now:
# concatenation - no changes to original strings
a + b #=> "ab"
a #=> "a"
b #=> "b"
Whereas:
# mutation - original string is changed in-place
a << b #=> "ab"
a #=> "ab"
Same goes with arrays:
# concatenation - no changes to original arrays
a = ['a'] #=> ["a"]
b = ['b'] #=> ["b"]
a + b #=> ["a", "b"]
a #=> ["a"]
b #=> ["b"]
# mutation - original array is changed in-place
a << b #=> ["a", ["b"]]
a #=> ["a", ["b"]]
As to Array#push
and Array#<<
- they do the same thing.
Upvotes: 2