Skip to content

02 — Methods and arguments

One line: A Ruby method call needs no parentheses, no return, no self, and its argument list can carry positionals, defaults, splats, keywords and a block — and each of those is a place where a Python reader's model needs one adjustment.

This chapter is about the shape of a call and of a definition. Ruby drops the parentheses, returns whatever the last expression produced, evaluates a default argument fresh on every call, marks dangerous methods with ! and predicates with ?, makes + and [] and ! ordinary methods you can define, sends a receiverless call to an implicit self, skips a call on nil with &., and makes an assignment obj.x = v evaluate to v no matter what the setter's body returns.

A Python programmer arrives with most of the right ideas: functions take positional and keyword arguments, *args and **kwargs collect the rest, and operators are dunder methods underneath. What breaks is the details — Python needs parentheses to call, returns None unless you say return, evaluates a default once at def time (the mutable-default trap), has no ? or ! in a name, and treats assignment as a statement with no value. Every page here prints both behaviours side by side.

Lesson Level The one thing
Parentheses are optional, but the space is not 101 a bare name is a call, and puts (1+2)*3 is not puts(1+2)*3
The last expression is the return value 101 no return needed; a method that ends in puts returns nil
Arguments: positional, keyword, splat and block 201 the eight kinds of parameter, ... forwarding and the three ArgumentError messages
Default arguments are evaluated on every call 201 def f(a = []) is fresh each call; Python's def f(a=[]) is not
Bang means dangerous, question mark means predicate 101 sort! mutates, strip! returns nil when nothing changed, empty? answers
Operators are methods, except the ones that are not 201 +, [], <=>, ! are methods you define; &&, ||, = are syntax
self is the implicit receiver 201 a receiverless call goes to self; a setter needs self.x =
&. skips the call when the receiver is nil 101 nil&.length is nil and the arguments are not even evaluated
A setter returns its argument, not its body 201 obj.x = 5 evaluates to 5 whatever def x= returns

Read more