Have you heard of `Enumerable#every`? It lets you apply a method call to 
all elements of an enumerable. Check it out...

  [1,2,3].every + 3  #=> [4,5,6]

  [1,2,3].every * 3  #=> [3,6,9]

  words = ["hello", "world"]
  words.every.upcase!
  words  #=> ["HELLO", "WORLD"]

Essentially every is a convenient and nicely readable "fluent notation" 
alternative to using a map/collect block.

Now you might be wondering how this bit of magic is achieved? Here is the 
definition.

    module Enumerable
       def every
          Functor.new do |op,*args|
            map{ |a| a.send(op,*args) }
          end
       end
    end

As you can see it works via something called a "Functor". Generally 
speaking, a "functor" is simply an object that encapsulates a function. In 
this case I have used the term as a concise reference to a specialized form 
of such to achieve <a href="
http://en.wikipedia.org/wiki/Higher_order_message";>Higher Order 
Messaging</a>. The basic definition of this class is:

  class Functor
    def initialize(&function)
      @function = function
    end
    def method_missing(op, *args, &blk)
      @function.call(op, *args, &blk)
    end
  end

This Functor class can be used in many many ways. Enumerable#every is just 
one of many examples. In fact, Ruby's own Enumerator class is actually just 
a highly specialized type of Functor.

As useful as a Functor can be, it does however have two downsides. First it 
depends on #method_missing. This means public Object methods 
can interfere with its usefulness. This can be worked around by making 
Functor a subclass of BasicObject. Though a few public methods remain, this 
is good enough for all practical purposes. A more problematic issue is the 
fact that it requires the creation of an indeterminate object every time 
the a method using a Functor is called. This is pretty inefficient, slows 
things down and requires us to be memory conscious. Caching can be used in 
some cases, but rarely is it an ideal fix.

Recently I came up with an idea that would allow these issues to be 
circumvented entirely. I realized that since this is a higher order 
*message*, then really it would be best handled as a messaging issue 
--hence via the definition of a "higher order method". In other words if 
Ruby had built-in support for the concept, the intermediate object would 
not be necessary and consequently interfering public methods would not 
exist. To facilitate this, I came up with a potential notation. Here's how 
it would be used to define Enumerable#every:

    module Enumerable
      def every => op, *args
        map{ |a| a.send(op,*args) }
      end
    end

(Hmm... as I typed this it occurs to me that maybe `=>` would be more 
intuitive if it pointed the other way using `<=`.) Regardless of the actual 
notation used, the idea is to allow Ruby to handle higher-order-messages 
internally as a special type of method.

For reference here are a few other examples of using Functor:
* 
https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/file.rb
* 
https://github.com/rubyworks/facets/blob/master/lib/core/facets/kernel/ergo.rb
* 
https://github.com/rubyworks/facets/blob/master/lib/core/facets/kernel/not.rb

P.S. There is also a functor gem out there, but it is not the Functor as 
defined above. The functor gem came along well after the one described here 
(which is included with Ruby Facets). The gems's implementation is 
basically a kind of struct that supports multiple dispatch capabilities. 
The above is much more generic and actually can even be used to create the 
functor gem's more specialized kind with just a bit of extra code.

-- You received this message because you are subscribed to the Google Groups 
ruby-talk-google group. To post to this group, send email to 
[email protected]. To unsubscribe from this group, send email 
to [email protected]. For more options, visit this 
group at https://groups.google.com/d/forum/ruby-talk-google?hl=en

Reply via email to