Functor Object

A FunctorObject is an object that acts as a function, and can be operated upon like an object.

See FunctionalPatternSystemForObjectOrientedDesign.

In many languages which support these, there is a conventionally named method that executes or computes the function, for example "run()" in EeLanguage, or "operator()" in CeePlusPlus.

There are a variety of programming constructs that manipulate functions rather than objects. These include HigherOrderFunctions, CurriedFunctions, InternalIteration and callback mechanisms among others. In order to use these constructs effectively it is necessary to be able to capture references to functions rather than just call them.

Therefore:

(In strongly typed languages) Create a family of interfaces that describe function call signatures. Use generic programming, generic types (like Java's Object) or naming conventions to insulate users and implementers of these interfaces from each other. Program HigherOrderFunctions and other functional clients in terms of this interface. Implement adapter classes that can make the methods of ordinary objects available to these functional clients. Use block closures in Smalltalk, inner classes in Java and the ->* syntax in C++. Program objects whose behavior is to be parameterized using HigherOrderFunctions that are coded against the FunctorObjectInterface?.

Resulting context:

Clients can parameterize objects that implement HigherOrderFunctions by creating FunctorObjects and passing them in. We expect to find HigherOrderFunctions only in FunctionalProgrammingLanguages, but they are actually found in more mundane settings as function pointers. The quicksort function in the standard C library is, in fact, a HigherOrderFunction as are callback mechanisms of all sorts. InternalIteration is another common use for FunctorObjects and is a recurring theme in ObjectFunctionalPatterns. The existence of FunctorObjects makes it possible to implement a variety of other patterns including CurriedFunctors, GenericFunctions using FunctorObjects to implement SpecializedFunctions, LazyEvaluation of FunctorObjects, and other ObjectFunctionalPatterns.

Since FunctorObjects are an enabling mechanism for LazyEvaluation some of the caveats for LazyEvaluation should be noted here. LazyEvaluation makes it impossible to know the exact order in which operations will be executed and in fact makes it possible for some operations not to be executed at all. It is therefore important to ensure that the FunctorObjects that may be lazily evaluated do not rely on state that may change during the time when LazyEvaluation may occur and that it does not change state that is relied on by other operations that may occur during the same time period. FunctorObjects that can have side-effects are called Procedure Objects by ThomasKuehne. These are very useful but some care must be taken with the timing of their side-effects.

Variations:

Argument binding: The basic FunctorObject is supplied with its parameters at invocation time. It is possible, however, to separate argument application from invocation. The PythonLanguage uses default argument values to make this separation. In other languages it is possible to create FunctorObjects that can appear to store parameter values until invocation time. This is the enabling infrastructure for CurriedFunctors.

Keyword parameters: Argument application can be further generalized by providing a mechanism for supplying parameters by name. This could be done through named methods or through keyword strings. Such an application can produce a new object - a form of CurriedFunctor.

Default parameters: A FunctorObject can also come with some parameters pre-applied. In this case the defaults can be overridden by some form of argument binding before the FunctorObject is actually invoked.

Multiple results: A FunctorObject can potentially calculate more than one result. In this case use CommandQuerySeparation to separate invocation of the FunctorObject from the queries that return its various results.

Composed FunctorObjects: A FunctorObject may represent a HigherOrderFunction that can be parameterized with another FunctorObject. For instance a FunctorObject may be parameterized with a predicate that will short-circuit the FunctionObject unless some condition is true. This is especially valuable for use in InternalIteration.

Known Uses:

C++ STL (Standard Template Library) -- StlFunctionObjects

In the C++ StandardTemplateLibrary, a "FunctionObject" is an instance of a class that implements "operator()". As such, its usage is syntactically indistinguishable from a FunctionPointer - a property that lets FunctionObjects and FunctionPointers be used interchangeably in template-based GenericAlgorithms?.

The benefit of using objects instead of FunctionPointers is that the compiler can inline methods with FunctionObjects.

[See StlFunctionObjects for discussion.]

See also: FunctorObjectExample, BlocksInJava, FunctionalProgrammingInCpp


Discussion:

The name, FunctorObject, is a very poor one. A FunctorObject is an object that acts as a function, and can be operated upon like an object. As such, they are akin to mathematical functionals such as the DiracDeltaFunction, or mathematical operators such as the derivative or the FourierTransform.

In CategoryTheory, the field of mathematics where the term Functor originates, a Functor is a mapping from one Category to another that respects Morphisms [functions]. For example, consider the Category of TopologicalSpaces and ContinuousMaps. The HomologyMorphism H_1 sends this Category to that of AbelianGroups and HomoMorphisms. This means that if I have the following series of continuous topological maps:

           f             g
    S  ---------> T ----------> U,

I also get the series of homomorphisms:

         H_1(f)        H_1(g)
  H_1(S) -----> H_1(T) ------> H_1(U),

and H_1(gf) = H_1(g)H_1(f).

You don't need to understand that; my point is that Functors act on the entire problem domain, not just on functions or upon arguments. The only example I can think of right now is this.

Consider the Category of Objects and Algorithms for functions whose results depend on no hidden variables. For example, real numbers and the sine function, but not decks of cards and a random shuffle function. Then, define the memoize functor to take objects to themselves, and algorithms to their memoized versions. The is a valid map from that category to itself - the memoized algorithm uses hidden variables, but the results do not.

-- EricJablow

A FunctorObject is an object that acts as a function, and can be operated upon like an object.

I think this would mean that it was very well named? The word functor comes from the latin from Latin f´┐Żnctio, which means performance of a function. A synonym for functor is function. In ComputerScience, it is very much like a lambda and sometimes no different than a function. In fact, even in Category Theory the use theory of functors and function theory analogously. -- RobertDiFalco

In CategoryTheory, the field of mathematics where the term Functor originates

This isn't true. Category Theory like many other branches of science and mathematics uses the term functor but it did not originate in abstract algebra -- at least that's not what my research says. Even if it did originate in Category Theory with set-valued functors or functory category, it wouldn't matter. In this case, we are talking about functors as they exist in programming languages where for decades, a functor has analogous to a function. -- RobertDiFalco

The term functor as used in Category Theory was originally borrowed from Carnap, and has been used unambiguously in mathematics at least since 1950. Anyway, there is a well established use of the term in computer science, specifically in the SmlLanguage, where a functor is a parametric structure. Because of that, FunctorObject seems to be a poorly chosen name. For a similar concept the CommonLispObjectSystem uses the more descriptive term funcallable instance. What's wrong with FunctionObject, besides the fact that its WikiName is already taken? --

JimCoplien uses the word 'functor' in his book 'AdvancedCeePlusPlus?'. If you've got a gripe with it ask him. -- PhilGoodwin

True, as Phil knows there are tons of synonyms for this such as: functor, functoid, function object, lexical closure, closure, code-block, and so on. There is a lot of history for functor and functiod, especially regarding enclosing functions in objects. -- RobertDiFalco

AndreiAlexandrescu uses the term CallableEntity? in his book ModernCeePlusPlusDesign to refer to C-like functions, pointers or references to C-like functions, objects that define an operator(), or the result of applying operator.* or operator->* with a pointer to a member function in the right-hand side of the expression.

Let me see, when would I use this? Oh yes, when I need a function pointer. Nice to see an OO solution ;). -- RichardHenderson.

I appreciate your humor, and at the same hope everyone who reads it understands the irony. A FunctorObject (or LambdaExpression, LexicalClosure, CodeBlock?, etc) includes a snapshot of its context (for example, a frame within which to bind its arguments and a safe place to answer its results). A naked function pointer, unless written very carefully, does not. It is certainly true that a FunctorObject can be constructed in, for example, CeePlusPlus using a function pointer -- some might argue that this was the impetus for CeePlusPlus -- but a function pointer by itself is NOT a FunctorObject.

No indeed, and I was only half-joking. I really do need safe function pointer-like behaviour. Specifically this provides a perfect analog of a connecting wire which explicitly connects two objects that don't need to know details about each other. Each adapts to the other by "requesting" a connection. Previously I used external adapter objects but this is much lighter weight and generally lovely MicroArchitecture.

Is there a restriction on the degree of independence that a functor has from its parent? I'm jumping on its adapter properties, but the Factory pattern is not so far away in that there is an equivalent interaction.

One of the first things I built from these, in Java, was a PluggableAdaptor module, following the example in Smalltalk. I find this an elegant and powerful "ConnectingWire?" - once you try it, you'll never turn back. -- TomStambaugh
Functors may also inform a factory about what they can do - either by proxy, or directly, allowing the factory to select the "optimum" functor from a collection of functors, using hints provided by the invoker of the factory...
When a language forces you to emulate simple functional values using a much more complicated object mechanism it is basically an instance of the AbstractionInversion AntiPattern. I'm not saying that it would not make sense to emulate functional values using the object mechanism in an OO language that doesn't provide first class functional values, but I'm saying that the language effectively forces AbstractionInversion. Consider the following example:

  Scheme:  ((lambda (x) x) 1)

Java: new Function() { public Object with(Object x) { return x; }}.with(new Integer(1))

Even if the manifest typing would be removed from the Java version, there would still be an unnecessary indirection in the Java version. The dispatch to the with-method happens indirectly, which is not necessary as the necessary indirection is already provided by the use of the functional value. -- VesaKarvonen

Of course, Java's not exactly a good example of a proper OO language, Smalltalk does it with pure objects while remaining as simple as the Scheme equivalent.

  [:x | x ] value: 1


Another issue worth mentioning is that FunctorObject is strongly related to the StrategyPattern. FunctorObject essentially differs from the StrategyPattern in that a FunctorObject is less specific to a particular situation and that a FunctorObject always contains just one entry point. Both StrategyPattern and FunctorObject are essentially "just parameterization". The most likely reason why they are given the high status as patterns in OO languages is that behavioral parameterization using functional values is not necessarily immediately obvious in OO languages that do not support first class functional values. -- VesaKarvonen
I would like to note that "functor" is a misnomer. It already has a meaning of "a morphism from category to category", which is approximately what a template is in C++ parlance. -- PanuKalliokoski
functor has a long history in discussions of Prolog predicates in terms of the 'functor' and the 'arity' of predicates. -- RobertShiplett
Someone created this page to discuss objects that combine dates/ranges with monetary amounts - moved to DateAndValueObject.


Discussion of ValueObjects (like MoneyAmount?) requiring garbage collection (AlgorithmsThatDemandGarbageCollection) moved to Do ValueObjectsRequireGarbageCollection?.


CategoryObjectFunctionalPatterns CategoryCodingConventions

EditText of this page (last edited September 10, 2014) or FindPage with title or text search