Building a Better Functor

Hi,

I've been messing around a with functors lately (see [1] and [2]) and have found them really helpful for testing. They make great light-weight MockObjects. Consider the following example:

Pretend I have a method called redirect that I am trying to test:

    def redirect(url, sys=Kernel)

···

#
      # code here that writes out an HTTP header
      # that causes the redirect to url
      #

      # my header has been written so kill the script:
      sys.exit
    end

Given the following definition for a functor I can easily mock out the sys.exit call:

    class Functor
      def initialize(method, &block)
        @method = method
        @block = block
      end
      def method_missing(symbol, *args)
  if @method.to_s.intern == symbol
     @block.call(*args)
  else
            super
         end
      end
    end

Here's my test method:

    def test_redirect__exit
      exited = false
      sys = Functor.new do |meth, *args|
        exited = true if meth == :exit
      end
      redirect('test/url.html', sys)
      assert(exited)
    end

As you can see a functor is a pretty amazing little object. You can define method_missing a couple of different ways [3], but you are probably having your own ideas by now. Also note: because I'm using blocks my functor methods have access to variables that are in scope where the functor is defined (like "exited" in this case).

As I have used functors I have often found that there are times when it would be nice for a functor to support multiple methods--not just one. I've implemented seen this implemented a couple of ways, but haven't been totally satisfied with the results. Today, while talking to a colleague I hit upon an idea: why not allow functors to be added together to allow the construction of larger functor objects.

Consider the following definition for a functor:

    class Functor
       def initialize(method = nil, &block)
          @methods = {}
          add_method(method, &block) if block_given?
       end

       def __add__(f)
          n = self.class.new
          n.instance_variable_get(
             '@methods'
          ).update(
             @methods
          ).update(
             f.instance_variable_get('@methods')
          )
          n
       end

       def add_method(method, &block)
          @methods[method.to_s.intern] = block
       end

       def method_missing(symbol, *args)
          case
          when @methods.has_key?(symbol)
             @methods[symbol].call(*args)
          when symbol == :+
             __add__(*args)
          else
             super
          end
       end
    end

With an additional top level method:

    def functor(method, &block)
       Functor.new(method, &block)
    end

This will allow you to do the following:

    f = functor(:run) { puts 'running...' } +
        functor(:jump) { puts 'jumping...' } +
        functor(:play) { puts 'playing...' }

    f.run #=> "running..."
    f.jump #=> "jumping..."
    f.play #=> "playing..."

This is a seriously cool concept. I'd like to see a version of this included in the standard lib. Perhaps even added to the core by modifying proc to behave the same manner (see Nowake's proposal[1]). Does anyone else have a better implementation? Can you see ways of improving my own?

I've uploaded my tests and source code on my Web site [4].

--
[1] http://groups-beta.google.com/group/comp.lang.ruby/browse_thread/thread/491add60f8da4d0f
[2] http://rubyforge.org/pipermail/chicagogroup-members-list/2004-October/thread.html
[3] http://rubyforge.org/pipermail/chicagogroup-members-list/2004-October/000024.html
[4] http://johnwlong.com/downloads/functor/

--
John Long
http://wiseheartdesign.com

John W. Long wrote:

Here's my test method:

   def test_redirect__exit
     exited = false
     sys = Functor.new do |meth, *args|
       exited = true if meth == :exit
     end
     redirect('test/url.html', sys)
     assert(exited)
   end

er, sorry, this code should be:

    def test_redirect__exit
      exited = false
      sys = Functor.new(:exit) do
        exited = true
      end
      redirect('test/url.html', sys)
      assert(exited)
    end

···

--
John Long
http://wiseheartdesign.com

       def __add__(f)

I'm almost certain you meant to say:
   def +(f)

This is a seriously cool concept. I'd like to see a version of this
included in the standard lib. Perhaps even added to the core by modifying
proc to behave the same manner (see Nowake's proposal[1]). Does anyone else
have a better implementation? Can you see ways of improving my own?

It looks a bit like FlexMock (http://onestepback.org/software/flexmock/\).

···

On Thursday 10 February 2005 12:37 am, John W. Long wrote:

--
-- Jim Weirich jim@weirichhouse.org http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

"John W. Long" <ng@johnwlong.com> schrieb im Newsbeitrag
news:420AF309.7090306@johnwlong.com...

Hi,

I've been messing around a with functors lately (see [1] and [2]) and

have found them really helpful for testing. They make great light-weight
MockObjects. Consider the following example:

Pretend I have a method called redirect that I am trying to test:

    def redirect(url, sys=Kernel)
      #
      # code here that writes out an HTTP header
      # that causes the redirect to url
      #

      # my header has been written so kill the script:
      sys.exit
    end

Given the following definition for a functor I can easily mock out the

sys.exit call:

    class Functor
      def initialize(method, &block)
        @method = method
        @block = block
      end
      def method_missing(symbol, *args)
if @method.to_s.intern == symbol
   @block.call(*args)
else
            super
         end
      end
    end

Just one remark: I'd change that to define the method in the constructor
and not use method_missing as that's more performant.

class Functor
  def initialize(method, &block)
    class << self;self;end.class_eval do
      define_method(method,&block)
    end
  end
end

This variant does not allow for easy adding of methods via Functor#+
though. But you can easily define a method add(method,&block) that adds a
method and returns self for chaining:

class Functor
  def add(method, &block)
    class << self;self;end.class_eval do
      define_method(method,&block)
    end
    self
  end

  alias :initialize :add
end

Functor.new(:x){puts "x"}.
  add(:y){puts "y"}.
  add(:z){puts "z"}.y

Kind regards

    robert

Hi--

Just FYI. I do not think this is what one calls a Functor exactly,
since the object is independent of the method ( please see
http://jakarta.apache.org/commons/sandbox/functor/ ).

What you have is sort of an OpenStruct for methods. While closely
related it's not exactly the same. I think the going name for what you
have defined is MethodProc ( see
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/114197 ).

Of course, by strict definition a Method _is_ a Functor. But that
doesn't get us very far :wink: I take it a step further and consider a
Functor a "MetaMethod". Ruby Carats (yet to be released) includes just
such a Functor class. Here is the trival use case:

  require 'carat/functor'

  f = Functor.new { |op, x| x.send(op, x) }
  f + 1 #=> 2
  f + 2 #=> 4
  f + 3 #=> 6
  f * 1 #=> 1
  f * 2 #=> 2
  f * 3 #=> 9

Here's the definition:

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

Hope you find this of interest,
T

Jim Weirich wrote:

      def __add__(f)

I'm almost certain you meant to say:
   def +(f)

Actually no. I used __add__(f) along this in method_missing:

> when symbol == :+
> __add__(*args)

Because I wanted people to be able to define their own behavior for plus:

f = functor (:+) { |value| 1 + value }

puts f + 1

···

On Thursday 10 February 2005 12:37 am, John W. Long wrote:

--
John Long
http://wiseheartdesign.com

Robert Klemme wrote:

This variant does not allow for easy adding of methods via Functor#+
though. But you can easily define a method add(method,&block) that adds a
method and returns self for chaining:

class Functor
  def add(method, &block)
    class << self;self;end.class_eval do
      define_method(method,&block)
    end
    self
  end

  alias :initialize :add
end

Functor.new(:x){puts "x"}.
  add(:y){puts "y"}.
  add(:z){puts "z"}.y

Mmm, not sure. I really like the ability to use the + method. Seems like there should be a way to use "define_method" and still support the "+" method. Anybody have time to give it a go?

···

--
John Long
http://wiseheartdesign.com

Robert Klemme wrote:

    class << self;self;end.class_eval do

This particular trick has shown up a lot on the Ruby list lately. It's kind of ugly, but clearly useful. I think it deserves a name, or possibly a new keyword. What would you call it, "virtual_class_eval"?

···

--
Glenn Parker | glenn.parker-AT-comcast.net | <http://www.tetrafoil.com/&gt;

Trans wrote:

Hi--

Just FYI. I do not think this is what one calls a Functor exactly,
since the object is independent of the method ( please see
Commons Functor - Overview ).

> . . .
>

  f = Functor.new { |op, x| x.send(op, x) }
  f + 1 #=> 2
  f + 2 #=> 4
  f + 3 #=> 6
  f * 1 #=> 1
  f * 2 #=> 2
  f * 3 #=> 9

> . . .

Interesting. So how exactly would you define a functor? What you have shown above seems to be an object that knows how to do some kind of operation using a user-defined method. Is this how you would define a functor?

···

--
John Long
http://wiseheartdesign.com

Apparently I haven't been paying attention. What does the above do, and how does it differ from:

class Foo
  def self.add( meth, &block )
    self.class_eval{ define_method( meth, &block ) }
  end
end

or

class Foo
  def add( meth, &block )
    self.class.class_eval{ define_method( meth, &block ) }
  end
end

?

Is it to add new methods to the instance only, and not all instances derived from Foo?

···

On Feb 10, 2005, at 6:41 AM, Glenn Parker wrote:

Robert Klemme wrote:

    class << self;self;end.class_eval do

This particular trick has shown up a lot on the Ruby list lately. It's kind of ugly, but clearly useful. I think it deserves a name, or possibly a new keyword. What would you call it, "virtual_class_eval"?

--
(-, /\ \/ / /\/

Interesting. So how exactly would you define a functor?
What you have shown above seems to be an object that
knows how to do some kind of operation using a
user-defined method. Is this how you would define a functor?

A good question. By standard definition, Method objects and Proc
objects are Functors. Since Ruby already has these I'm simply defining
a Functor as a "MetaMethod" for the sake of a distinction. By this I
mean an object the represents a method which can act on another method.
Function composition, represented as a 1st class object, for instance,
would also be a Functor of this sort.

T.

"Gavin Kistner" <gavin@refinery.com> schrieb im Newsbeitrag
news:991b24e67ac5d4902f4b04192210830a@refinery.com...

> Robert Klemme wrote:
>> class << self;self;end.class_eval do
>
> This particular trick has shown up a lot on the Ruby list lately.
> It's kind of ugly, but clearly useful. I think it deserves a name, or
> possibly a new keyword. What would you call it, "virtual_class_eval"?

Apparently I haven't been paying attention. What does the above do, and
how does it differ from:

class Foo
def self.add( meth, &block )
self.class_eval{ define_method( meth, &block ) }
end
end

or

class Foo
def add( meth, &block )
self.class.class_eval{ define_method( meth, &block ) }
end
end

?

Is it to add new methods to the instance only, and not all instances
derived from Foo?

Exactly.

    robert

···

On Feb 10, 2005, at 6:41 AM, Glenn Parker wrote:

--
(-, /\ \/ / /\/

Trans wrote:

Interesting. So how exactly would you define a functor?
What you have shown above seems to be an object that
knows how to do some kind of operation using a
user-defined method. Is this how you would define a functor?

A good question. By standard definition, Method objects and Proc
objects are Functors. Since Ruby already has these I'm simply defining
a Functor as a "MetaMethod" for the sake of a distinction. By this I
mean an object the represents a method which can act on another method.
Function composition, represented as a 1st class object, for instance,
would also be a Functor of this sort.

And a functor, by definition only handles one method? Which is why what I have written is not a functor?

···

--
John

Coming from Javascript (where every instance is trivially extensible directly) that seems somewhat cumbersome.

Do many people write things like:

class Object
  def instance_class
    class<<self; self; end
  end
end

in a common library they re-use frequently? Is there an RCR (or has there been discussion) about adding a simple method like that to the language, so you can simply do:

f = Foo.new
f.instance_class.class_eval{ ... }
?

Or (what I'm really looking for) perhaps it might be nice to have a define_method method that worked directly for instances. Hrm, but what would the syntax be? Perhaps that's not such a good idea.

···

On Feb 10, 2005, at 7:35 AM, Robert Klemme wrote:

"Gavin Kistner" <gavin@refinery.com> schrieb im Newsbeitrag
news:991b24e67ac5d4902f4b04192210830a@refinery.com...

Robert Klemme wrote:

    class << self;self;end.class_eval do

Is it to add new methods to the instance only, and not all instances
derived from Foo?

Exactly.

And a functor, by definition only handles one method? Which
is why what. I have written is not a functor?

Yes. But that not to say what you have written isn't close (and damn
cool). I just wouldn't call it a Functor per se. Certainly, your first
example is very close, since it only stores a single block, so I see
why you'd call it a Functor. But it's the block inside that's actually
the Functor. You're creating more of a Functor Delegator. A minor
distinction no doubt. Maybe not even worth considering. But I thought
I'd point it out.

T.

Well, no, maybe it would be nice. Something like:

class Object
  def add_method( name, &block )
    case self
      when Class
        self.class_eval{
          define_method( name, &block )
        }
      else
        class<<self; self; end.class_eval{
          define_method( name, &block )
        }
    end
  end
end

class Foo
  def whee; puts "#{self} says 'whee'"; end
end

Foo.add_method( 'yow' ){ puts "#{self} says 'yow!'" }

f1 = Foo.new
f2 = Foo.new

f1.whee
#=> #<Foo:0x1cbdec> says 'whee'

f1.yow
#=> #<Foo:0x1cbdec> says 'yow!'

f2.add_method( 'booya!' ){ puts "#{self} says 'booya!'" }
f2.booya!
#=> #<Foo:0x1cbdc4> says 'booya!'

f1.booya!
#=> tmp.rb:33: undefined method `booya!' for #<Foo:0x1cbdec> (NoMethodError)

I'm certainly adding that to my personal library, but it seems like it would be a nice (useful, good, less-hacks-needed) built-in.

···

On Feb 10, 2005, at 7:47 AM, Gavin Kistner wrote:

Or (what I'm really looking for) perhaps it might be nice to have a define_method method that worked directly for instances. Hrm, but what would the syntax be? Perhaps that's not such a good idea.

--
(-, /\ \/ / /\/

Ruby Facets:

  require 'facet/object/special_class'

  f = Foo.new
  f.special_class
  f.special_class_eval { ... }
  f.define_special_method( :meth_name ) { ... }

These are also aliased as "singleton" in place of the word "special".
"Singeton" is the more commonly used term, but it sometimes causes
confusion because of Singleton Pattern. So I choose "special" to help
clarify --being more percise.

See http://calibre.rubyforge.org/

T

It's been discussed several times, but no one has come up with a good
name for it yet. (I like proxy_class myself.)

martin

···

Gavin Kistner <gavin@refinery.com> wrote:

in a common library they re-use frequently? Is there an RCR (or has
there been discussion) about adding a simple method like that to the
language, so you can simply do:

"Gavin Kistner" <gavin@refinery.com> schrieb im Newsbeitrag
news:eee6f56d3405a57c4480046c35fca189@refinery.com...

> "Gavin Kistner" <gavin@refinery.com> schrieb im Newsbeitrag
> news:991b24e67ac5d4902f4b04192210830a@refinery.com...
>>> Robert Klemme wrote:
>>>> class << self;self;end.class_eval do
>> Is it to add new methods to the instance only, and not all instances
>> derived from Foo?
>
> Exactly.

Coming from Javascript (where every instance is trivially extensible
directly) that seems somewhat cumbersome.

JavaScript has no classes as far as I know. Ruby has classes and from
that alone it's obvious that it's a bit more complicated. Usually when
you define instance methods you do

obj = ....
class <<obj
  def this_is_only_visible_in_a_single_instance() ... end
end

The construction with class<<self;self;end is only needed in order to be
able to drag local variables into the class_eval block.

Do many people write things like:

class Object
def instance_class
class<<self; self; end
end
end

in a common library they re-use frequently? Is there an RCR (or has
there been discussion)

Discussion - a lot, RCR - maybe.

about adding a simple method like that to the
language, so you can simply do:

f = Foo.new
f.instance_class.class_eval{ ... }

class Object
  def instance_class() class<<self;self;end end
end

?

Or (what I'm really looking for) perhaps it might be nice to have a
define_method method that worked directly for instances. Hrm, but what
would the syntax be? Perhaps that's not such a good idea.

IMHO it's sufficient to have the simplified access to the singleton class.
OTOH, it's not too difficult to obtain that, so...

Regards

    robert

···

On Feb 10, 2005, at 7:35 AM, Robert Klemme wrote:

In article <eee6f56d3405a57c4480046c35fca189@refinery.com>,

"Gavin Kistner" <gavin@refinery.com> schrieb im Newsbeitrag
news:991b24e67ac5d4902f4b04192210830a@refinery.com...

Robert Klemme wrote:

    class << self;self;end.class_eval do

Is it to add new methods to the instance only, and not all instances
derived from Foo?

Exactly.

Coming from Javascript (where every instance is trivially extensible
directly) that seems somewhat cumbersome.

Do many people write things like:

class Object
def instance_class
  class<<self; self; end
end
end

in a common library they re-use frequently? Is there an RCR (or has
there been discussion) about adding a simple method like that to the
language, so you can simply do:

f = Foo.new
f.instance_class.class_eval{ ... }
?

Or (what I'm really looking for) perhaps it might be nice to have a
define_method method that worked directly for instances. Hrm, but what
would the syntax be? Perhaps that's not such a good idea.

Isn't this the common way of doing this:

  f = Foo.new
  def f.somemethod
    "in somemethod"
  end

  f.somemethod #=> "in somemethod"

Phil

···

Gavin Kistner <gavin@refinery.com> wrote:

On Feb 10, 2005, at 7:35 AM, Robert Klemme wrote: