简体   繁体   中英

Difference between array<<element and array.push(element)? or string<<“something” and string+“something”? in Ruby

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

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:

  • one performs in-place mutating
  • second is simply concatenating without changing the original strings.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM