2

I'm reading the docs for Ruby 2.5.0 and I don't understand this part about the Methods:

Additionally, methods for element reference and assignment may be defined: [] and []= respectively. Both can take one or more arguments, and element reference can take none.

class C
  def [](a, b)
    puts a + b
  end

  def []=(a, b, c)
    puts a * b + c
  end
end

obj = C.new

obj[2, 3]     # prints "5"
obj[2, 3] = 4 # prints "10"

1) Why and how the assignment method in this case assigns a=2 b=3 and c=4?

2) Seems that it behaves like the method for element reference, so if this is the case, why does it exist? I could just write:

def [](a, b, c)
        puts a * b + c
end
obj[2, 3, 4] # prints "10"

and it wouldn't change anything, would it?

John S.
  • 33
  • 5

1 Answers1

1

1) Why and how the assignment method in this case assigns a=2 b=3 and c=4?

a, b, and c are the parameters and 2, 3, and 4 are the arguments. Arguments are bound to parameters just like every other method, because []= is a method just like every other method.

2) Seems that it behaves like the method for element reference, so if this is the case, why does it exist? I could just write: […]

You could also just write obj.foo(2, 3, 4) or obj.frobnicate(2, 3, 4) or obj.(2, 3, 4). It doesn't matter. It's just a method like any other, and []= is just a name like any other. You could also write it

obj.[]=(2, 3, 4)

if you want.

The name doesn't matter. (To a computer, anyway.)

Except the name does matter! (Method) names are what we use to communicate the intent of our code to our (human) colleagues.

So, [] and []= are different names, and they communicate different intent. In particular, [] communicates the intent to get something and []= communicates the intent to set something. Note, however, that the examples in the documentation purely demonstrate how arguments are bound for indexer and indexing assignment methods, they are not good examples of how to use such methods; maybe that is part of the source of your confusion. A much better example is how the [] and []= methods are used by the Array and Hash classes.

Note also that "the name doesn't matter" is slightly exaggerated. The name does matter because of the fact that Ruby allows you to write

obj[2, 3] = 4

instead of

obj.[]=(2, 3, 4)

which would be the "normal" syntax for a message send to a method named []=. []= is one of a set of methods that have syntactic sugar allowing them to be called in a non-standard way. Other such methods are +, -, *, /, %, <<, >>, |, & etc. which can be called like a + b instead of a.+(b), !, +@, -@, which can be called as !a, +a, and -a instead of a.!, a.+@, and a.-@, call which can be called like a.(1, 2) instead of a.call(1, 2), and any method ending with = which can be called like a.foo = 42 instead of a.foo=(42). (And some others as well.)

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • Alright, thanks. I didn't read yet that some methods could be called in a non-standard way, now I understand why it behaves that way, also your explanation about when to use [] or []= is what I was missing, thanks again. – John S. Feb 04 '18 at 02:21