The principle of least surprise?
Following on from yesterday's post on There's more than one way to do it, let's look at another way that is expressed in Ruby: via redundant aliases for the same method.
array = [1, 2, 3]
array.size # => 3
array.length # => 3
array.collect(&:to_s) # => ["1", "2", "3"]
array.map(&:to_s) # => ["1", "2", "3"]
array.inject(:+) # => 6
array.reduce(:+) # => 6
Why does Ruby have multiple methods that do the same thing? Let's dig into the history to find out.
The original methods used by Ruby in this example were named after their counterparts in Smalltalk: size, collect and inject. But outside of Smalltalk, it was the names used in the early functional programming languages: length, map and reduce, which propagated into other languages more widely. So to accommodate the expectations of programmers coming from other languages, Ruby added aliases for these methods.
This has been interpreted as a manifestation of "the principle of least surprise" (originally coined as "least astonishment"), which implies that a language should behave in a way that minimizes surprises for programmers. By providing multiple ways to do the same thing, Ruby allowed programmers to use the names that they were most familiar with, making the language more approachable.
What may come as a surprise, however, is that Matz has stated that he did not actually have this principle in mind when designing Ruby, and that it is more of a post-hoc rationalization for the design choices made. Instead, Matz has said that his main goal was to create a language that was enjoyable to use, and that the multiple ways to do the same thing were simply a result of that goal.
This speaks to something which I think is generally true about Ruby programming: that it encourages exploring the gap between engineering and art. Strict adherence to "principles" might suit an engineering mindset, but it's not where Ruby is coming from. Human language is full of synonyms, and Ruby, being a human-oriented language, naturally has them as well.
All that said, in the last decade it has become the de facto standard to apply linting rules to Ruby projects that do enforce a single naming convention within any given codebase. This strikes the right balance between freedom and consistency, and thanks to ever-improving auto-correction features in tools like RuboCop, it doesn't come with any maintenance burden either.
History
Addition of aliases have happened organically over the years. While length and size were both present in the very early versions of Ruby, map was added as an alias for collect in Ruby 1.6 in 2000, and reduce as an alias for inject in Ruby 1.8.7 in 2008.