Content deleted Content added
added Category:Articles with example Julia code using HotCat |
m →External links: HTTP to HTTPS for SourceForge |
||
(40 intermediate revisions by 25 users not shown) | |||
Line 1:
{{Short description|Programming construct}}
{{About|the computer programming concept of function objects|functors in mathematics|Functor|the related concept in functional programming|Functor (functional programming)}}
{{More citations needed|date=February 2009}}
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 ==
Line 8 ⟶ 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.
| author = Silan Liu
| 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.
|
}}</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 ⟶ 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.
| author = Paweł Turlejski
| date = 2009-10-02
| 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.
|
}}</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++ ==
Consider the example of a sorting routine that uses a callback function to define an ordering relation between a pair of items.
<!-- 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. -->
<
#include <stdlib.h>
Line 35 ⟶ 33:
int compareInts(const void* a, const void* b)
{
return ( *(int *)a
}
...
Line 47 ⟶ 45:
return 0;
}
</syntaxhighlight>
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:
<
// comparator predicate: returns true if a < b, false otherwise
struct IntComparator
Line 67 ⟶ 65:
return 0;
}
</syntaxhighlight>
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.
<
struct CompareBy
{
Line 82 ⟶ 79:
}
bool operator()(const Employee& a, const Employee& b) const
{
if (SORT_FIELD == "name")
Line 106 ⟶ 103:
return 0;
}
</syntaxhighlight>
In [[C++11]], the lambda expression provides a more succinct way to do the same thing.
<
int main()
{
Line 118 ⟶ 113:
/* 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>
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/w/cpp/language/overload_resolution#Call_to_a_class_object|title=Overload resolution§Call to a class object|website=cppreference.com}}</ref>
<syntaxhighlight lang="cpp">
// 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;
}
</syntaxhighlight>
=== Maintaining state ===
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.
<
#include <algorithm>
#include <iostream>
Line 144 ⟶ 161:
class CountFrom {
public:
CountFrom(int
int operator()() { return count_++; }
private:
int
};
int main() {
const int state(10);
std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 11,
CountFrom(state));
}
</syntaxhighlight>
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 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.
<
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);
}
}
</syntaxhighlight>
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);
}
}
</syntaxhighlight>
== 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:
<
bool find(T)(T[] haystack, bool delegate(T) needle_test) {
foreach (straw; haystack) {
Line 213 ⟶ 246:
return n == needle;
}
assert(find(haystack, &needleTest));
}
</syntaxhighlight>
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:
<
void main() {
int[] haystack = [345, 15, 457, 9, 56, 123, 456];
int needle = 123;
assert(find(haystack, (int n) { return n == needle; }));
}
</syntaxhighlight>
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) {
Line 252 ⟶ 281:
}
}
assert(find(haystack, new NeedleTest(needle)));
}
</syntaxhighlight>
== In Eiffel ==
Line 264 ⟶ 291:
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.
<
</syntaxhighlight>
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>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 '!':
<
my_list: LINKED_LIST [STRING]
...
Line 279 ⟶ 306:
end
...
</syntaxhighlight>
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.)
Line 287 ⟶ 314:
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
Line 293 ⟶ 320:
print ("%N" + s)
end
</syntaxhighlight>
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.
<
my_list: LINKED_LIST [STRING]
...
Line 304 ⟶ 331:
my_list.do_all (agent print_on_new_line (?))
...
</syntaxhighlight>
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.
Line 314 ⟶ 341:
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:
<
</syntaxhighlight>
The Eiffel agent mechanism is detailed in the [http://www.ecma-international.org/publications/standards/Ecma-367.htm Eiffel ISO/ECMA standard document].
Line 325 ⟶ 352:
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.
<
List<String> list = Arrays.asList("10", "1", "20", "11", "21", "12");
Comparator<String> numStringComparator = new Comparator<String>() {
public int compare(String str1, String str2) {
Line 335 ⟶ 362:
Collections.sort(list, numStringComparator);
</syntaxhighlight>
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);
</syntaxhighlight>
== In JavaScript ==
Line 351 ⟶ 378:
Compare the following with the subsequent Python example.
<
function Accumulator(start) {
var current = start;
Line 358 ⟶ 385:
};
}
</syntaxhighlight>
An example of this in use:
<
var a = Accumulator(4);
var x = a(5); // x has value 9
Line 370 ⟶ 397:
x = b(7); // x has value 49 (current = 49 in closure b)
x = a(7); // x has value 18 (current = 18 in closure a)
</syntaxhighlight>
== In Julia ==
In [[
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>
<
julia> mutable struct Accumulator
n::Int
Line 400 ⟶ 427:
julia> b(7)
49
</syntaxhighlight>
Such an accumulator can also be implemented using closure:
<
julia> function Accumulator(n0)
n = n0
Line 427 ⟶ 454:
julia> b(7)
49
</syntaxhighlight>
== In Lisp and Scheme ==
Line 436 ⟶ 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.
A function-object using the class system in Common Lisp, no use of closures:
<
(defclass counter ()
((value :initarg :value :accessor value-of)))
Line 452 ⟶ 479:
(functor-call *c*) --> 11
(functor-call *c*) --> 12
</syntaxhighlight>
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.
Line 460 ⟶ 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''.
<
(defun make-counter (value)
(lambda () (incf value)))
Line 468 ⟶ 495:
(funcall *c*) ; --> 11
(funcall *c*) ; --> 12
</syntaxhighlight>
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))
Line 479 ⟶ 506:
(c) ; --> 11
(c) ; --> 12
</syntaxhighlight>
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 489 ⟶ 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>:
<
// Construct a function object
SEL sel = @selector(myMethod);
Line 499 ⟶ 526:
// Do the actual invocation
[inv invoke];
</syntaxhighlight>
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 {{usurped|1=[https://web.archive.org/web/20110227215311/http://www.a-coding.com/2010/10/making-nsinvocations.html here]}}.
== In Perl ==
Line 507 ⟶ 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:
<
package Acc1;
sub new {
Line 519 ⟶ 546:
}
1;
</syntaxhighlight>
or by overloading the <code>&{}</code> operator so that the object can be used as a function:
<
package Acc2;
use overload
Line 542 ⟶ 569:
}
1;
</syntaxhighlight>
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
</syntaxhighlight>
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
</syntaxhighlight>
== In PHP ==
[[PHP]] 5.3+ has [[first-class function]]s that can be used e.g. as parameter to the {{Code|usort()}} function:
<
$a = array(3, 1, 4);
usort($a, function ($x, $y) { return $x - $y; });
</syntaxhighlight>
[[PHP]] 5.3+, supports also lambda functions and closures.
<
function Accumulator(
{ $current = $start;
return function(
{
return $current += $x; };
}
</syntaxhighlight>
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
</syntaxhighlight>
It is also possible in PHP 5.3+ to make objects invokable by adding a magic {{Code|__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>
<
class Minus
{ public function __invoke($x, $y)
{
return $x - $y;
}
Line 601 ⟶ 632:
$a = array(3, 1, 4);
usort($a, new Minus());
</syntaxhighlight>
== In PowerShell ==
Line 607 ⟶ 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.
<
Function Get-Accumulator($x) {
{
param($y)
return $
}.GetNewClosure()
}
</syntaxhighlight>
<
PS C:\> $a = Get-Accumulator 4
PS C:\> & $a 5
Line 624 ⟶ 655:
PS C:\> & $b 10
42
</syntaxhighlight>
== In Python ==
Line 631 ⟶ 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>
<
class Accumulator
def __init__(self, n) -> None:
self.n = n
Line 639 ⟶ 670:
self.n += x
return self.n
</syntaxhighlight>
An example of this in use (using the interactive interpreter):
<
>>> a = Accumulator(4)
>>> a(5)
Line 652 ⟶ 683:
>>> b(7)
49
</syntaxhighlight>
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:
<
def Accumulator(n):
def inc(x):
Line 664 ⟶ 694:
return n
return inc
</syntaxhighlight>
== 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—equivalent to calling <code>to_proc</code> on an object, and [[duck typing|assuming that method exists]]—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.]
<
class Symbol
def to_proc
Line 675 ⟶ 705:
end
end
</syntaxhighlight>
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.
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:
<
class Functor
def initialize(&func)
Line 691 ⟶ 721:
end
end
</syntaxhighlight>
This usage is more akin to that used by functional programming languages, like [[ML (programming language)|ML]], and the original mathematical terminology.
Line 701 ⟶ 731:
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
In [[Prolog]] and related languages, ''functor'' is a synonym for [[function symbol]].
Line 724 ⟶ 754:
== External links ==
* [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++] {{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)
* Article "[https://web.archive.org/web/20041009232434/http://www.cuj.com/documents/s%3D8464/cujcexp0308sutter/ Generalized Function Pointers]" by [[Herb Sutter]]
* [
* [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]
* [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)
Line 736 ⟶ 766:
[[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 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
[[Category:Articles with example Python (programming language) code]]
[[Category:Articles with example Ruby code]]
|