Array arithmetic
Earlier this week we looked at how Ruby allows using arithmetic on Time objects to easily advance or rewind time. Another example of this kind of operator overloading in Ruby can be found on Array:
# + performs array concatenation
[1, 2, 3] + [2, 4]
# => [1, 2, 3, 2, 4]
# - performs array difference
[1, 2, 3] - [2, 4]
# => [1, 3]
# * performs array repetition
[1, 2, 3] * 2
# => [1, 2, 3, 1, 2, 3]
# & performs array intersection
[1, 2, 3] & [2, 4]
# => [2]
# | performs array union
[1, 2, 3] | [2, 4]
# => [1, 2, 3, 4]
// No built-in operators for these operations, but we can achieve the same results with methods:
// Concatenation
[1, 2, 3].concat([2, 4]);
// => [1, 2, 3, 2, 4]
// Difference
[1, 2, 3].filter(x => ![2, 4].includes(x));
// => [1, 3]
// Repetition
Array(2).fill([1, 2, 3]).flat();
// => [1, 2, 3, 1, 2, 3]
// Intersection
[1, 2, 3].filter(x => [2, 4].includes(x));
// => [2]
// Union
[...new Set([1, 2, 3].concat([2, 4]))];
// => [1, 2, 3, 4]
Some things to note:
- The + operator does not mutate the original array. It returns a new array with the concatenated result. If you want to mutate the original array, you can (and probably should, for performance) use the #concat method instead.
- There are named methods for other operations as well. In particular, #intersection and #union probably communicate the intent more clearly than the & and | operators.
History
All the Array arithmetic methods have been part of Ruby since its inception.
The named method #union was added in Ruby 2.6, released in 2018.
The named method #intersection was added in Ruby 2.7, released in 2019.
Speculating about inspiration, I believe Smalltalk probably provides the closest precedent, though it does so by providing methods like intersection, union and difference rather than operators.
Python has + and * operators for lists, but doesn't cover the others. Python is also not recognized as having influenced Ruby's design in any significant way.