summaryrefslogtreecommitdiff
path: root/doc/syntax/operators.rdoc
blob: d3045ac99e35b3119dfb62c8ece6268626389bd2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
= Operators

In Ruby, operators such as <code>+</code>, are defined as methods on the class.
Literals[rdoc-ref:syntax/literals.rdoc] define their methods within the lower
level, C language. String class, for example.

Ruby objects can define or overload their own implementation for most operators.

Here is an example:

  class Foo < String
    def +(str)
      self.concat(str).concat("another string")
    end
  end

  foobar = Foo.new("test ")
  puts foobar + "baz "

This prints:

  test baz another string

What operators are available is dependent on the implementing class.

== Operator Behavior

How a class behaves to a given operator is specific to that class, since
operators are method implementations.

When using an operator, it's the expression on the left-hand side of the
operation that specifies the behavior.

  'a' * 3         #=> "aaa"
  3 * 'a'         # TypeError: String can't be coerced into Integer

== Logical Operators

Logical operators are not methods, and therefore cannot be
redefined/overloaded. They are tokenized at a lower level.

Short-circuit logical operators (<code>&&</code>, <code>||</code>,
<code>and</code>, and <code>or</code>) do not always result in a boolean value.
Similar to blocks, it's the last evaluated expression that defines the result
of the operation.

=== <code>&&</code>, <code>and</code>

Both <code>&&</code>/<code>and</code> operators provide short-circuiting by executing each
side of the operator, left to right, and stopping at the first occurrence of a
falsey expression. The expression that defines the result is the last one
executed, whether it be the final expression, or the first occurrence of a falsey
expression.

Some examples:

  true && 9 && "string"                       #=> "string"
  (1 + 2) && nil && "string"                  #=> nil
  (a = 1) && (b = false) && (c = "string")    #=> false

  puts a                                      #=> 1
  puts b                                      #=> false
  puts c                                      #=> nil

In this last example, <code>c</code> was initialized, but not defined.

=== <code>||</code>, <code>or</code>

The means by which <code>||</code>/<code>or</code> short-circuits, is to return the result of
the first expression that is truthy.

Some examples:

  (1 + 2) || true || "string"                 #=> 3
  false || nil || "string"                    #=> "string"