From time to time returning
seems to violate the so-called principle of least surprise:
returning([]) do |arr|
arr += [:foo, :bar]
end
=> []
Let's work up from pure simplicity:
begin
x = 1
y = x
x = x + 1
y
end
=> 1
begin
x = []
y = x
x = x + [:foo, :bar]
y
end
=> []
begin
x = []
y = x
x += [:foo, :bar]
y
end
=> []
Compare and contrast with:
begin
x = []
y = x
x.concat [:foo, :bar]
y
end
=> [:foo, :bar]
Which leads to:
returning([]) do |arr|
arr.concat [:foo, :bar]
end
=> [:foo, :bar]
There is similar behaviour with things like returning('') do ...
, any time you have a value with constructive methods (methods that return copies of the object). Things like ActiveRecord instances almost never have methods with these semantics, so people almost never get this mixed up.
The principles behind this code are much more basic than returning
, it's really a question of understanding values, references, and which Ruby methods are destructive and which are constructive. I note that it is not part of the Ruby culture to disambiguate them. For example, !
is used in the standard library for destructive methods, but only when a constructive version of the same method already exists.
It is a matter of wonder why ordering arrays is handled with sort
and sort!
, but catenation is handled with +
and concat
.
My recent work:
- JavaScript Allongé, CoffeeScript Ristretto, and my other books.
- allong.es, practical function combinators and decorators for JavaScript.
- Method Combinators, a CoffeeScript/JavaScript library for writing method decorators, simply and easily.
- jQuery Combinators, what else? A jQuery plugin for writing your own fluent, jQuery-like code.
(Spot a bug or a spelling mistake? This is a Github repo, fork it and send me a pull request!)