notes.dt.in.th

In Ruby, everything is an object. A lot of problems can be solved by writing code strictly from left to right, by chaining method calls.

More ways can mean more consistency.

Even though the Zen of Python states that "There should be one— and preferably only one —obvious way to do it.", but in Python, to derive a new value from an existing one, oftentimes you have to mix and match multiple syntaxes (such as method calls, functions, and list comprehensions). So, when you look at a single problem in isolation, there is often one obvious way to solve that people consistently use. But when you combine smaller solutions to form a big solution, the syntax inconsistencies become apparent.

In Ruby, there are many possible ways to accomplish the same objective. There are many synonyms and aliases in the language.

  • To convert something to an array, you can do either of these:
    • [*thing]
    • thing.to_a
  • To create an array with 5 elements filled with 'hello', you can do any of these:
    • Array.new(5) { 'hello' }
    • 5.times.map { 'hello' }
    • Array.new(5, 'hello')
    • ['hello'] * 5
  • To convert an array to hash, you can do either of these:
    • Hash[my_array]
    • my_array.to_h
  • To call a Ruby proc:
    • my_proc[arg1, arg2]
    • my_proc.(arg1, arg2)
    • my_proc.call(arg1, arg2)
  • To add things to an Array:
    • my_array << thing1 << thing2
    • my_array.push(thing1, thing2)
    • my_array.append(thing1, thing2)

While this can lead to the same problem being solved differently by different people, it also allows composing solutions using the same syntax (in this example: method calls).

Python exampleRuby
fruits.index('cherry')fruits.index('cherry')
len(fruits)fruits.count
fruits.length
fruits.size
[f for f in fruits if len(f) > 5]`fruits.select {

From the above table, you see 3 different syntaxes in Python for 3 solutions, whereas in Ruby all solutions are possible via method calls.

Value pipeline

When an object doesn't have a method you want (for example, Ruby numbers doesn't have the sqrt method), Ruby provides the then method that lets you derive a new value using an arbitrary block.

RubyAlso Ruby
Math.sqrt(16)16.then(&Math.method(:sqrt))
`16.then {
f(123)123.then(&method(:f))
`123.then {

The code on the right isn't necessarily cleaner, but when you are focused on short-term development speed (such as when you are rapid-prototyping or doing some competitive programming), you may find the .then trick useful.

Operators are methods too

RubyAlso Ruby
1 + 11.+(1) ^[The method name is +]
fruits[0]fruits.[](0) ^[The method name is []]
fruits[1] = 'banana'fruits.[](1, 'banana') ^[The method name is []=]