Ruby-ish, rubbish… Get it? Anyways, not like Ruby-ish means bad! Quite the opposite!
It’s the day after Xmas and because Ruby is awesome and delivered 2.6.0, we’ll get to play with some of our new Xmas gifts:
This is a very Ruby-specific post, but hopefully everyone can get something out of this.
Let’s start with
#then, which is actually just an alias to an already-existing method:
#then is much prettier, don’t you agree?
Let me show you why this is cool.
Playing with… function composition?
Calling functions and composing them is common among most modern programming languages, be it in the form of methods, functions, lambdas, closures, blocks, procs, or whatever the language calls it.
A function is basically a calculation associated with a name. It takes some input, and returns some output.
In most programming languages, the standard way to call a function is the same as you’d do in math:
sum(2) calls the function
sum with the argument
This works most of the time, but when you need to call several functions, it can get messy.
When using the regular
f(g(x)) syntax, the first operation performed —
g(x) in this example — is hidden inside a “wrapper” function. The more wrappers we have, the harder the expression is to understand.
In the pseudo-code below, assume
people is just a list of people.
Which operation is the first there? It’s not immediately clear. We see
count first, then
nameStartsWith and then
olderThan. But the order in which they get called is actually the reverse. So it’s hard to know what this whole thing
NOTE: This is a good example of good naming conventions — the variable is called
What the functional language designers added is a new way to call functions: Instead of saying
g(x), you can say
x | g. That means “send the left side as first argument to the right side”.
That might seem arbitrary, and even useless, but consider this:
x | g | f. We can chain and call functions in the actual order they are executed!
With this new syntax, the example above reads:
Isn’t that nice?
Function composition in Ruby
In Ruby we have several things which could be called a “function”, like methods, procs, blocks, and lambdas.
Let’s work with methods for now. The standard way to combine methods is simply wrapping them:
As we saw before, the more we wrap, the harder it is to understand. There are many solutions to this problem when it comes to Ruby, the most common being the Single Responsibility Principle, or SRP. Following the principle, each method must do only one thing:
While that’s not bad for readability, we now have a new alternative:
The new method
#then simply sends the value on the left side as parameter to the right side. Sound familiar?
Chaining is usually written like this:
#then is just like using
| in the example above. The order in which the methods are read is the same as the order of execution.
So in this new example, Ruby builds a new
Person object, then passes it as first parameter to
Report#initialize, and then, because
Report#initialize returns a new instance of
Report, that is given as first argument to
#then has the advantage of showing the operations in order, the syntax has quite a lot of clutter. Wouldn’t it be nice to have some syntactic sugar to help us with this?
Well, we kind of do actually! Let’s talk about
Proc#<<. They are binary operators which work very similarly to
#then. They work on procs and methods, and always return a
Notice that because
>> returns a
Proc, we have to use
#call to evaluate it. The equivalent using
<< would be:
DIY: Full composition
#<< are nice, but they return a
Proc, and they can only be used with procs and methods. I can’t say:
Instead, I am forced to use Procs:
Also, if I want to evaluate this in-line, it gets messy:
It doesn’t behave like
#then. But because Ruby is awesome, we can create our own
Isn’t that cool? One of the things I like the most about Ruby is that you can make little Domain-Specific Languages — or DLS’s — with it. So we can make our own little language inside Ruby! And we can use that custom language to write our custom program.
NOTE: If you are into that kind of thing, then do yourself a favor and check out Lisp.
That’s it! Hope you had some fun reading this. While programming is a job, it’s good to let your inner child play with things like this, and in my case, go back to my roots as a curious kid making computers do cool stuff.
If you happen to celebrate it, then merry Xmas! Otherwise, Happy 25th of December! Every day is worthy of celebration. 🙂