What about being able to shorten `users.collect { |user| user.order.city }` or its unefficient form `users.collect(&:order).collect(&:city)` into

``````users.collect(&[:order, :city])
``````

It can be achieved by composing functions, in Ruby's case by composing Procs. This is an amusing exercise that demonstrates Ruby's functional abilites.

Just in case you need to freshen your memory about composing functions, it's a common notion in functional programming and it's also found early in mathematics courses.

Given two functions `f(x)` and `g(x)`, ```(g o f)(x) == g(f(x))```, `o` being the symbol of the composition operation.

## Unchaining method calls

`users.collect { |user| user.order.city }`

The first step here is to compact the `#order` and `#city` method calls.

To achieve that, it's interesting to know how methods calls are done under the hood. Python, by being explicit by design as opposed to Ruby, gives a clear answer :

``````class User
def __init__(self, firstname, lastname):
self.firstname = firstname
self.lastname  = lastname

def name(self):
return self.firstname + self.lastname
``````

Each method accepts a first argument which is always `self`. It's simple as that, a method is nothing more than a function whose first argument is the instance. This way, attributes can be accessed trough self inside the function. Under the hood in Ruby `@firstname` is basically just a nice way to grab it from the instance without having to be explicit about `self`.

Back to our example, with that knowledge we can say that :

``````users.collect { |user| user.order.city }
``````

is equivalent in the underlying implementation to :

``````# pseudo-code
users.collect { |user| city(order(user)) }
``````

So that's it, in theory we got functions here and composing them makes sense :

``````# pseudo-code, 'o' being the hypothetical composition operator.
get_order_then_city = city o order
users.collect { |user| get_order_then_city(user) }
``````

Finally, let's convert that to real Ruby code, artificially reverting methods to their primitive forms, functions.

``````order = Proc.new { |user| user.order }
city  = Proc.new { |order| order.city }
``````

Those two Procs still need to be composed, sadly Ruby don't come with a defined composition operator for Proc, so let's write one.

## Composing functions in Ruby

As Procs are Ruby objects, it's simply a matter of adding a composition operator to the Proc class. As the symbol used in mathematics, `o` can't be used here, it's usually `*` that takes its place.

``````  increment = Proc.new { |x| x + 1 }
square    = Proc.new { |x| x * x }

increment_and_square = square * increment

p increment_and_square(2)
# => (2+1)^2 = 9
``````

Implementation is pretty straight-forward :

``````class Proc
def *(other)
Proc.new { |x| call(other.call(x)) }
end
end
``````

Now `increment` and `square` can be composed throught the `*` operator and it works as expected.

At this point, the job is almost finished. Procs can be composed, and symbols can be converted to Procs thanks to `&:order`.

`&:order` is quite common but before composing it, how does it really works ?

Behind its somewhat exotic syntax, it calls `#to_proc` which creates a Proc that sends the symbol itself, (`:order` in this case) to an object. Then it converts the Proc into a block so it can be passed to methods like `#each` or `#collect` that expects one.

In more concrete terms `&:order` creates the following Proc:

``````  get_order = Proc.new { |user| user.order }
``````

And its generalized form:

``````class Symbol
def to_proc
# This is a simplified version, the real one can handle multiple
# arguments.
Proc.new { |object| object.__send__(self) }
end
end
``````

Such Procs can as previously seen, be easily composed with the brand new `*` operator on Procs.

At this point it can be tempting to write `users.collect(&:city * &:order)` but this can't work. As a block isn't an object, calling any method on it (`#*` in this case) makes absolutely no sense. Only a single unary `&` can exist in an expression. Ruby will raise a `SyntaxError` if a second one is present.

The correct syntax with a single `&` isn't really shiny, but it works as expected.

``````users.collect(&(:city.to_proc * :order.to_proc))
# => ['Kuala Lumpur', 'Paris']
``````

But frankly, from a syntactic point of view, it's sill far from being simpler than a traditional `users.collect { |user| user.order.city }` and the order feels a bit backward.

Even if it's just for fun, better syntax can be achived by calling Array to the rescue. Having a list of Procs that will be composed makes some sense and provides a lighter syntax.

``````users.collect(&[:city, :order])
# => ['Kuala Lumpur', 'Paris']
``````

`#to_proc` can be added to basically any object, while this opens many weird and exotic possibilites it suits perfectly what is needed here.

So building a Proc from an array of symbols, given they can be converted to procs and then composed, can be written as the following:

``````class array
def to_proc
collect(&:to_proc).inject(&:*)
end
end

users.collect(&[:city, :order])
# => ['kuala lumpur', 'paris']
``````

Yet without knowing we're composing stuff under the hood, it would be nice to have the symbols ordered like the chained method calls.

``````class array
def to_proc
reverse.collect(&:to_proc).inject(&:*)
end
end

users.collect(&[:order, :city])
# => ['kuala lumpur', 'paris']
``````

And it does the job and with a nice syntax!

The only bad thing here is it has to create a Proc for each symbol and that's why nobody should use it in real code. A less fun but more practical version can be written by using `#inject` and `#send`:

``````class Array
def to_proc
Proc.new do |object|
inject(object) do |this, method_id|
this.send(method_id)
end
end
end
end
``````

#### Related posts

Mixed links of the week (2)
Introducing Photograph
Mixed links of the week (1)