liveBook · Manning

Syntactic sugar

As explained in The Well-Grounded Rubyist, Fourth Edition

Syntactic sugar is a language feature that provides a more convenient or readable syntax for expressing an operation supported by the language's ordinary rules.

In Ruby, `1 + 2` looks like an arithmetic expression, but `+` is a method call: `1.+(2)`. Syntactic sugar is a convenient way to write certain calls without the usual `object.method(arguments)` form. The notation changes how a call looks, not which method receives it. section 7.2

Assignment-like syntax works the same way. `ticket.price = 63.00` calls `price=` on `ticket`, passing `63.00`. It does not assign to a variable named `ticket.price`. The method can do more than store the value: a price setter might reject an amount with extra decimal places, while a year setter might normalize a two-digit year. section 3.3.2 section 3.3.3

Give an object an operator

Define `+` as a method, and an instance can be used with `obj + 100`. Ruby calls `obj.+(100)`. The method’s behavior is yours to define, though a surprising meaning for `+` can mislead readers. Similarly, defining `-` lets an account object use `acc -= 5`: the shortcut stands for `acc = acc - 5`. section 7.2.1

This pattern extends beyond arithmetic to indexing, comparisons, case equality, and bitwise operations. Not every operator can be redefined: `||=` and `&&=` offer shortcut notation, but their underlying `||` and `&&` operators cannot be overridden. When an arithmetic operator behaves unexpectedly, inspect its method definition. section 7.2.1 section 8.3.2

Table 7.2 Methods with operator-style syntactic sugar–calling notation 

Category

Name

Definition example

Calling
example

Sugared
notation

Arithmetic method/operators

+

def +(x)

obj.+(x)

obj + x

-

def -(x)

obj.-(x)

obj - x

*

def *(x)

obj.*(x)

obj * x

/

def /(x)

obj./(x)

obj / x

% (modulo)

def %(x)

obj.%(x)

obj % x

** (exponent)

def **(x)

obj.**(x)

obj ** x

Get/set/append data

[]

def [](x)

obj.[](x)

obj[x]

[]=

def []=(x,y)

obj.[]=(x,y)

obj[x] = y

<<

def <<(x)

obj.<<(x)

obj << x

Comparison method/operators

<=>

def <=>(x)

obj.<=>(x)

obj <=> x

==

def ==(x)

obj.==(x)

obj == x

>

def >(x)

obj.>(x)

obj > x

<

def <(x)

obj.<(x)

obj < x

>=

def >=(x)

obj.>=(x)

obj >= x

<=

def <=(x)

obj.<=(x)

obj <= x

Case equality operator

===

def ===(x)

obj.===(x)

Obj === x

Bitwise operators

| (OR)

def |(x)

obj.|(x)

obj | x

& (AND)

def &(x)

obj.&(x)

obj & x

^ (XOR)

def ^(x)

obj.^(x)

obj ^ x

Compare ordinary method calls with their operator-style forms, including `obj.[](x)` and `obj[x]`. section 7.2.1

How The Well-Grounded Rubyist, Fourth Edition covers it

How deep it goes
Explains the method calls behind setter and operator notation, including custom definitions, shortcuts, semantic pitfalls, and non-overridable operators.
Examples
Uses a ticket price setter, normalized travel year, custom `+`, bank-account `-=`, and arithmetic written as explicit method calls.
What it assumes
Assumes familiarity with Ruby objects and method calls while explaining how familiar-looking assignment and operators invoke methods.
What you can do after
Build it from scratch by defining setter or operator methods, and diagnose/debug surprising operator behavior by checking those methods.
How it connects
Connects setter methods and operator methods to method dispatch, validation, normalization, and compound assignment.

Also explained in

Compare how 2 books explain syntactic sugar →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Well-Grounded Rubyist, Fourth Edition. The section links point to the parts of the book it draws on.