Jump to content

Function object: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
In C and C++: removed erroneous reference to sortInts (the example uses std::sort instead)
Rescuing 1 sources and tagging 0 as dead.) #IABot (v2.0.9.5
 
(76 intermediate revisions by 51 users not shown)
Line 1: Line 1:
{{Short description|Programming construct}}
{{About|the computer programming concept|functors in category theory|Functor}}
{{About|the computer programming concept of function objects|functors in mathematics|Functor|the related concept in functional programming|Functor (functional programming)}}
{{Refimprove|date=February 2009}}
{{Refimprove|date=February 2009}}
A '''function object'''{{efn|1=In C++, a '''functionoid''' is an object that has one major method, and a '''functor''' is a special case of a functionoid.<ref>[http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.15 33.15: What's the difference between a functionoid and a functor?]</ref> They are similar to a function object, ''but not the same''.}} is a [[computer programming]] construct allowing an [[object (computer science)|object]] to be invoked or called as if it were an ordinary [[subroutine|function]], usually with the same syntax (a function parameter that can also be a function).
In [[computer programming]], a '''function object'''{{efn|1=In C++, a '''functionoid''' is an object that has one major method, and a '''functor''' is a special case of a functionoid.<ref>[https://isocpp.org/wiki/faq/pointers-to-members#functor-vs-functionoid What's the difference between a functionoid and a functor?]</ref> They are similar to a function object, ''but not the same''.}} is a construct allowing an [[object (computer science)|object]] to be invoked or called as if it were an ordinary [[subroutine|function]], usually with the same syntax (a function parameter that can also be a function). In some languages, particularly C++, function objects are often called '''functors''' (not related to [[Functor (functional programming)|the functional programming concept]]).


== Description ==
== Description ==
Line 8: Line 9:
| title = C++ Tutorial Part I - Basic: 5.10 Function pointers are mainly used to achieve call back technique, which will be discussed right after.
| title = C++ Tutorial Part I - Basic: 5.10 Function pointers are mainly used to achieve call back technique, which will be discussed right after.
| author = Silan Liu
| author = Silan Liu
| authorlink =
| date =
| publisher = TRIPOD: Programming Tutorials Copyright © Silan Liu 2002
| publisher = TRIPOD: Programming Tutorials Copyright © Silan Liu 2002
| quote = Function pointers are mainly used to achieve call back technique, which will be discussed right after.
| quote = Function pointers are mainly used to achieve call back technique, which will be discussed right after.
| accessdate = 2012-09-07
| access-date = 2012-09-07
}}</ref> However it can be difficult or awkward to pass a state into or out of the callback function. This restriction also inhibits more dynamic behavior of the function. A function object solves those problems since the function is really a [[facade pattern|façade]] for a full object, carrying its own state.
}}</ref> However it can be difficult or awkward to pass a state into or out of the callback function. This restriction also inhibits more dynamic behavior of the function. A function object solves those problems since the function is really a [[facade pattern|façade]] for a full object, carrying its own state.


Line 19: Line 18:
| title = C++ Tutorial Part I - Basic: 5.10 Function pointers are mainly used to achieve call back technique, which will be discussed right after.
| title = C++ Tutorial Part I - Basic: 5.10 Function pointers are mainly used to achieve call back technique, which will be discussed right after.
| author = Paweł Turlejski
| author = Paweł Turlejski
| authorlink =
| date = 2009-10-02
| date = 2009-10-02
| publisher = Just a Few Lines
| publisher = Just a Few Lines
| quote = PHP 5.3, along with many other features, introduced closures. So now we can finally do all the cool stuff that Ruby / Groovy / Scala / any_modern_language guys can do, right? Well, we can, but we probably won’t… Here’s why.
| quote = PHP 5.3, along with many other features, introduced closures. So now we can finally do all the cool stuff that Ruby / Groovy / Scala / any_modern_language guys can do, right? Well, we can, but we probably won’t… Here's why.
| accessdate = 2012-09-07
| access-date = 2012-09-07
}}</ref> [[Functional programming]] languages additionally support [[closure (computer science)|closures]], i.e. first-class functions that can 'close over' variables in their surrounding environment at creation time. During compilation, a transformation known as [[lambda lifting]] converts the closures into function objects.
}}</ref> [[Functional programming]] languages additionally support [[closure (computer science)|closures]], i.e. first-class functions that can 'close over' variables in their surrounding environment at creation time. During compilation, a transformation known as [[lambda lifting]] converts the closures into function objects.


== In C and C++ ==
== In C and C++ ==
Consider the example of a sorting routine that uses a callback function to define an ordering relation between a pair of items. The following C/C++ program uses function pointers:
{{Cleanup| reason=This section does not make sense the way it is currently written; something seems to have happened in [https://en.wikipedia.org/enwiki/w/index.php?title=Function_object&diff=563019155&oldid=560572313 this edit from 2013] that messed up the example; for instance the repeated referral to a non-existing sortInts() function.|date=March 2015}}
<!-- NOTE: For the compareInts() implementation below, see http://stackoverflow.com/a/10997428/1629102 for an explanation of why the more simple (int) a - (int) b would not work in all cases. -->
Consider the example of a sorting routine that uses a callback function to define an ordering relation between a pair of items. A C program using function pointers may appear as:
<syntaxhighlight lang="c">

<source lang=C>
#include <stdlib.h>
#include <stdlib.h>


/* Callback function, returns < 0 if a < b, > 0 if a > b, 0 if a == b */
/* qsort() callback function, returns < 0 if a < b, > 0 if a > b, 0 if a == b */
int compareInts(const void* a, const void* b)
int compareInts(const void* a, const void* b)
{
{
return *(const int *)a - *(const int *)b;
return ( *(int *)a - *(int *)b );
}
}
...
...
Line 48: Line 45:
return 0;
return 0;
}
}
</syntaxhighlight>
</source>


In C++, a function object may be used instead of an ordinary function by defining a class that [[operator overloading|overloads]] the [[function call operator]] by defining an <code>operator()</code> member function. In C++, this is called a ''class type functor'', and may appear as follows:
In C++, a function object may be used instead of an ordinary function by defining a class that [[operator overloading|overloads]] the [[function call operator]] by defining an <code>operator()</code> member function. In C++, this may appear as follows:


<source lang=Cpp>
<syntaxhighlight lang="cpp">
// comparator predicate: returns true if a < b, false otherwise
// comparator predicate: returns true if a < b, false otherwise
struct IntComparator
struct IntComparator
Line 61: Line 58:
}
}
};
};

...
// An overload of std::sort is:
template <class RandomIt, class Compare>
void sort(RandomIt first, RandomIt last, Compare comp);
...
int main()
int main()
{
{
Line 72: Line 65:
return 0;
return 0;
}
}
</syntaxhighlight>
</source>


Notice that the syntax for providing the callback to the <code>std::sort()</code> function is identical, but an object is passed instead of a function pointer. When invoked, the callback function is executed just as any other member function, and therefore has full access to the other members (data or functions) of the object.
Notice that the syntax for providing the callback to the <code>std::sort()</code> function is identical, but an object is passed instead of a function pointer. When invoked, the callback function is executed just as any other member function, and therefore has full access to the other members (data or functions) of the object. Of course, this is just a trivial example. To understand what power a functor provides more than a regular function, consider the common use case of sorting objects by a particular field. In the following example, a functor is used to sort a simple employee database by each employee's ID number.


<syntaxhighlight lang="cpp">
It is possible to use function objects in situations other than as callback functions (although the shortened term ''functor'' is normally not used). Continuing the example,
struct CompareBy
{
const std::string SORT_FIELD;
CompareBy(const std::string& sort_field="name")
: SORT_FIELD(sort_field)
{
/* validate sort_field */
}
bool operator()(const Employee& a, const Employee& b) const
{
if (SORT_FIELD == "name")
return a.name < b.name;
else if (SORT_FIELD == "age")
return a.age < b.age;
else if (SORT_FIELD == "idnum")
return a.idnum < b.idnum;
else
/* throw exception or something */
}
};


int main()
<source lang=Cpp>
{
IntComparator cpm;
std::vector<Employee> emps;
bool result = cpm(a, b);
</source>
/* code to populate database */
// Sort the database by employee ID number
std::sort(emps.begin(), emps.end(), CompareBy("idnum"));
return 0;
}
</syntaxhighlight>

In [[C++11]], the lambda expression provides a more succinct way to do the same thing.

<syntaxhighlight lang="cpp">
int main()
{
std::vector<Employee> emps;
/* code to populate database */
const std::string sort_field = "idnum";
std::sort(emps.begin(), emps.end(), [&sort_field](const Employee& a, const Employee& b) const { /* code to select and compare field */ });
return 0;
}
</syntaxhighlight>

It is possible to use function objects in situations other than as callback functions. In this case, the shortened term ''functor'' is normally ''not'' used about the function object. Continuing the example,

<syntaxhighlight lang="cpp">
IntComparator cpm;
bool result = cpm(a, b);
</syntaxhighlight>


In addition to class type functors, other kinds of function objects are also possible in C++. They can take advantage of C++'s member-pointer or [[generic programming|template]] facilities. The expressiveness of templates allows some [[functional programming]] techniques to be used, such as defining function objects in terms of other function objects (like [[function composition (computer science)|function composition]]). Much of the C++ [[Standard Template Library]] (STL) makes heavy use of template-based function objects.
In addition to class type functors, other kinds of function objects are also possible in C++. They can take advantage of C++'s member-pointer or [[generic programming|template]] facilities. The expressiveness of templates allows some [[functional programming]] techniques to be used, such as defining function objects in terms of other function objects (like [[function composition (computer science)|function composition]]). Much of the C++ [[Standard Template Library]] (STL) makes heavy use of template-based function objects.


Another way to create a function object in C++ is to define a non-explicit conversion function to a function pointer type, a function [[reference (C++)|reference]] type, or a reference to function pointer type. Assuming the conversion does not discard [[Type_qualifier|cv-qualifiers]], this allows an object of that type to be used as a function with the same [[function signature|signature]] as the type it is converted to. Modifying an earlier example to use this we obtain the following class, whose instances can be called like function pointers:<ref>{{cite web|url=https://en.cppreference.com/enwiki/w/cpp/language/overload_resolution#Call_to_a_class_object|title=Overload resolution§Call to a class object|website=cppreference.com}}</ref>
[[C++11]] allows one to define [[anonymous function]] objects. The line from the prior example could be written as follows:


<source lang=Cpp>
<syntaxhighlight lang="cpp">
// comparator predicate: returns true if a < b, false otherwise
std:;sort(items.begin(), items.end(), [](int a, int b) { return a < b; });
struct IntComparator
</source>
{
static bool compare(const int &a, const int &b)
{
return a < b;
}
using T = decltype(compare);
operator T*() const { return compare; }
};

int main()
{
std::vector<int> items { 4, 3, 1, 2 };
std::sort(items.begin(), items.end(), IntComparator());
return 0;
}
</syntaxhighlight>


=== Maintaining state ===
=== Maintaining state ===
Another advantage of function objects is their ability to maintain a state that affects <code lang=C>operator()</code> between calls. For example, the following code defines a [[generator (computer science)|generator]] counting from 10 upwards and is invoked 11 times.


Another advantage of function objects is their ability to maintain a state that affects <code>operator()</code> between calls. For example, the following code defines a [[generator (computer science)|generator]] counting from 10 upwards and is invoked 11 times.
<source lang=Cpp>

<syntaxhighlight lang="cpp">
#include <algorithm>
#include <iostream>
#include <iostream>
#include <iterator>
#include <iterator>
#include <algorithm>


class CountFrom {
class CountFrom {
public:
private:
int &count;
CountFrom(int count) : count_(count) {}
public:
CountFrom(int &n) : count(n) {}
int operator()() { return count_++; }

int operator()() { return count++; }
private:
int count_;
};
};


int main()
int main() {
const int state(10);
{
std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 11,
int state(10);
std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 11, CountFrom(state));
CountFrom(state));
return 0;
}
}
</syntaxhighlight>
</source>

In C++14 or later, the example above could be rewritten as:

<syntaxhighlight lang="cpp">
#include <algorithm>
#include <iostream>
#include <iterator>

int main() {
std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 11,
[count=10]() mutable { return count++; });
}
</syntaxhighlight>


== In C# ==
== In C# ==
In [[C Sharp (programming language)|C#]], function objects are declared via [[delegate (CLI)|delegate]]s. A delegate can be declared using a named method or a [[Lambda (programming)|lambda expression]]. Here is an example using a named method.
In [[C Sharp (programming language)|C#]], function objects are declared via [[delegate (CLI)|delegate]]s. A delegate can be declared using a named method or a [[Lambda (programming)|lambda expression]]. Here is an example using a named method.


<source lang=CSharp>
<syntaxhighlight lang="csharp">
using System;
using System;
using System.Collections.Generic;
using System.Collections.Generic;


public class ComparisonClass1 {
public class ComparisonClass1
{
public static int CompareFunction(int x, int y) {
public static int CompareFunction(int x, int y)
{
return x - y;
return x - y;
}
}


public static void Main() {
public static void Main()
{
List<int> items = new List<int> { 4, 3, 1, 2 };
var items = new List<int> { 4, 3, 1, 2 };

Comparison<int> del = CompareFunction;
Comparison<int> del = CompareFunction;

items.Sort(del);
items.Sort(del);
}
}
}
}
</syntaxhighlight>
</source>


Here is an example using a lambda expression.
Here is an example using a lambda expression.


<source lang=CSharp>
<syntaxhighlight lang="csharp">
using System;
using System;
using System.Collections.Generic;
using System.Collections.Generic;


public class ComparisonClass2 {
public class ComparisonClass2
{
public static void Main() {
public static void Main()
{
List<int> items = new List<int> { 4, 3, 1, 2 };
var items = new List<int> { 4, 3, 1, 2 };
items.Sort((x, y) => x - y);
items.Sort((x, y) => x - y);
}
}
}
}
</syntaxhighlight>
</source>


== In D ==
== In D ==
[[D (programming language)|D]] provides several ways to declare function objects: Lisp/Python-style via [[closure (computer science)|closures]] or C#-style via [[delegate (CLI)|delegate]]s, respectively:
[[D (programming language)|D]] provides several ways to declare function objects: Lisp/Python-style via [[closure (computer science)|closures]] or C#-style via [[delegate (CLI)|delegate]]s, respectively:


<source lang=D>
<syntaxhighlight lang="d">
bool find(T)(T[] haystack, bool delegate(T) needle_test) {
bool find(T)(T[] haystack, bool delegate(T) needle_test) {
foreach (straw; haystack) {
foreach (straw; haystack) {
Line 169: Line 246:
return n == needle;
return n == needle;
}
}
assert(
assert(find(haystack, &needleTest));
find(haystack, &needleTest)
);
}
}
</syntaxhighlight>
</source>


The difference between a [[delegate (CLI)|delegate]] and a [[closure (computer science)|closure]] in D is automatically and conservatively determined by the compiler. D also supports function literals, that allow a lambda-style definition:
The difference between a [[delegate (CLI)|delegate]] and a [[closure (computer science)|closure]] in D is automatically and conservatively determined by the compiler. D also supports function literals, that allow a lambda-style definition:


<source lang=D>
<syntaxhighlight lang="d">
void main() {
void main() {
int[] haystack = [345, 15, 457, 9, 56, 123, 456];
int[] haystack = [345, 15, 457, 9, 56, 123, 456];
int needle = 123;
int needle = 123;
assert(find(haystack, (int n) { return n == needle; }));
assert(
find(haystack, (int n) { return n == needle; })
);
}
}
</syntaxhighlight>
</source>


To allow the compiler to inline the code (see above), function objects can also be specified C++-style via [[operator overloading]]:
To allow the compiler to inline the code (see above), function objects can also be specified C++-style via [[operator overloading]]:


<source lang=D>
<syntaxhighlight lang="d">
bool find(T, F)(T[] haystack, F needle_test) {
bool find(T, F)(T[] haystack, F needle_test) {
foreach (straw; haystack) {
foreach (straw; haystack) {
Line 208: Line 281:
}
}
}
}
assert(
assert(find(haystack, new NeedleTest(needle)));
find(haystack, new NeedleTest(needle))
);
}
}
</syntaxhighlight>
</source>


== In Eiffel ==
== In Eiffel ==


In the [[Eiffel (programming language)|Eiffel]] software development method and language, operations and objects are seen always as separate concepts. However, the [[Eiffel (programming language)#Agents|agent]] mechanism facilitates the modeling of operations as runtime objects. Agents satisfy the range of application attributed to function objects, such as being passed as arguments in procedural calls or specified as callback routines. The design of the agent mechanism in Eiffel attempts to reflect the object-oriented nature of the method and language. An agent is an object that generally is a direct instance of one of the two library classes, which model the two types of routines in Eiffel: <code lang=Eiffel>PROCEDURE</code> and <code lang=Eiffel>FUNCTION</code>. These two classes descend from the more abstract <code lang=Eiffel>ROUTINE</code>.
In the [[Eiffel (programming language)|Eiffel]] software development method and language, operations and objects are seen always as separate concepts. However, the [[Eiffel (programming language)#Agents|agent]] mechanism facilitates the modeling of operations as runtime objects. Agents satisfy the range of application attributed to function objects, such as being passed as arguments in procedural calls or specified as callback routines. The design of the agent mechanism in Eiffel attempts to reflect the object-oriented nature of the method and language. An agent is an object that generally is a direct instance of one of the two library classes, which model the two types of routines in Eiffel: <code>PROCEDURE</code> and <code>FUNCTION</code>. These two classes descend from the more abstract <code>ROUTINE</code>.


Within software text, the language keyword <code lang=Eiffel>agent</code> allows agents to be constructed in a compact form. In the following example, the goal is to add the action of stepping the gauge forward to the list of actions to be executed in the event that a button is clicked.
Within software text, the language keyword <code>agent</code> allows agents to be constructed in a compact form. In the following example, the goal is to add the action of stepping the gauge forward to the list of actions to be executed in the event that a button is clicked.


<source lang=Eiffel>
<syntaxhighlight lang="eiffel">
my_button.select_actions.extend (agent my_gauge.step_forward)
my_button.select_actions.extend (agent my_gauge.step_forward)
</syntaxhighlight>
</source>


The routine <code lang=Eiffel>extend</code> referenced in the example above is a feature of a class in a graphical user interface (GUI) library to provide [[event-driven programming]] capabilities.
The routine <code>extend</code> referenced in the example above is a feature of a class in a graphical user interface (GUI) library to provide [[event-driven programming]] capabilities.


In other library classes, agents are seen to be used for different purposes. In a library supporting data structures, for example, a class modeling linear structures effects [[universal quantification]] with a function <code lang=Eiffel>for_all</code> of type <code lang=Eiffel>BOOLEAN</code> that accepts an agent, an instance of <code lang=Eiffel>FUNCTION</code>, as an argument. So, in the following example, <code lang=Eiffel>my_action</code> is executed only if all members of <code lang=Eiffel>my_list</code> contain the character '!':
In other library classes, agents are seen to be used for different purposes. In a library supporting data structures, for example, a class modeling linear structures effects [[universal quantification]] with a function <code>for_all</code> of type <code>BOOLEAN</code> that accepts an agent, an instance of <code>FUNCTION</code>, as an argument. So, in the following example, <code>my_action</code> is executed only if all members of <code>my_list</code> contain the character '!':


<source lang=Eiffel>
<syntaxhighlight lang="eiffel">
my_list: LINKED_LIST [STRING]
my_list: LINKED_LIST [STRING]
...
...
Line 235: Line 306:
end
end
...
...
</syntaxhighlight>
</source>


When agents are created, the arguments to the routines they model and even the target object to which they are applied can be either ''closed'' or left ''open''. Closed arguments and targets are given values at agent creation time. The assignment of values for open arguments and targets is deferred until some point after the agent is created. The routine <code lang=Eiffel>for_all</code> expects as an argument an agent representing a function with one open argument or target that conforms to actual generic parameter for the structure (<code lang=Eiffel>STRING</code> in this example.)
When agents are created, the arguments to the routines they model and even the target object to which they are applied can be either ''closed'' or left ''open''. Closed arguments and targets are given values at agent creation time. The assignment of values for open arguments and targets is deferred until some point after the agent is created. The routine <code>for_all</code> expects as an argument an agent representing a function with one open argument or target that conforms to actual generic parameter for the structure (<code>STRING</code> in this example.)


When the target of an agent is left open, the class name of the expected target, enclosed in braces, is substituted for an object reference as shown in the text <code lang=Eiffel>agent {STRING}.has ('!')</code> in the example above. When an argument is left open, the question mark character ('?') is coded as a placeholder for the open argument.
When the target of an agent is left open, the class name of the expected target, enclosed in braces, is substituted for an object reference as shown in the text <code>agent {STRING}.has ('!')</code> in the example above. When an argument is left open, the question mark character ('?') is coded as a placeholder for the open argument.


The ability to close or leave open targets and arguments is intended to improve the flexibility of the agent mechanism. Consider a class that contains the following procedure to print a string on standard output after a new line:
The ability to close or leave open targets and arguments is intended to improve the flexibility of the agent mechanism. Consider a class that contains the following procedure to print a string on standard output after a new line:


<source lang=Eiffel>
<syntaxhighlight lang="eiffel">
print_on_new_line (s: STRING)
print_on_new_line (s: STRING)
-- Print `s' preceded by a new line
-- Print `s' preceded by a new line
Line 249: Line 320:
print ("%N" + s)
print ("%N" + s)
end
end
</syntaxhighlight>
</source>


The following snippet, assumed to be in the same class, uses <code lang=Eiffel>print_on_new_line</code> to demonstrate the mixing of open arguments and open targets in agents used as arguments to the same routine.
The following snippet, assumed to be in the same class, uses <code>print_on_new_line</code> to demonstrate the mixing of open arguments and open targets in agents used as arguments to the same routine.


<source lang=Eiffel>
<syntaxhighlight lang="eiffel">
my_list: LINKED_LIST [STRING]
my_list: LINKED_LIST [STRING]
...
...
Line 260: Line 331:
my_list.do_all (agent print_on_new_line (?))
my_list.do_all (agent print_on_new_line (?))
...
...
</syntaxhighlight>
</source>


This example uses the procedure <code lang=Eiffel>do_all</code> for linear structures, which executes the routine modeled by an agent for each item in the structure.
This example uses the procedure <code>do_all</code> for linear structures, which executes the routine modeled by an agent for each item in the structure.


The sequence of three instructions prints the strings in <code lang=Eiffel>my_list</code>, converts the strings to lowercase, and then prints them again.
The sequence of three instructions prints the strings in <code>my_list</code>, converts the strings to lowercase, and then prints them again.


Procedure <code lang=Eiffel>do_all</code> iterates across the structure executing the routine substituting the current item for either the open argument (in the case of the agents based on <code lang=Eiffel>print_on_new_line</code>), or the open target (in the case of the agent based on <code lang=Eiffel>to_lower</code>).
Procedure <code>do_all</code> iterates across the structure executing the routine substituting the current item for either the open argument (in the case of the agents based on <code>print_on_new_line</code>), or the open target (in the case of the agent based on <code>to_lower</code>).


Open and closed arguments and targets also allow the use of routines that call for more arguments than are required by closing all but the necessary number of arguments:
Open and closed arguments and targets also allow the use of routines that call for more arguments than are required by closing all but the necessary number of arguments:


<source lang=Eiffel>
<syntaxhighlight lang="eiffel">
my_list.do_all (agent my_multi_arg_procedure (closed_arg_1, ?, closed_arg_2, closed_arg_3)
my_list.do_all (agent my_multi_arg_procedure (closed_arg_1, ?, closed_arg_2, closed_arg_3)
</syntaxhighlight>
</source>


The Eiffel agent mechanism is detailed in the [http://www.ecma-international.org/publications/standards/Ecma-367.htm Eiffel ISO/ECMA standard document].
The Eiffel agent mechanism is detailed in the [http://www.ecma-international.org/publications/standards/Ecma-367.htm Eiffel ISO/ECMA standard document].


== In Java ==
== In Java ==
[[Java (programming language)|Java]] has no [[first-class function]]s, so function objects are usually expressed by an interface with a single method (most commonly the <code lang=Java>Callable</code> interface), typically with the implementation being an anonymous [[inner class]], or, starting in Java 8, a [[anonymous function|lambda]].
[[Java (programming language)|Java]] has no [[first-class function]]s, so function objects are usually expressed by an interface with a single method (most commonly the <code>Callable</code> interface), typically with the implementation being an anonymous [[inner class]], or, starting in Java 8, a [[anonymous function|lambda]].


For an example from Java's standard library, <code lang=Java>java.util.Collections.sort()</code> takes a <code lang=Java>List</code> and a functor whose role is to compare objects in the List. Without first-class functions, the function is part of the Comparator interface. This could be used as follows.
For an example from Java's standard library, <code>java.util.Collections.sort()</code> takes a <code>List</code> and a functor whose role is to compare objects in the List. Without first-class functions, the function is part of the Comparator interface. This could be used as follows.


<source lang=Java>
<syntaxhighlight lang="java">
List<String> list = Arrays.asList("10", "1", "20", "11", "21", "12");
List<String> list = Arrays.asList("10", "1", "20", "11", "21", "12");
Line 291: Line 362:


Collections.sort(list, numStringComparator);
Collections.sort(list, numStringComparator);
</syntaxhighlight>
</source>


In Java 8+, this can be written as:
In Java 8+, this can be written as:
<source lang=Java>
<syntaxhighlight lang="java">
List<String> list = Arrays.asList("10", "1", "20", "11", "21", "12");
List<String> list = Arrays.asList("10", "1", "20", "11", "21", "12");
Comparator<String> numStringComparator = (str1, str2) -> Integer.valueOf(str1).compareTo(Integer.valueOf(str2);
Comparator<String> numStringComparator = (str1, str2) -> Integer.valueOf(str1).compareTo(Integer.valueOf(str2));


Collections.sort(list, numStringComparator);
Collections.sort(list, numStringComparator);
</syntaxhighlight>
</source>


== In JavaScript ==
== In JavaScript ==
Line 307: Line 378:
Compare the following with the subsequent Python example.
Compare the following with the subsequent Python example.


<source lang=JavaScript>
<syntaxhighlight lang="javascript">
function Accumulator(start) {
function Accumulator(start) {
var current = start;
var current = start;
Line 314: Line 385:
};
};
}
}
</syntaxhighlight>
</source>


An example of this in use:
An example of this in use:


<source lang=JavaScript>
<syntaxhighlight lang="javascript">
var a = Accumulator(4);
var a = Accumulator(4);
var x = a(5); // x has value 9
var x = a(5); // x has value 9
Line 324: Line 395:


var b = Accumulator(42);
var b = Accumulator(42);
x = b(7); // x has value 49 (current = 42 in closure b)
x = b(7); // x has value 49 (current = 49 in closure b)
x = a(7); // x has value 18 (current = 11 in closure a)
x = a(7); // x has value 18 (current = 18 in closure a)
</syntaxhighlight>
</source>

== In Julia ==
In [[Julia_(programming_language)|Julia]], methods are associated with types, so it is possible to make any arbitrary Julia object "callable" by adding methods to its type. (Such "callable" objects are sometimes called "functors.")

An example is this accumulator mutable struct (based on [[Paul Graham (computer programmer)|Paul Graham's]] study on programming language syntax and clarity):<ref>[http://www.paulgraham.com/accgen.html Accumulator Generator]</ref>

<syntaxhighlight lang="julia-repl">
julia> mutable struct Accumulator
n::Int
end

julia> function (acc::Accumulator)(n2)
acc.n += n2
end

julia> a = Accumulator(4)
Accumulator(4)

julia> a(5)
9

julia> a(2)
11

julia> b = Accumulator(42)
Accumulator(42)

julia> b(7)
49
</syntaxhighlight>

Such an accumulator can also be implemented using closure:

<syntaxhighlight lang="julia-repl">
julia> function Accumulator(n0)
n = n0
function(n2)
n += n2
end
end
Accumulator (generic function with 1 method)

julia> a = Accumulator(4)
(::#1) (generic function with 1 method)

julia> a(5)
9

julia> a(2)
11

julia> b = Accumulator(42)
(::#1) (generic function with 1 method)

julia> b(7)
49
</syntaxhighlight>


== In Lisp and Scheme ==
== In Lisp and Scheme ==
Line 335: Line 463:
Many uses of functors in languages like C++ are simply emulations of the missing closure constructor. Since the programmer cannot directly construct a closure, they must define a class that has all of the necessary state variables, and also a member function. Then, construct an instance of that class instead, ensuring that all the member variables are initialized through its constructor. The values are derived precisely from those local variables that ought to be captured directly by a closure.
Many uses of functors in languages like C++ are simply emulations of the missing closure constructor. Since the programmer cannot directly construct a closure, they must define a class that has all of the necessary state variables, and also a member function. Then, construct an instance of that class instead, ensuring that all the member variables are initialized through its constructor. The values are derived precisely from those local variables that ought to be captured directly by a closure.


A function-object using the class system, no use of closures:
A function-object using the class system in Common Lisp, no use of closures:


<source lang=Lisp>
<syntaxhighlight lang="lisp">
(defclass counter ()
(defclass counter ()
((value :initarg :value :accessor value-of)))
((value :initarg :value :accessor value-of)))
Line 351: Line 479:
(functor-call *c*) --> 11
(functor-call *c*) --> 11
(functor-call *c*) --> 12
(functor-call *c*) --> 12
</syntaxhighlight>
</source>


Since there is no standard way to make funcallable objects in Lisp, we fake it by defining a generic function called FUNCTOR-CALL. This can be specialized for any class whatsoever. The standard FUNCALL function is not generic; it only takes function objects.
Since there is no standard way to make funcallable objects in Common Lisp, we fake it by defining a generic function called FUNCTOR-CALL. This can be specialized for any class whatsoever. The standard FUNCALL function is not generic; it only takes function objects.


It is this FUNCTOR-CALL generic function that gives us function objects, which are ''a computer programming construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax.'' We have ''almost'' the same syntax: FUNCTOR-CALL instead of FUNCALL. Some Lisps provide ''funcallable'' objects as a simple extension. Making objects callable using the same syntax as functions is a fairly trivial business. Making a function call operator work with different kinds of ''function things'', whether they be class objects or closures is no more complicated than making a + operator that works with different kinds of numbers, such as integers, reals or complex numbers.
It is this FUNCTOR-CALL generic function that gives us function objects, which are ''a computer programming construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax.'' We have ''almost'' the same syntax: FUNCTOR-CALL instead of FUNCALL. Some Lisps provide ''funcallable'' objects as a simple extension. Making objects callable using the same syntax as functions is a fairly trivial business. Making a function call operator work with different kinds of ''function things'', whether they be class objects or closures is no more complicated than making a + operator that works with different kinds of numbers, such as integers, reals or complex numbers.
Line 359: Line 487:
Now, a counter implemented using a closure. This is much more brief and direct. The INITIAL-VALUE argument of the MAKE-COUNTER [[factory function]] is captured and used directly. It does not have to be copied into some auxiliary class object through a constructor. It ''is'' the counter. An auxiliary object is created, but that happens ''behind the scenes''.
Now, a counter implemented using a closure. This is much more brief and direct. The INITIAL-VALUE argument of the MAKE-COUNTER [[factory function]] is captured and used directly. It does not have to be copied into some auxiliary class object through a constructor. It ''is'' the counter. An auxiliary object is created, but that happens ''behind the scenes''.


<source lang=Lisp>
<syntaxhighlight lang="lisp">
(defun make-counter (value)
(defun make-counter (value)
(lambda () (incf value)))
(lambda () (incf value)))
Line 367: Line 495:
(funcall *c*) ; --> 11
(funcall *c*) ; --> 11
(funcall *c*) ; --> 12
(funcall *c*) ; --> 12
</syntaxhighlight>
</source>


Scheme makes closures even simpler, and Scheme code tends to use such higher-order programming somewhat more idiomatically.
Scheme makes closures even simpler, and Scheme code tends to use such higher-order programming somewhat more idiomatically.


<source lang=scheme>
<syntaxhighlight lang="scheme">
(define (make-counter value)
(define (make-counter value)
(lambda () (set! value (+ value 1)) value))
(lambda () (set! value (+ value 1)) value))
Line 378: Line 506:
(c) ; --> 11
(c) ; --> 11
(c) ; --> 12
(c) ; --> 12
</syntaxhighlight>
</source>


More than one closure can be created in the same lexical environment. A vector of closures, each implementing a specific kind of operation, can quite faithfully emulate an object that has a set of virtual operations. That type of [[single dispatch]] object-oriented programming can be done fully with closures.
More than one closure can be created in the same lexical environment. A vector of closures, each implementing a specific kind of operation, can quite faithfully emulate an object that has a set of virtual operations. That type of [[single dispatch]] object-oriented programming can be done fully with closures.
Line 388: Line 516:
In [[Objective-C]], a function object can be created from the <code>NSInvocation</code> class. Construction of a function object requires a method signature, the target object, and the target selector. Here is an example for creating an invocation to the current object's <code>myMethod</code>:
In [[Objective-C]], a function object can be created from the <code>NSInvocation</code> class. Construction of a function object requires a method signature, the target object, and the target selector. Here is an example for creating an invocation to the current object's <code>myMethod</code>:


<source lang=ObjC>
<syntaxhighlight lang="objc">
// Construct a function object
// Construct a function object
SEL sel = @selector(myMethod);
SEL sel = @selector(myMethod);
NSInvocation* inv = [NSInvocation invocationWithMethodSignature:
NSInvocation* inv = [NSInvocation invocationWithMethodSignature:
[[self methodSignatureForSelector:sel]];
[self methodSignatureForSelector:sel]];
[inv setTarget:self];
[inv setTarget:self];
[inv setSelector:sel];
[inv setSelector:sel];
Line 398: Line 526:
// Do the actual invocation
// Do the actual invocation
[inv invoke];
[inv invoke];
</syntaxhighlight>
</source>


An advantage of <code>NSInvocation</code> is that the target object can be modified after creation. A single <code>NSInvocation</code> can be created and then called for each of any number of targets, for instance from an observable object. An <code>NSInvocation</code> can be created from only a protocol, but it is not straightforward. See [http://www.a-coding.com/2010/10/making-nsinvocations.html here].
An advantage of <code>NSInvocation</code> is that the target object can be modified after creation. A single <code>NSInvocation</code> can be created and then called for each of any number of targets, for instance from an observable object. An <code>NSInvocation</code> can be created from only a protocol, but it is not straightforward. See [http://www.a-coding.com/2010/10/making-nsinvocations.html here].
Line 406: Line 534:
In [[Perl]], a function object can be created either from a class's constructor returning a function closed over the object's instance data, blessed into the class:
In [[Perl]], a function object can be created either from a class's constructor returning a function closed over the object's instance data, blessed into the class:


<source lang=Perl>
<syntaxhighlight lang="perl">
package Acc1;
package Acc1;
sub new {
sub new {
Line 418: Line 546:
}
}
1;
1;
</syntaxhighlight>
</source>


or by overloading the &{} operator so that the object can be used as a function:
or by overloading the <code>&{}</code> operator so that the object can be used as a function:


<source lang=Perl>
<syntaxhighlight lang="perl">
package Acc2;
package Acc2;
use overload
use overload
Line 429: Line 557:
my $self = shift;
my $self = shift;
sub {
sub {
$num = shift;
my $num = shift;
$self->{arg} += $num;
$self->{arg} += $num;
}
}
Line 441: Line 569:
}
}
1;
1;
</syntaxhighlight>
</source>


In both cases the function object can be used either using the dereferencing arrow syntax ''$ref->(@arguments)'':
In both cases the function object can be used either using the dereferencing arrow syntax ''$ref->(@arguments)'':


<source lang=Perl>
<syntaxhighlight lang="perl">
use Acc1;
use Acc1;
my $a = Acc1->new(42);
my $a = Acc1->new(42);
# prints '52'
print $a->(10), "\n"; # prints 52
print $a->(10), "\n";
print $a->(8), "\n"; # prints 60
</syntaxhighlight>
# prints '60'
print $a->(8), "\n";
</source>
or using the coderef dereferencing syntax ''&$ref(@arguments)'':
or using the coderef dereferencing syntax ''&$ref(@arguments)'':
<source lang=Perl>
<syntaxhighlight lang="perl">
use Acc2;
use Acc2;
my $a = Acc2->new(12);
my $a = Acc2->new(12);
# prints '22'
print &$a(10), "\n"; # prints 22
print &$a(10), "\n";
print &$a(8), "\n"; # prints 30
</syntaxhighlight>
# prints '30'
print &$a(8), "\n";
</source>


== In PHP ==
== In PHP ==
Line 467: Line 591:
[[PHP]] 5.3+ has [[first-class function]]s that can be used e.g. as parameter to the usort() function:
[[PHP]] 5.3+ has [[first-class function]]s that can be used e.g. as parameter to the usort() function:


<source lang=PHP>
<syntaxhighlight lang="php">
$a = array(3, 1, 4);
$a = array(3, 1, 4);
usort($a, function ($x, $y) { return $x - $y; });
usort($a, function ($x, $y) { return $x - $y; });
</syntaxhighlight>
</source>

[[PHP]] 5.3+, supports also lambda functions and closures.

<syntaxhighlight lang="php">
function Accumulator($start)
{
$current = $start;
return function($x) use(&$current)
{
return $current += $x;
};
}
</syntaxhighlight>

An example of this in use:

<syntaxhighlight lang="php">
$a = Accumulator(4);
$x = $a(5);
echo "x = $x<br/>"; // x = 9
$x = $a(2);
echo "x = $x<br/>"; // x = 11
</syntaxhighlight>


It is also possible in PHP 5.3+ to make objects invokable by adding a magic __invoke() method to their class:<ref name="phpinvoke">[http://php.net/manual/en/language.oop5.magic.php#object.invoke PHP Documentation on Magic Methods]</ref>
It is also possible in PHP 5.3+ to make objects invokable by adding a magic __invoke() method to their class:<ref name="phpinvoke">[http://php.net/manual/en/language.oop5.magic.php#object.invoke PHP Documentation on Magic Methods]</ref>


<source lang=PHP>
<syntaxhighlight lang="php">
class Minus {
class Minus
{
public function __invoke($x, $y) {
public function __invoke($x, $y)
{
return $x - $y;
return $x - $y;
}
}
Line 483: Line 632:
$a = array(3, 1, 4);
$a = array(3, 1, 4);
usort($a, new Minus());
usort($a, new Minus());
</syntaxhighlight>
</source>


== In PowerShell ==
== In PowerShell ==
Line 489: Line 638:
In the [[Windows PowerShell]] language, a script block is a collection of statements or expressions that can be used as a single unit. A script block can accept arguments and return values. A script block is an instance of a Microsoft [[.NET Framework]] type System.Management.Automation.ScriptBlock.
In the [[Windows PowerShell]] language, a script block is a collection of statements or expressions that can be used as a single unit. A script block can accept arguments and return values. A script block is an instance of a Microsoft [[.NET Framework]] type System.Management.Automation.ScriptBlock.


<source lang=PowerShell>
<syntaxhighlight lang="powershell">
Function Get-Accumulator($x) {
Function Get-Accumulator($x) {
{
{
param($y)
param($y)
return $script:x += $y
return $x += $y
}.GetNewClosure()
}.GetNewClosure()
}
}
</syntaxhighlight>
</source>
<source lang=PowerShell>
<syntaxhighlight lang="ps1con">
PS C:\> $a = Get-Accumulator 4
PS C:\> $a = Get-Accumulator 4

PS C:\> & $a 5
PS C:\> & $a 5

9
9

PS C:\> & $a 2
PS C:\> & $a 2

11
11

PS C:\> $b = Get-Accumulator 32
PS C:\> $b = Get-Accumulator 32

PS C:\> & $b 10
PS C:\> & $b 10

42
42
</syntaxhighlight>
</source>


== In Python ==
== In Python ==
Line 520: Line 662:
An example is this accumulator class (based on [[Paul Graham (computer programmer)|Paul Graham's]] study on programming language syntax and clarity):<ref>[http://www.paulgraham.com/accgen.html Accumulator Generator]</ref>
An example is this accumulator class (based on [[Paul Graham (computer programmer)|Paul Graham's]] study on programming language syntax and clarity):<ref>[http://www.paulgraham.com/accgen.html Accumulator Generator]</ref>


<source lang=Python>
<syntaxhighlight lang="python">
class Accumulator(object):
class Accumulator:
def __init__(self, n):
def __init__(self, n) -> None:
self.n = n
self.n = n


Line 528: Line 670:
self.n += x
self.n += x
return self.n
return self.n
</syntaxhighlight>
</source>


An example of this in use (using the interactive interpreter):
An example of this in use (using the interactive interpreter):


<source lang=Python>
<syntaxhighlight lang="pycon">
>>> a = Accumulator(4)
>>> a = Accumulator(4)
>>> a(5)
>>> a(5)
9
9
>>> a(2)
>>> a(2)
11
11
>>> b = Accumulator(42)
>>> b = Accumulator(42)
>>> b(7)
>>> b(7)
49
49
</syntaxhighlight>
</source>


Since functions are objects, they can also be defined locally, given attributes, and returned by other functions
Since functions are objects, they can also be defined locally, given attributes, and returned by other functions, <ref>[https://docs.python.org/3/reference/compound_stmts.html#function-definitions Python reference manual - Function definitions]</ref> as demonstrated in the following example:
,<ref>[https://docs.python.org/3/reference/compound_stmts.html#function-definitions Python reference manual - Function definitions]</ref> as demonstrated in the following two examples:


<source lang=Python>
<syntaxhighlight lang="python3">
def Accumulator(n):
def inc(x):
inc.n += x
return inc.n
inc.n = n
return inc
</source>

Function object creation using a [[Closure (computer science)|closure]] referencing a [[non-local variable]] in Python 3:

<source lang=Python>
def Accumulator(n):
def Accumulator(n):
def inc(x):
def inc(x):
Line 564: Line 694:
return n
return n
return inc
return inc
</syntaxhighlight>
</source>


== In Ruby ==
== In Ruby ==
In [[Ruby (programming language)|Ruby]], several objects can be considered function objects, in particular Method and Proc objects. Ruby also has two kinds of objects that can be thought of as semi-function objects: UnboundMethod and block. UnboundMethods must first be bound to an object (thus becoming a Method) before they can be used as a function object. Blocks can be called like function objects, but to be used in any other capacity as an object (e.g. passed as an argument) they must first be converted to a Proc. More recently, symbols (accessed via the literal unary indicator <code>:</code>) can also be converted to <code>Proc</code>s. Using Ruby's unary <code>&</code> operator&mdash;equivalent to calling <code>to_proc</code> on an object, and [[duck typing|assuming that method exists]]&mdash;the [[Ruby Extensions Project]] [http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Tech/Ruby/ToProc.rdoc created a simple hack.]
In [[Ruby (programming language)|Ruby]], several objects can be considered function objects, in particular Method and Proc objects. Ruby also has two kinds of objects that can be thought of as semi-function objects: UnboundMethod and block. UnboundMethods must first be bound to an object (thus becoming a Method) before they can be used as a function object. Blocks can be called like function objects, but to be used in any other capacity as an object (e.g. passed as an argument) they must first be converted to a Proc. More recently, symbols (accessed via the literal unary indicator <code>:</code>) can also be converted to <code>Proc</code>s. Using Ruby's unary <code>&</code> operator&mdash;equivalent to calling <code>to_proc</code> on an object, and [[duck typing|assuming that method exists]]&mdash;the [[Ruby Extensions Project]] [https://web.archive.org/web/20060425104650/http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Tech/Ruby/ToProc.rdoc created a simple hack.]


<source lang=Ruby>
<syntaxhighlight lang="ruby">
class Symbol
class Symbol
def to_proc
def to_proc
Line 575: Line 705:
end
end
end
end
</syntaxhighlight>
</source>


Now, method <code>foo</code> can be a function object, i.e. a <code>Proc</em>, via <code>&:foo</code> and used via <code>takes_a_functor(&:foo)</code>. <code>Symbol.to_proc</code> was officially added to Ruby on June 11, 2006 during RubyKaiga2006. [http://redhanded.hobix.com/cult/symbolTo_procExonerated.html]
Now, method <code>foo</code> can be a function object, i.e. a <code>Proc</code>, via <code>&:foo</code> and used via <code>takes_a_functor(&:foo)</code>. <code>Symbol.to_proc</code> was officially added to Ruby on June 11, 2006 during RubyKaigi2006. [https://web.archive.org/web/20060820025032/http://redhanded.hobix.com/cult/symbolTo_procExonerated.html]


Because of the variety of forms, the term Functor is not generally used in Ruby to mean a Function object.
Because of the variety of forms, the term Functor is not generally used in Ruby to mean a Function object.
Just a type of dispatch [[delegation (programming)|delegation]] introduced by the [http://facets.rubyforge.org Ruby Facets] project is named as Functor. The most basic definition of which is:
Just a type of dispatch [[delegation (programming)|delegation]] introduced by the [https://web.archive.org/web/20070107205748/http://facets.rubyforge.org/ Ruby Facets] project is named as Functor. The most basic definition of which is:


<source lang=Ruby>
<syntaxhighlight lang="ruby">
class Functor
class Functor
def initialize(&func)
def initialize(&func)
Line 591: Line 721:
end
end
end
end
</syntaxhighlight>
</source>


This usage is more akin to that used by functional programming languages, like [[ML (programming language)|ML]], and the original mathematical terminology.
This usage is more akin to that used by functional programming languages, like [[ML (programming language)|ML]], and the original mathematical terminology.
Line 599: Line 729:
In a more theoretical context a ''function object'' may be considered to be any instance of the class of functions, especially in languages such as [[Common Lisp]] in which functions are [[first-class object]]s.
In a more theoretical context a ''function object'' may be considered to be any instance of the class of functions, especially in languages such as [[Common Lisp]] in which functions are [[first-class object]]s.


The [[functional programming]] languages [[ML (programming language)|ML]] and [[Haskell (programming language)|Haskell]] use the term ''functor'' to represent a [[function (mathematics)|mapping]] from modules to modules, or from types to types and is a technique for reusing code. Functors used in this manner are analogous to the original mathematical meaning of [[functor]] in [[category theory]], or to the use of generic programming in C++, Java or [[Ada (programming language)|Ada]].
The [[ML (programming language)|ML]] family of [[functional programming]] languages uses the term ''functor'' to represent a [[function (mathematics)|mapping]] from modules to modules, or from types to types and is a technique for reusing code. Functors used in this manner are analogous to the original mathematical meaning of [[functor]] in [[category theory]], or to the use of generic programming in C++, Java or [[Ada (programming language)|Ada]].

In [[Haskell (programming language)|Haskell]], the term ''[[Functor (functional programming)|functor]]'' is also used for a concept related to the meaning of ''functor'' in category theory.


In [[Prolog]] and related languages, functor is a synonym for [[function symbol]].
In [[Prolog]] and related languages, ''functor'' is a synonym for [[function symbol]].


== See also ==
== See also ==
Line 618: Line 750:


== Further reading ==
== Further reading ==
* David Vandevoorde & Nicolai M Josuttis (2006). ''C++ Templates: The Complete Guide'', ISBN 0-201-73484-2: Specifically, chapter 22 is devoted to function objects.
* David Vandevoorde & Nicolai M Josuttis (2006). ''C++ Templates: The Complete Guide'', {{ISBN|0-201-73484-2}}: Specifically, chapter 22 is devoted to function objects.


== External links ==
== External links ==
* [http://c2.com/cgi/wiki?FunctorObject Description from the Portland Pattern Repository]
* [http://c2.com/cgi/wiki?FunctorObject Description from the Portland Pattern Repository]
* [http://www.two-sdg.demon.co.uk/curbralan/papers/AsynchronousC++.pdf C++ Advanced Design Issues - Asynchronous C++] by [[Kevlin Henney]]
* [http://www.two-sdg.demon.co.uk/curbralan/papers/AsynchronousC++.pdf C++ Advanced Design Issues - Asynchronous C++] {{Webarchive|url=https://web.archive.org/web/20200922012516/http://www.two-sdg.demon.co.uk/curbralan/papers/AsynchronousC++.pdf |date=2020-09-22 }} by [[Kevlin Henney]]
* [http://www.newty.de/fpt/index.html The Function Pointer Tutorials] by Lars Haendel (2000/2001)
* [http://www.newty.de/fpt/index.html The Function Pointer Tutorials] by Lars Haendel (2000/2001)
* Article "[http://cuj.com/documents/s=8464/cujcexp0308sutter/ Generalized Function Pointers]" by [[Herb Sutter]]
* Article "[https://web.archive.org/web/20041009232434/http://www.cuj.com/documents/s%3D8464/cujcexp0308sutter/ Generalized Function Pointers]" by [[Herb Sutter]]
* [http://jga.sourceforge.net/ Generic Algorithms for Java]
* [http://jga.sourceforge.net/ Generic Algorithms for Java]
* [http://www.amcgowan.ca/blog/computer-science/php-functors-function-objects-in-php/ PHP Functors - Function Objects in PHP]
* [https://web.archive.org/web/20100330073950/http://www.amcgowan.ca/blog/computer-science/php-functors-function-objects-in-php/ PHP Functors - Function Objects in PHP]
* [http://parashift.com/c%2B%2B-faq-lite/pointers-to-members.html#faq-33.10 What the heck is a functionoid, and why would I use one?] (C++ FAQ)
* [https://web.archive.org/web/20041013202445/http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.10 What the heck is a functionoid, and why would I use one?] (C++ FAQ)


{{DEFAULTSORT:Function Object}}
{{DEFAULTSORT:Function Object}}
Line 634: Line 766:
[[Category:Articles with example C code]]
[[Category:Articles with example C code]]
[[Category:Articles with example C++ code]]
[[Category:Articles with example C++ code]]
[[Category:Articles with example D code]]
[[Category:Articles with example Eiffel code]]
[[Category:Articles with example Java code]]
[[Category:Articles with example Java code]]
[[Category:Articles with example JavaScript code]]
[[Category:Articles with example Julia code]]
[[Category:Articles with example Lisp (programming language) code]]
[[Category:Articles with example Objective-C code]]
[[Category:Articles with example Perl code]]
[[Category:Articles with example Perl code]]
[[Category:Articles with example Python code]]
[[Category:Articles with example PHP code]]
[[Category:Articles with example Python (programming language) code]]
[[Category:Articles with example Ruby code]]
[[Category:Articles with example Ruby code]]

Latest revision as of 17:22, 14 May 2024

In computer programming, a function object[a] is a construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax (a function parameter that can also be a function). In some languages, particularly C++, function objects are often called functors (not related to the functional programming concept).

Description

[edit]

A typical use of a function object is in writing callback functions. A callback in procedural languages, such as C, may be performed by using function pointers.[2] However it can be difficult or awkward to pass a state into or out of the callback function. This restriction also inhibits more dynamic behavior of the function. A function object solves those problems since the function is really a façade for a full object, carrying its own state.

Many modern (and some older) languages, e.g. C++, Eiffel, Groovy, Lisp, Smalltalk, Perl, PHP, Python, Ruby, Scala, and many others, support first-class function objects and may even make significant use of them.[3] Functional programming languages additionally support closures, i.e. first-class functions that can 'close over' variables in their surrounding environment at creation time. During compilation, a transformation known as lambda lifting converts the closures into function objects.

In C and C++

[edit]

Consider the example of a sorting routine that uses a callback function to define an ordering relation between a pair of items. The following C/C++ program uses function pointers:

#include <stdlib.h>

/* qsort() callback function, returns < 0 if a < b, > 0 if a > b, 0 if a == b */
int compareInts(const void* a, const void* b)
{
    return ( *(int *)a - *(int *)b );
}
...
// prototype of qsort is
// void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *));
...
int main(void)
{
    int items[] = { 4, 3, 1, 2 };
    qsort(items, sizeof(items) / sizeof(items[0]), sizeof(items[0]), compareInts);
    return 0;
}

In C++, a function object may be used instead of an ordinary function by defining a class that overloads the function call operator by defining an operator() member function. In C++, this may appear as follows:

// comparator predicate: returns true if a < b, false otherwise
struct IntComparator
{
  bool operator()(const int &a, const int &b) const
  {
    return a < b;
  }
};

int main()
{
    std::vector<int> items { 4, 3, 1, 2 };
    std::sort(items.begin(), items.end(), IntComparator());
    return 0;
}

Notice that the syntax for providing the callback to the std::sort() function is identical, but an object is passed instead of a function pointer. When invoked, the callback function is executed just as any other member function, and therefore has full access to the other members (data or functions) of the object. Of course, this is just a trivial example. To understand what power a functor provides more than a regular function, consider the common use case of sorting objects by a particular field. In the following example, a functor is used to sort a simple employee database by each employee's ID number.

struct CompareBy
{
    const std::string SORT_FIELD;
    CompareBy(const std::string& sort_field="name")
      : SORT_FIELD(sort_field)
    {
        /* validate sort_field */
    }
    
    bool operator()(const Employee& a, const Employee& b) const
    {
        if (SORT_FIELD == "name")
            return a.name < b.name;
        else if (SORT_FIELD == "age")
            return a.age < b.age;
        else if (SORT_FIELD == "idnum")
            return a.idnum < b.idnum;
        else
            /* throw exception or something */
    }
};

int main()
{
    std::vector<Employee> emps;
    
    /* code to populate database */
    
    // Sort the database by employee ID number
    std::sort(emps.begin(), emps.end(), CompareBy("idnum"));
    
    return 0;
}

In C++11, the lambda expression provides a more succinct way to do the same thing.

int main()
{
    std::vector<Employee> emps;
    /* code to populate database */
    const std::string sort_field = "idnum";
    std::sort(emps.begin(), emps.end(), [&sort_field](const Employee& a, const Employee& b) const { /* code to select and compare field */ });
    return 0;
}


It is possible to use function objects in situations other than as callback functions. In this case, the shortened term functor is normally not used about the function object. Continuing the example,

IntComparator cpm;
bool result = cpm(a, b);

In addition to class type functors, other kinds of function objects are also possible in C++. They can take advantage of C++'s member-pointer or template facilities. The expressiveness of templates allows some functional programming techniques to be used, such as defining function objects in terms of other function objects (like function composition). Much of the C++ Standard Template Library (STL) makes heavy use of template-based function objects.

Another way to create a function object in C++ is to define a non-explicit conversion function to a function pointer type, a function reference type, or a reference to function pointer type. Assuming the conversion does not discard cv-qualifiers, this allows an object of that type to be used as a function with the same signature as the type it is converted to. Modifying an earlier example to use this we obtain the following class, whose instances can be called like function pointers:[4]

// comparator predicate: returns true if a < b, false otherwise
struct IntComparator
{
  static bool compare(const int &a, const int &b)
  {
    return a < b;
  }
  using T = decltype(compare);
  operator T*() const { return compare; }
};

int main()
{
    std::vector<int> items { 4, 3, 1, 2 };
    std::sort(items.begin(), items.end(), IntComparator());
    return 0;
}

Maintaining state

[edit]

Another advantage of function objects is their ability to maintain a state that affects operator() between calls. For example, the following code defines a generator counting from 10 upwards and is invoked 11 times.

#include <algorithm>
#include <iostream>
#include <iterator>

class CountFrom {
 public:
  CountFrom(int count) : count_(count) {}
  
  int operator()() { return count_++; }

 private:
  int count_;
};

int main() {
  const int state(10);
  std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 11,
                  CountFrom(state));
}

In C++14 or later, the example above could be rewritten as:

#include <algorithm>
#include <iostream>
#include <iterator>

int main() {
  std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 11,
                  [count=10]() mutable { return count++; });
}

In C#

[edit]

In C#, function objects are declared via delegates. A delegate can be declared using a named method or a lambda expression. Here is an example using a named method.

using System;
using System.Collections.Generic;

public class ComparisonClass1
{
    public static int CompareFunction(int x, int y)
    {
        return x - y;
    }

    public static void Main()
    {
        var items = new List<int> { 4, 3, 1, 2 };
        Comparison<int> del = CompareFunction;
        items.Sort(del);
    }
}

Here is an example using a lambda expression.

using System;
using System.Collections.Generic;

public class ComparisonClass2
{
    public static void Main()
    {
        var items = new List<int> { 4, 3, 1, 2 };
        items.Sort((x, y) => x - y);
    }
}

In D

[edit]

D provides several ways to declare function objects: Lisp/Python-style via closures or C#-style via delegates, respectively:

bool find(T)(T[] haystack, bool delegate(T) needle_test) {
  foreach (straw; haystack) {
    if (needle_test(straw))
      return true;
  }
  return false;
}

void main() {
    int[] haystack = [345, 15, 457, 9, 56, 123, 456];
    int   needle = 123;
    bool needleTest(int n) {
      return n == needle;
    }
    assert(find(haystack, &needleTest));
}

The difference between a delegate and a closure in D is automatically and conservatively determined by the compiler. D also supports function literals, that allow a lambda-style definition:

void main() {
    int[] haystack = [345, 15, 457, 9, 56, 123, 456];
    int   needle = 123;
    assert(find(haystack, (int n) { return n == needle; }));
}

To allow the compiler to inline the code (see above), function objects can also be specified C++-style via operator overloading:

bool find(T, F)(T[] haystack, F needle_test) {
  foreach (straw; haystack) {
    if (needle_test(straw))
      return true;
  }
  return false;
}

void main() {
    int[] haystack = [345, 15, 457, 9, 56, 123, 456];
    int   needle = 123;
    class NeedleTest {
      int needle;
      this(int n) { needle = n; }
      bool opCall(int n) {
        return n == needle;
      }
    }
    assert(find(haystack, new NeedleTest(needle)));
}

In Eiffel

[edit]

In the Eiffel software development method and language, operations and objects are seen always as separate concepts. However, the agent mechanism facilitates the modeling of operations as runtime objects. Agents satisfy the range of application attributed to function objects, such as being passed as arguments in procedural calls or specified as callback routines. The design of the agent mechanism in Eiffel attempts to reflect the object-oriented nature of the method and language. An agent is an object that generally is a direct instance of one of the two library classes, which model the two types of routines in Eiffel: PROCEDURE and FUNCTION. These two classes descend from the more abstract ROUTINE.

Within software text, the language keyword agent allows agents to be constructed in a compact form. In the following example, the goal is to add the action of stepping the gauge forward to the list of actions to be executed in the event that a button is clicked.

my_button.select_actions.extend (agent my_gauge.step_forward)

The routine extend referenced in the example above is a feature of a class in a graphical user interface (GUI) library to provide event-driven programming capabilities.

In other library classes, agents are seen to be used for different purposes. In a library supporting data structures, for example, a class modeling linear structures effects universal quantification with a function for_all of type BOOLEAN that accepts an agent, an instance of FUNCTION, as an argument. So, in the following example, my_action is executed only if all members of my_list contain the character '!':

    my_list: LINKED_LIST [STRING]
        ...
            if my_list.for_all (agent {STRING}.has ('!')) then
                my_action
            end
        ...

When agents are created, the arguments to the routines they model and even the target object to which they are applied can be either closed or left open. Closed arguments and targets are given values at agent creation time. The assignment of values for open arguments and targets is deferred until some point after the agent is created. The routine for_all expects as an argument an agent representing a function with one open argument or target that conforms to actual generic parameter for the structure (STRING in this example.)

When the target of an agent is left open, the class name of the expected target, enclosed in braces, is substituted for an object reference as shown in the text agent {STRING}.has ('!') in the example above. When an argument is left open, the question mark character ('?') is coded as a placeholder for the open argument.

The ability to close or leave open targets and arguments is intended to improve the flexibility of the agent mechanism. Consider a class that contains the following procedure to print a string on standard output after a new line:

    print_on_new_line (s: STRING)
            -- Print `s' preceded by a new line
        do
            print ("%N" + s)
        end

The following snippet, assumed to be in the same class, uses print_on_new_line to demonstrate the mixing of open arguments and open targets in agents used as arguments to the same routine.

    my_list: LINKED_LIST [STRING]
        ...
            my_list.do_all (agent print_on_new_line (?))
            my_list.do_all (agent {STRING}.to_lower)
            my_list.do_all (agent print_on_new_line (?))
        ...

This example uses the procedure do_all for linear structures, which executes the routine modeled by an agent for each item in the structure.

The sequence of three instructions prints the strings in my_list, converts the strings to lowercase, and then prints them again.

Procedure do_all iterates across the structure executing the routine substituting the current item for either the open argument (in the case of the agents based on print_on_new_line), or the open target (in the case of the agent based on to_lower).

Open and closed arguments and targets also allow the use of routines that call for more arguments than are required by closing all but the necessary number of arguments:

my_list.do_all (agent my_multi_arg_procedure (closed_arg_1, ?, closed_arg_2, closed_arg_3)

The Eiffel agent mechanism is detailed in the Eiffel ISO/ECMA standard document.

In Java

[edit]

Java has no first-class functions, so function objects are usually expressed by an interface with a single method (most commonly the Callable interface), typically with the implementation being an anonymous inner class, or, starting in Java 8, a lambda.

For an example from Java's standard library, java.util.Collections.sort() takes a List and a functor whose role is to compare objects in the List. Without first-class functions, the function is part of the Comparator interface. This could be used as follows.

List<String> list = Arrays.asList("10", "1", "20", "11", "21", "12");
		
Comparator<String> numStringComparator = new Comparator<String>() {
    public int compare(String str1, String str2) {
        return Integer.valueOf(str1).compareTo(Integer.valueOf(str2));
    }
};

Collections.sort(list, numStringComparator);

In Java 8+, this can be written as:

List<String> list = Arrays.asList("10", "1", "20", "11", "21", "12");
		
Comparator<String> numStringComparator = (str1, str2) -> Integer.valueOf(str1).compareTo(Integer.valueOf(str2));

Collections.sort(list, numStringComparator);

In JavaScript

[edit]

In JavaScript, functions are first class objects. JavaScript also supports closures.

Compare the following with the subsequent Python example.

function Accumulator(start) {
  var current = start;
  return function (x) {
    return current += x;
  };
}

An example of this in use:

var a = Accumulator(4);
var x = a(5);   // x has value 9
x = a(2);       // x has value 11

var b = Accumulator(42);
x = b(7);       // x has value 49 (current = 49 in closure b)
x = a(7);       // x has value 18 (current = 18 in closure a)

In Julia

[edit]

In Julia, methods are associated with types, so it is possible to make any arbitrary Julia object "callable" by adding methods to its type. (Such "callable" objects are sometimes called "functors.")

An example is this accumulator mutable struct (based on Paul Graham's study on programming language syntax and clarity):[5]

julia> mutable struct Accumulator
           n::Int
       end

julia> function (acc::Accumulator)(n2)
           acc.n += n2
       end

julia> a = Accumulator(4)
Accumulator(4)

julia> a(5)
9

julia> a(2)
11

julia> b = Accumulator(42)
Accumulator(42)

julia> b(7)
49

Such an accumulator can also be implemented using closure:

julia> function Accumulator(n0)
           n = n0
           function(n2)
               n += n2
           end
       end
Accumulator (generic function with 1 method)

julia> a = Accumulator(4)
(::#1) (generic function with 1 method)

julia> a(5)
9

julia> a(2)
11

julia> b = Accumulator(42)
(::#1) (generic function with 1 method)

julia> b(7)
49

In Lisp and Scheme

[edit]

In Lisp family languages such as Common Lisp, Scheme, and others, functions are objects, just like strings, vectors, lists, and numbers. A closure-constructing operator creates a function object from a part of the program: the part of code given as an argument to the operator is part of the function, and so is the lexical environment: the bindings of the lexically visible variables are captured and stored in the function object, which is more commonly called a closure. The captured bindings play the role of member variables, and the code part of the closure plays the role of the anonymous member function, just like operator () in C++.

The closure constructor has the syntax (lambda (parameters ...) code ...). The (parameters ...) part allows an interface to be declared, so that the function takes the declared parameters. The code ... part consists of expressions that are evaluated when the functor is called.

Many uses of functors in languages like C++ are simply emulations of the missing closure constructor. Since the programmer cannot directly construct a closure, they must define a class that has all of the necessary state variables, and also a member function. Then, construct an instance of that class instead, ensuring that all the member variables are initialized through its constructor. The values are derived precisely from those local variables that ought to be captured directly by a closure.

A function-object using the class system in Common Lisp, no use of closures:

(defclass counter ()
  ((value :initarg :value :accessor value-of)))

(defmethod functor-call ((c counter))
  (incf (value-of c)))

(defun make-counter (initial-value)
  (make-instance 'counter :value initial-value))

;;; use the counter:
(defvar *c* (make-counter 10))
(functor-call *c*) --> 11
(functor-call *c*) --> 12

Since there is no standard way to make funcallable objects in Common Lisp, we fake it by defining a generic function called FUNCTOR-CALL. This can be specialized for any class whatsoever. The standard FUNCALL function is not generic; it only takes function objects.

It is this FUNCTOR-CALL generic function that gives us function objects, which are a computer programming construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax. We have almost the same syntax: FUNCTOR-CALL instead of FUNCALL. Some Lisps provide funcallable objects as a simple extension. Making objects callable using the same syntax as functions is a fairly trivial business. Making a function call operator work with different kinds of function things, whether they be class objects or closures is no more complicated than making a + operator that works with different kinds of numbers, such as integers, reals or complex numbers.

Now, a counter implemented using a closure. This is much more brief and direct. The INITIAL-VALUE argument of the MAKE-COUNTER factory function is captured and used directly. It does not have to be copied into some auxiliary class object through a constructor. It is the counter. An auxiliary object is created, but that happens behind the scenes.

(defun make-counter (value)
  (lambda () (incf value)))

;;; use the counter
(defvar *c* (make-counter 10))
(funcall *c*) ; --> 11
(funcall *c*) ; --> 12

Scheme makes closures even simpler, and Scheme code tends to use such higher-order programming somewhat more idiomatically.

(define (make-counter value)
  (lambda () (set! value (+ value 1)) value))
;;; use the counter
(define c (make-counter 10))
(c) ; --> 11
(c) ; --> 12

More than one closure can be created in the same lexical environment. A vector of closures, each implementing a specific kind of operation, can quite faithfully emulate an object that has a set of virtual operations. That type of single dispatch object-oriented programming can be done fully with closures.

Thus there exists a kind of tunnel being dug from both sides of the proverbial mountain. Programmers in OOP languages discover function objects by restricting objects to have one main function to do that object's functional purpose, and even eliminate its name so that it looks like the object is being called! While programmers who use closures are not surprised that an object is called like a function, they discover that multiple closures sharing the same environment can provide a complete set of abstract operations like a virtual table for single dispatch type OOP.

In Objective-C

[edit]

In Objective-C, a function object can be created from the NSInvocation class. Construction of a function object requires a method signature, the target object, and the target selector. Here is an example for creating an invocation to the current object's myMethod:

// Construct a function object
SEL sel = @selector(myMethod);
NSInvocation* inv = [NSInvocation invocationWithMethodSignature:
                     [self methodSignatureForSelector:sel]];
[inv setTarget:self];
[inv setSelector:sel];

// Do the actual invocation
[inv invoke];

An advantage of NSInvocation is that the target object can be modified after creation. A single NSInvocation can be created and then called for each of any number of targets, for instance from an observable object. An NSInvocation can be created from only a protocol, but it is not straightforward. See here.

In Perl

[edit]

In Perl, a function object can be created either from a class's constructor returning a function closed over the object's instance data, blessed into the class:

package Acc1;
sub new {
    my $class = shift;
    my $arg = shift;
    my $obj = sub {
        my $num = shift;
        $arg += $num;
    };
    bless $obj, $class;
}
1;

or by overloading the &{} operator so that the object can be used as a function:

package Acc2;
use overload
    '&{}' =>
        sub {
            my $self = shift;
            sub {
                my $num = shift;
                $self->{arg} += $num;
            }
        };

sub new {
    my $class = shift;
    my $arg = shift;
    my $obj = { arg => $arg };
    bless $obj, $class;
}
1;

In both cases the function object can be used either using the dereferencing arrow syntax $ref->(@arguments):

use Acc1;
my $a = Acc1->new(42);
print $a->(10), "\n";    # prints 52
print $a->(8), "\n";     # prints 60

or using the coderef dereferencing syntax &$ref(@arguments):

use Acc2;
my $a = Acc2->new(12);
print &$a(10), "\n";     # prints 22
print &$a(8), "\n";      # prints 30

In PHP

[edit]

PHP 5.3+ has first-class functions that can be used e.g. as parameter to the usort() function:

$a = array(3, 1, 4);
usort($a, function ($x, $y) { return $x - $y; });

PHP 5.3+, supports also lambda functions and closures.

function Accumulator($start)
{
    $current = $start;
    return function($x) use(&$current)
    {
        return $current += $x;
    };
}

An example of this in use:

$a = Accumulator(4);
$x = $a(5);
echo "x = $x<br/>";	// x = 9
$x = $a(2);
echo "x = $x<br/>";	// x = 11

It is also possible in PHP 5.3+ to make objects invokable by adding a magic __invoke() method to their class:[6]

class Minus
{
    public function __invoke($x, $y)
    {
        return $x - $y;
    }
}

$a = array(3, 1, 4);
usort($a, new Minus());

In PowerShell

[edit]

In the Windows PowerShell language, a script block is a collection of statements or expressions that can be used as a single unit. A script block can accept arguments and return values. A script block is an instance of a Microsoft .NET Framework type System.Management.Automation.ScriptBlock.

Function Get-Accumulator($x) {
    {
        param($y)
        return $x += $y
    }.GetNewClosure()
}
PS C:\> $a = Get-Accumulator 4
PS C:\> & $a 5
9
PS C:\> & $a 2
11
PS C:\> $b = Get-Accumulator 32
PS C:\> & $b 10
42

In Python

[edit]

In Python, functions are first-class objects, just like strings, numbers, lists etc. This feature eliminates the need to write a function object in many cases. Any object with a __call__() method can be called using function-call syntax.

An example is this accumulator class (based on Paul Graham's study on programming language syntax and clarity):[7]

class Accumulator:
    def __init__(self, n) -> None:
        self.n = n

    def __call__(self, x):
        self.n += x
        return self.n

An example of this in use (using the interactive interpreter):

>>> a = Accumulator(4)
>>> a(5)
9
>>> a(2)
11
>>> b = Accumulator(42)
>>> b(7)
49

Since functions are objects, they can also be defined locally, given attributes, and returned by other functions, [8] as demonstrated in the following example:

def Accumulator(n):
    def inc(x):
        nonlocal n
        n += x
        return n
    return inc

In Ruby

[edit]

In Ruby, several objects can be considered function objects, in particular Method and Proc objects. Ruby also has two kinds of objects that can be thought of as semi-function objects: UnboundMethod and block. UnboundMethods must first be bound to an object (thus becoming a Method) before they can be used as a function object. Blocks can be called like function objects, but to be used in any other capacity as an object (e.g. passed as an argument) they must first be converted to a Proc. More recently, symbols (accessed via the literal unary indicator :) can also be converted to Procs. Using Ruby's unary & operator—equivalent to calling to_proc on an object, and assuming that method exists—the Ruby Extensions Project created a simple hack.

class Symbol
  def to_proc
    proc { |obj, *args| obj.send(self, *args) }
  end
end

Now, method foo can be a function object, i.e. a Proc, via &:foo and used via takes_a_functor(&:foo). Symbol.to_proc was officially added to Ruby on June 11, 2006 during RubyKaigi2006. [1]

Because of the variety of forms, the term Functor is not generally used in Ruby to mean a Function object. Just a type of dispatch delegation introduced by the Ruby Facets project is named as Functor. The most basic definition of which is:

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

This usage is more akin to that used by functional programming languages, like ML, and the original mathematical terminology.

Other meanings

[edit]

In a more theoretical context a function object may be considered to be any instance of the class of functions, especially in languages such as Common Lisp in which functions are first-class objects.

The ML family of functional programming languages uses the term functor to represent a mapping from modules to modules, or from types to types and is a technique for reusing code. Functors used in this manner are analogous to the original mathematical meaning of functor in category theory, or to the use of generic programming in C++, Java or Ada.

In Haskell, the term functor is also used for a concept related to the meaning of functor in category theory.

In Prolog and related languages, functor is a synonym for function symbol.

See also

[edit]

Notes

[edit]
  1. ^ In C++, a functionoid is an object that has one major method, and a functor is a special case of a functionoid.[1] They are similar to a function object, but not the same.

References

[edit]
  1. ^ What's the difference between a functionoid and a functor?
  2. ^ Silan Liu. "C++ Tutorial Part I - Basic: 5.10 Function pointers are mainly used to achieve call back technique, which will be discussed right after". TRIPOD: Programming Tutorials Copyright © Silan Liu 2002. Retrieved 2012-09-07. Function pointers are mainly used to achieve call back technique, which will be discussed right after.
  3. ^ Paweł Turlejski (2009-10-02). "C++ Tutorial Part I - Basic: 5.10 Function pointers are mainly used to achieve call back technique, which will be discussed right after". Just a Few Lines. Retrieved 2012-09-07. PHP 5.3, along with many other features, introduced closures. So now we can finally do all the cool stuff that Ruby / Groovy / Scala / any_modern_language guys can do, right? Well, we can, but we probably won't… Here's why.
  4. ^ "Overload resolution§Call to a class object". cppreference.com.
  5. ^ Accumulator Generator
  6. ^ PHP Documentation on Magic Methods
  7. ^ Accumulator Generator
  8. ^ Python reference manual - Function definitions

Further reading

[edit]
  • David Vandevoorde & Nicolai M Josuttis (2006). C++ Templates: The Complete Guide, ISBN 0-201-73484-2: Specifically, chapter 22 is devoted to function objects.
[edit]