Ruby operators

Ruby’s grammar has a ton of operators. Overtimes, they can mean more than one thing, depending on their context. This blog post enumerates each operator and its meaning.

Call operator operators

First, we have the operators that are used to call methods. These are not the names of the methods themselves, but rather specify the manner in which the method should be called. They are:

Call name operators

Next, we have the operators that are the names of methods on objects. All of these operators can be used in their normal form (either as a unary or binary expression) or in their call form (like a normal method call). For example, foo + bar is equivalent to foo.+(bar).

Unary call name operators

Arithmetic call name operators

These operators represent what is classically considered arithmetic operations. Most of them have fast paths in the various Ruby implementations when the receiver is a numeric type. YJIT also has fast paths for all of these operators.

Bitwise call name operators

Comparison call name operators

Miscellaneous call name operators

Assignment operators

Next, we get to the assignment operators. These operators typically break down to reading a value, performing some operation on it, and then assigning it back to the receiver. For example, foo += 1 is equivalent to foo = foo + 1. However, there are a couple of exceptions.

Note that for each of these operators, the target of the expression (the expression on the left-hand side of the operator) can drastically change the semantics of the operator. The target can be any of the variable types (local, instance, class, global, constant, etc.), as well as almost any method call without arguments (e.g. foo.bar), or even some method calls with arguments (e.g. foo[1]). When the receiver is a method call, the name of the method is automatically changed by appending an =. For example, foo.bar = 1 is equivalent to foo.bar=(1).

Arithmetic assignment operators

Similarly to the arithmetic call name operators, these operators are used to perform arithmetic operations. The result is then assigned back to the receiver.

Bitwise assignment operators

Miscellaneous assignment operators

Control-flow operators

Next, we have the control-flow operators. For completeness, I’ve included some keywords in here that you might normally think of as statements, but in reality they function more similarly to infix operators.

Truthiness operators

These operators are used to check the truthiness of a value.

Conditional operators

These operators are used to perform conditional expressions.

Pattern matching operators

These operators are used to perform pattern matching.

Range operators

Finally, we get to the range operators. These operators can be used to create ranges (either inclusive or exclusive). They can also be used to create flip-flops, if the left- and right-hand side of the operator are particular kinds of expressions.

As a random bit of trivia, if an endless range is used as the final predicate to a when or in clause, then you will have to use a semicolon, the then keyword, or parentheses to delimit the end of the list.

Wrapping up

That’s a lot of operators! I hope you learned something and that this list comes in handy for educational purposes. If you have any questions or comments, feel free to reach out to me on Twitter @kddnewton or GitHub kddnewton.

← Back to home