You need to understand what the method *
does.1. That depends on the method's receiver. For "cat".*(3)
, "cat"
is *
's receiver. For 1.*(3)
(which, as explained later, can be written, 1*3
) 1
is *
's receiver. The term "receiver" derives from OOP's concept of sending a message (method) to a receiver.
A method can be defined on an object (e.g., "cat"
or 1
) in one of two ways. The most common is that the method is an instance method defined on the receiver's class (e.g., *
defined on "cat".class #=> String
or 1.class #=> Integer
. The second way, which is not applicable here, is that the method has been defined on the object's singleton class, provided the object has one. ("cat"
has a singleton class but 1
, being an immediate value, does not.)
When we see "cat".*(3)
, therefore, we look to the doc for String#* and conclude that
"cat".*(3) #=> "catcatcat"
For 1*(3)
, we look to Integer#*, which tells us that
1.*(3) #=> 3
Let's try another: [1,2,3].*(3)
, Because [1,2,3].class #=> Array
we look to Array#* and conclude that
[1,2,3].*(3) #=> [1, 2, 3, 1, 2, 3, 1, 2, 3]
Note that this method has two forms, depending on whether its argument is an integer (as here) or a string. In the latter case
[1,2,3].*(' or ') #=> "1 or 2 or 3"
Many methods have different behaviors that depend on its arguments (and on whether an optional block is provided).
Lastly, Ruby allows us to use a shorthand with these three methods (and certain others with names comprised of characters that are not letters, numbers or underscores.):
"cat"*3 #=> "catcatcat"
"cat" * 3 #=> "catcatcat"
1*3 #=> 3
[1,2,3] * 3 #=> [1, 2, 3, 1, 2, 3, 1, 2, 3]
This shorthand is generally referred to as "syntactic sugar".
1 Ruby's method names are not restricted to words, such as "map", "upcase"
and so on. "*", "~", "[]" and "[]=", for example, are valid method names"