#-- # Functor # Copyright (c) 2004,2005 Thomas Sawyer # # Ruby License # # This module is free software. You may use, modify, and/or redistribute this # software under the same terms as Ruby. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. # # ========================================================================== # Revision History # ========================================================================== # 05-09-22 trans # Made a subclass of BasicObject. # # 05-01-10 trans # Ported to Mega Modules. # ========================================================================== #++ require 'mega/basicobject' #:title: Functor # # By definition a Functor is simply a first class method, but these are common # in the form of Method and Proc. So here a Functor is a bit more specialized # as a 1st class _metafunction_. Essentally, a Functor can vary its behavior # accorrding to the operation applied to it. # # == Synopsis # # require 'mega/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 # # == Author(s) # # * Thomas Sawyer # class Functor < BasicObject def initialize(*obj, &func) @obj = obj @func = func end def method_missing(op, *args) if @obj.empty? @func.call(op, *args) else @func.call(op, *(@obj + args)) end end end # _____ _ # |_ _|__ ___| |_ # | |/ _ \/ __| __| # | | __/\__ \ |_ # |_|\___||___/\__| # =begin testing require 'test/unit' class TC_Functor < Test::Unit::TestCase def test_function f = Functor.new { |op, x| x.send(op, x) } assert_equal( 2, f + 1 ) #=> 2 assert_equal( 4, f + 2 ) #=> 4 assert_equal( 6, f + 3 ) #=> 6 assert_equal( 1, f * 1 ) #=> 1 assert_equal( 4, f * 2 ) #=> 4 assert_equal( 9, f * 3 ) #=> 9 end def test_decoration f = Functor.new("A") { |op, a, x| x.send(op, a + x) } assert_equal( 'BAB', f + 'B' ) assert_equal( 'CAC', f + 'C' ) assert_equal( 'DAD', f + 'D' ) end end =end