Functor Object

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

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

There are a variety of programming constructs that manipulate functions rather than objects. These include Higher Order Functions, Curried Functions, Internal Iteration 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 Higher Order Functions 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 Higher Order Functions that are coded against the Functor Object Interface.

Resulting context:

Clients can parameterize objects that implement Higher Order Functions by creating Functor Objects and passing them in. We expect to find Higher Order Functions only in Functional Programming Languages, but they are actually found in more mundane settings as function pointers. The quicksort function in the standard C library is, in fact, a Higher Order Function as are callback mechanisms of all sorts. Internal Iteration is another common use for Functor Objects and is a recurring theme in Object Functional Patterns. The existence of Functor Objects makes it possible to implement a variety of other patterns including Curried Functors, Generic Functions using Functor Objects to implement SpecializedFunctions, Lazy Evaluation of Functor Objects, and other Object Functional Patterns.

Since Functor Objects are an enabling mechanism for Lazy Evaluation some of the caveats for Lazy Evaluation should be noted here. Lazy Evaluation 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 Functor Objects that may be lazily evaluated do not rely on state that may change during the time when Lazy Evaluation may occur and that it does not change state that is relied on by other operations that may occur during the same time period. Functor Objects that can have side-effects are called Procedure Objects by Thomas Kuehne. These are very useful but some care must be taken with the timing of their side-effects.

Variations:

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

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 Curried Functor.

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

Multiple results: A Functor Object can potentially calculate more than one result. In this case use Command Query Separation to separate invocation of the Functor Object from the queries that return its various results.

Composed Functor Objects: A Functor Object may represent a Higher Order Function that can be parameterized with another Functor Object. For instance a Functor Object may be parameterized with a predicate that will short-circuit the Function Object unless some condition is true. This is especially valuable for use in Internal Iteration.

Known Uses:

C++ STL (Standard Template Library) -- Stl Function Objects

In the C++ Standard Template Library, a "Function Object" is an instance of a class that implements "operator()". As such, its usage is syntactically indistinguishable from a Function Pointer - a property that lets Function Objects and Function Pointers be used interchangeably in template-based Generic Algorithms.

The benefit of using objects instead of Function Pointers is that the compiler can inline methods with Function Objects.

[See Stl Function Objects for discussion.]


Discussion:

The name, Functor Object, is a very poor one. A Functor Object 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 Dirac Delta Function, or mathematical operators such as the derivative or the Fourier Transform.

In Category Theory, 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 Topological Spaces and Continuous Maps. The HomologyMorphism H_1 sends this Category to that of Abelian Groups and Homo Morphisms. 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.

A Functor Object 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 Computer Science, 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. -- Robert Di Falco

In Category Theory, 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. -- Robert Di Falco

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 Sml Language, where a functor is a parametric structure. Because of that, Functor Object seems to be a poorly chosen name. For a similar concept the Common Lisp Object System uses the more descriptive term funcallable instance. What's wrong with Function Object, besides the fact that its Wiki Name is already taken? --

Jim Coplien uses the word 'functor' in his book 'Advanced Cee Plus Plus'. If you've got a gripe with it ask him. -- Phil Goodwin

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. -- Robert Di Falco

Andrei Alexandrescu uses the term Callable Entity in his book Modern Cee Plus Plus Design 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 ;). -- Richard Henderson.

I appreciate your humor, and at the same hope everyone who reads it understands the irony. A Functor Object (or Lambda Expression, Lexical Closure, Code Block, 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 Functor Object can be constructed in, for example, Cee Plus Plus using a function pointer -- some might argue that this was the impetus for Cee Plus Plus -- but a function pointer by itself is NOT a Functor Object.

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 Micro Architecture.

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 Pluggable Adaptor module, following the example in Smalltalk. I find this an elegant and powerful "Connecting Wire" - once you try it, you'll never turn back. -- Tom Stambaugh


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 Abstraction Inversion Anti Pattern. 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 Abstraction Inversion. 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. -- Vesa Karvonen

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 Functor Object is strongly related to the Strategy Pattern. Functor Object essentially differs from the Strategy Pattern in that a Functor Object is less specific to a particular situation and that a Functor Object always contains just one entry point. Both Strategy Pattern and Functor Object 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. -- Vesa Karvonen


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. -- Panu Kalliokoski


functor has a long history in discussions of Prolog predicates in terms of the 'functor' and the 'arity' of predicates. -- Robert Shiplett


Someone created this page to discuss objects that combine dates/ranges with monetary amounts - moved to Date And Value Object.


Discussion of Value Objects (like Money Amount) requiring garbage collection (Algorithms That Demand Garbage Collection) moved to Do Value Objects Require Garbage Collection?.


See original on c2.com