Content deleted Content added
Fixed typo added content Tags: Reverted Mobile edit Mobile web edit |
|||
(25 intermediate revisions by 23 users not shown) | |||
Line 1:
{{Short description|Programming language feature}}
In [[computer science]], a [[programming language]] is said to have '''first-class functions''' if it treats [[function (programming)|function]]s as [[first-class citizen]]s. This means the language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures.<ref>{{cite book|first1=Harold|last1=Abelson|authorlink1=Harold Abelson|first2=Gerald Jay|last2=Sussman|authorlink2=Gerald Jay Sussman|title=Structure and Interpretation of Computer Programs|at=[https://archive.org/details/structureinterpr00abel/page/ Formulating Abstractions with Higher-Order Procedures]|publisher=MIT Press|year=1984|isbn=0-262-01077-1|url=https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3|access-date=2021-09-27|archive-date=2021-09-21|archive-url=https://web.archive.org/web/20210921155625/https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3|url-status=dead}}</ref> Some programming language theorists require support for [[anonymous function]]s (function literals) as well.<ref name="test">[http://www.worldcat.org/oclc/222529448 Programming language pragmatics], by Michael Lee Scott, section 11.2 "Functional Programming".</ref> In languages with first-class functions, the [[name (computer science)|names]] of functions do not have any special status; they are treated like ordinary [[variable (computer science)|variable]]s with a [[function type]].<ref>{{cite journal |title=The Implementation of Lua 5.0 |author1=Roberto Ierusalimschy |author1-link=Roberto Ierusalimschy |author2=Luiz Henrique de Figueiredo |author3=Waldemar Celes |journal=Journal of Universal Computer Science |doi=10.3217/jucs-011-07-1159 |doi-access=free |volume=11 |issue=7 |date=2005 |pages=1159–1176}}</ref> The term was coined by [[Christopher Strachey]] in the context of "functions as first-class citizens" in the mid-1960s.<ref name=strachey>{{cite journal|last1=Burstall |first1=Rod |last2=Strachey |first2=Christopher |title=Understanding Programming Languages |journal=[[Higher-Order and Symbolic Computation]] |date=2000 |volume=13 |issue=52 |pages=11–49 |doi=10.1023/A:1010052305354 |s2cid=1989590 |url=http://www.cs.cmu.edu/~crary/819-f09/Strachey67.pdf |url-status=bot: unknown |archiveurl=https://web.archive.org/web/20100216060948/http://www.cs.cmu.edu/~crary/819-f09/Strachey67.pdf |archivedate=February 16, 2010 }} (also on 2010-02-16</ref>
There are certain implementation difficulties in passing functions as arguments or returning them as results, especially in the presence of [[non-local variable]]s introduced in [[nested function|nested]] and [[anonymous function]]s. Historically, these were termed the ''[[funarg problem]]s'', the name coming from
== Concepts ==
Line 63:
typedef struct {
int (*f)(int, int, int);
int
int
} closure_t;
void map(closure_t *closure, int x[], size_t n) {
for (int i = 0; i < n; ++i)
x[i] = (
}
Line 80:
int a = 3;
int b = 1;
closure_t closure = {f,
map(&closure, l, 5);
}
Line 91:
=== Assigning functions to variables ===
[[Assignment (computer science)|Assigning]] functions to [[variable (computer science)|variables]] and storing them inside (global)
<syntaxhighlight lang="haskell">
f :: [[Integer] -> [Integer]]
Line 100:
=== Equality of functions ===
As one can test most literals and values for equality, it is natural to ask whether a programming language can support testing functions for equality. On further inspection, this question appears more difficult and one has to distinguish between several types of function equality:<ref>[[Andrew W. Appel]] (1995). [http://www.cs.princeton.edu/~appel/papers/conteq.pdf "Intensional Equality ;=) for Continuations"].</ref>
Line 108 ⟶ 107:
; [[Intensional equality]]: Under intensional equality, two functions ''f'' and ''g'' are considered equal if they have the same "internal structure". This kind of equality could be implemented in [[interpreted language]]s by comparing the [[source code]] of the function bodies (such as in Interpreted Lisp 1.5) or the [[object code]] in [[compiled language]]s. Intensional equality implies extensional equality (assuming the functions are deterministic and have no hidden inputs, such as the [[program counter]] or a mutable [[global variable]].)
; [[Reference equality]]: Given the impracticality of implementing extensional and intensional equality, most languages supporting testing functions for equality use reference equality. All functions or closures are assigned a unique identifier (usually the address of the function body or the closure) and equality is decided based on equality of the identifier. Two separately defined, but otherwise identical function definitions will be considered unequal. Referential equality implies intensional and extensional equality. Referential equality breaks [[referential transparency]] and is therefore not supported in [[
== Type theory ==
Line 135 ⟶ 134:
| [[ALGOL 60]] || {{yes}} || {{no}} || {{yes}} || {{no}} || {{partial|Downwards}} || {{no}} || rowspan=6 | Have [[function type]]s.
|-
| [[ALGOL 68]] || {{yes}} || {{Partial|Yes}}<ref name=compa68pascal>{{cite journal|page=319|title=A comparison of PASCAL and Algol 68|journal=The Computer Journal|volume=21|number=4|year=1977|first=A.S.|last=Tanenbaum|doi=10.1093/comjnl/21.4.316|doi-access=free|url=https://research.vu.nl/files/110789276/11054}}</ref> || {{yes}} || {{yes}} || {{partial|Downwards}}<ref>{{Cite web|url=http://python-history.blogspot.nl/2009/04/origins-of-pythons-functional-features.html?showComment=1243166621952#c702829329923892023|title = The History of Python: Origins of Python's "Functional" Features|date = 21 April 2009}}</ref> || {{no}}
|-
| [[Pascal (programming language)|Pascal]] || {{yes}} || {{no}} || {{yes}} || {{no}} || {{partial|Downwards}} || {{no}}
Line 146 ⟶ 145:
|-
| rowspan=9 | C family
| [[C (programming language)|C]] || {{yes}} || {{yes}} || {{Partial|Yes in GNU C}} || {{
|-
| [[C++]] || {{yes}} || {{yes}} || {{yes|C++11<ref>[https://stackoverflow.com/a/4324829 Nested functions using lambdas/closures]</ref>}} || {{yes|C++11}}<ref name=doc1968>Doc No. [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1968.pdf 1968]: V Samko; J Willcock, J Järvi, D Gregor, A Lumsdaine (February 26, 2006) ''Lambda expressions and closures for C++''</ref> || {{partial|C++11}}<ref name=doc1968/> || {{partial|C++11}} || Has function pointers, [[function object]]s. (Also, see below.)
Line 155 ⟶ 154:
| [[Objective-C]] || {{yes}} || {{yes}} || {{partial|Using anonymous}} || {{yes|2.0 + Blocks<ref>{{cite web |url=https://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html |url-status=dead |archive-url=https://web.archive.org/web/20090831133626/http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html |archive-date=2009-08-31 |title=Mac Dev Center: Blocks Programming Topics: Introduction}}</ref>}} || {{yes|2.0 + Blocks}} || {{no}} || Has function pointers.
|-
| [[Java (programming language)|Java]] || {{yes}} || {{yes}} || {{partial|Using anonymous}} || {{yes|Java 8}} || {{yes|Java 8}} || {{
|-
| [[Go (programming language)|Go]] || {{yes}} || {{yes}} || {{partial|Using anonymous}} || {{yes}} || {{yes}} || {{yes}}<ref>{{cite web |url=https://play.golang.org/p/lZHXrX-yR6 |title=2 examples in Go that you can have partial application }}</ref> ||
Line 165 ⟶ 164:
| [[Rust (programming language)|Rust]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}}<ref>{{cite web |url=https://docs.rs/partial_application |title=partial_application |website=Docs.rs |access-date=2020-11-03}}</ref> ||
|-
| rowspan=
|-
| [[Scheme (programming language)|Scheme]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes|SRFI 26}}<ref>{{Cite web|url=http://srfi.schemers.org/srfi-26/srfi-26.html|title=SRFI 26: Notation for Specializing Parameters without Currying}}</ref> ||
Line 176 ⟶ 175:
|-
| [[Haskell (programming language)|Haskell]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} ||
|-
| [[jq (programming language)|jq]] || {{yes}} || {{no}} || {{yes}} ||{{partial|Expressions only}} || {{partial|Downwards}} || {{no}}
|-
| [[Scala (programming language)|Scala]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} ||
|-
| [[Erlang (programming language)|Erlang]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} ||
|-
| [[Elixir (programming language)|Elixir]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} ||
|-
| [[F Sharp (programming language)|F#]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} ||
Line 224 ⟶ 227:
: The identifier of a regular "function" in Ruby (which is really a method) cannot be used as a value or passed. It must first be retrieved into a <code>Method</code> or <code>Proc</code> object to be used as first-class data. The syntax for calling such a function object differs from calling regular methods.
: Nested method definitions do not actually nest the scope.
: Explicit currying with <code>[
==See also==
Line 242 ⟶ 245:
==External links==
* [http://rosettacode.org/wiki/First-class_functions First-class functions] on [[Rosetta Code]].
* [http://www.ibm.com/developerworks/linux/library/l-highfunc/index.html Higher order functions] {{Webarchive|url=https://web.archive.org/web/20191112160401/http://www.ibm.com/developerworks/linux/library/l-highfunc/index.html|date=November 12, 2019}} at
{{data types}}
|