Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
First-class function
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
{{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> First-class functions are a necessity for the [[functional programming]] style, in which the use of [[higher-order function]]s is a standard practice. A simple example of a higher-ordered function is the ''[[map (higher-order function)|map]]'' function, which takes, as its arguments, a function and a list, and returns the list formed by applying the function to each member of the list. For a language to support ''map'', it must support passing a function as an argument. 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 ''function argument''.<ref>[[Joel Moses]]. [https://dspace.mit.edu/handle/1721.1/5854 "The Function of FUNCTION in LISP, or Why the FUNARG Problem Should be Called the Environment Problem"]. MIT AI Memo 199, 1970.</ref> In early imperative languages these problems were avoided by either not supporting functions as result types (e.g. [[ALGOL 60]], [[Pascal (programming language)|Pascal]]) or omitting nested functions and thus non-local variables (e.g. [[C (programming language)|C]]). The early functional language [[Lisp (programming language)|Lisp]] took the approach of [[dynamic scoping]], where non-local variables refer to the closest definition of that variable at the point where the function is executed, instead of where it was defined. Proper support for [[lexically scoped]] first-class functions was introduced in [[Scheme (programming language)|Scheme]] and requires handling references to functions as [[closure (computer science)|closure]]s instead of bare [[function pointer]]s,<ref name="strachey"/> which in turn makes [[Garbage collection (computer science)|garbage collection]] a necessity.{{Citation needed|reason=Rust does it without GC|date=April 2025}} == Concepts == In this section, we compare how particular programming idioms are handled in a functional language with first-class functions ([[Haskell (programming language)|Haskell]]) compared to an imperative language where functions are second-class citizens ([[C (programming language)|C]]). === Higher-order functions: passing functions as arguments === {{further information|Higher-order function}} In languages where functions are first-class citizens, functions can be passed as arguments to other functions in the same way as other values (a function taking another function as argument is called a higher-order function). In the language [[Haskell (programming language)|Haskell]]: <syntaxhighlight lang="haskell"> map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = f x : map f xs </syntaxhighlight> Languages where functions are not first-class often still allow one to write higher-order functions through the use of features such as [[function pointer]]s or [[Delegate (CLI)|delegate]]s. In the language [[C (programming language)|C]]: <syntaxhighlight lang="c"> void map(int (*f)(int), int x[], size_t n) { for (int i = 0; i < n; i++) x[i] = f(x[i]); } </syntaxhighlight> There are a number of differences between the two approaches that are ''not'' directly related to the support of first-class functions. The Haskell sample operates on [[List (computing)|list]]s, while the C sample operates on [[Array data structure|arrays]]. Both are the most natural compound data structures in the respective languages and making the C sample operate on linked lists would have made it unnecessarily complex. This also accounts for the fact that the C function needs an additional parameter (giving the size of the array.) The C function updates the array [[in-place]], returning no value, whereas in Haskell data structures are [[persistent data structure|persistent]] (a new list is returned while the old is left intact.) The Haskell sample uses [[recursion]] to traverse the list, while the C sample uses [[iteration]]. Again, this is the most natural way to express this function in both languages, but the Haskell sample could easily have been expressed in terms of a [[fold (higher-order function)|fold]] and the C sample in terms of recursion. Finally, the Haskell function has a [[Polymorphism (computer science)|polymorphic]] type, as this is not supported by C we have fixed all type variables to the type constant <code>int</code>. === Anonymous and nested functions === {{further information|Anonymous function|Nested function}} In languages supporting anonymous functions, we can pass such a function as an argument to a higher-order function: <syntaxhighlight lang="haskell"> main = map (\x -> 3 * x + 1) [1, 2, 3, 4, 5] </syntaxhighlight> In a language which does not support anonymous functions, we have to bind it to a name instead: <syntaxhighlight lang="c"> int f(int x) { return 3 * x + 1; } int main() { int list[] = {1, 2, 3, 4, 5}; map(f, list, 5); } </syntaxhighlight> === Non-local variables and closures === {{further information|Non-local variable|Closure (computer science)}} Once we have anonymous or nested functions, it becomes natural for them to refer to variables outside of their body (called ''non-local variables''): <syntaxhighlight lang="haskell"> main = let a = 3 b = 1 in map (\x -> a * x + b) [1, 2, 3, 4, 5] </syntaxhighlight> If functions are represented with bare function pointers, we can not know anymore how the value that is outside of the function's body should be passed to it, and because of that a closure needs to be built manually. Therefore we can not speak of "first-class" functions here. <syntaxhighlight lang="c"> typedef struct { int (*f)(int, int, int); int a; int b; } closure_t; void map(closure_t *closure, int x[], size_t n) { for (int i = 0; i < n; ++i) x[i] = (closure->f)(closure->a, closure->b, x[i]); } int f(int a, int b, int x) { return a * x + b; } void main() { int l[] = {1, 2, 3, 4, 5}; int a = 3; int b = 1; closure_t closure = {f, a, b}; map(&closure, l, 5); } </syntaxhighlight> Also note that the <code>map</code> is now specialized to functions referring to two <code>int</code>s outside of their environment. This can be set up more generally, but requires more [[boilerplate code]]. If <code>f</code> would have been a [[nested function]] we would still have run into the same problem and this is the reason they are not supported in C.<ref>"If you try to call the nested function through its address after the containing function has exited, all hell will break loose." ([https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Nested-Functions.html#Nested-Functions GNU Compiler Collection: Nested Functions])</ref> === Higher-order functions: returning functions as results === When returning a function, we are in fact returning its closure. In the C example any local variables captured by the closure will go out of scope once we return from the function that builds the closure. Forcing the closure at a later point will result in undefined behaviour, possibly corrupting the stack. This is known as the [[upwards funarg problem]]. === Assigning functions to variables === [[Assignment (computer science)|Assigning]] functions to [[variable (computer science)|variables]] and storing them inside (global) datastructures potentially suffers from the same difficulties as returning functions. <syntaxhighlight lang="haskell"> f :: [[Integer] -> [Integer]] f = let a = 3 b = 1 in [map (\x -> a * x + b), map (\x -> b * x + a)] </syntaxhighlight> === 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> ; [[Extensional equality]]: Two functions ''f'' and ''g'' are considered extensionally equal if they agree on their outputs for all inputs (∀''x''. ''f''(''x'') = ''g''(''x'')). Under this definition of equality, for example, any two implementations of a [[stable sorting algorithm]], such as [[insertion sort]] and [[merge sort]], would be considered equal. Deciding on extensional equality is [[undecidable problem|undecidable]] in general and even for functions with finite domains often intractable. For this reason no programming language implements function equality as extensional equality. ; [[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 [[purity (computer science)|pure]] languages, such as Haskell. == Type theory == {{main|Function type}} In [[type theory]], the type of functions accepting values of type ''A'' and returning values of type ''B'' may be written as ''A'' → ''B'' or ''B''<sup>''A''</sup>. In the [[Curry–Howard correspondence]], [[function type]]s are related to [[logical implication]]; lambda abstraction corresponds to discharging hypothetical assumptions and function application corresponds to the [[modus ponens]] inference rule. Besides the usual case of programming functions, type theory also uses first-class functions to model [[associative array]]s and similar [[data structure]]s. In [[category theory|category-theoretical]] accounts of programming, the availability of first-class functions corresponds to the [[closed category]] assumption. For instance, the [[simply typed lambda calculus]] corresponds to the internal language of [[Cartesian closed category|Cartesian closed categories]]. == Language support == Functional programming languages, such as [[Erlang (programming language)|Erlang]], [[Scheme (programming language)|Scheme]], [[ML (programming language)|ML]], [[Haskell (programming language)|Haskell]], [[F Sharp (programming language)|F#]], and [[Scala (programming language)|Scala]], all have first-class functions. When [[Lisp (programming language)|Lisp]], one of the earliest functional languages, was designed, not all aspects of first-class functions were then properly understood, resulting in functions being dynamically scoped. The later [[Scheme (programming language)|Scheme]] and [[Common Lisp]] dialects do have lexically scoped first-class functions. Many scripting languages, including [[Perl]], [[Python (programming language)|Python]], [[PHP]], [[Lua (programming language)|Lua]], [[Tcl]]/Tk, [[JavaScript]] and [[Io (programming language)|Io]], have first-class functions. For imperative languages, a distinction has to be made between Algol and its descendants such as Pascal, the traditional C family, and the modern garbage-collected variants. The Algol family has allowed nested functions and higher-order taking function as arguments, but not higher-order functions that return functions as results (except Algol 68, which allows this). The reason for this was that it was not known how to deal with non-local variables if a nested-function was returned as a result (and Algol 68 produces runtime errors in such cases). The C family allowed both passing functions as arguments and returning them as results, but avoided any problems by not supporting nested functions. (The gcc compiler allows them as an extension.) As the usefulness of returning functions primarily lies in the ability to return nested functions that have captured non-local variables, instead of top-level functions, these languages are generally not considered to have first-class functions. Modern imperative languages often support garbage-collection making the implementation of first-class functions feasible. First-class functions have often only been supported in later revisions of the language, including C# 2.0 and Apple's Blocks extension to C, C++, and Objective-C. C++11 has added support for anonymous functions and closures to the language, but because of the non-garbage collected nature of the language, special care has to be taken for non-local variables in functions to be returned as results (see below). {| class=wikitable width=100% style="font-size: 85%" ! colspan=2 rowspan=2 | Language !! colspan=2 | [[Higher-order function]]s !! colspan=2 | [[Nested function]]s !! colspan=2 | [[Non-local variable]]s !! rowspan=2 width=25% | Notes |- ! Arguments !! Results !! Named !! [[Anonymous function|Anonymous]] !! [[Closure (computer programming)|Closures]] !! [[Partial application]] |- | rowspan=6 | Algol family | [[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}} |- | [[Ada (programming language)|Ada]] || {{yes}} || {{no}} || {{yes}} || {{no}} || {{partial|Downwards}} || {{no}} |- | [[Oberon (programming language)|Oberon]] || {{yes}} || {{partial|Non-nested only}} || {{yes}} || {{no}} || {{partial|Downwards}} || {{no}} |- | [[Delphi (programming language)|Delphi]] || {{yes}} || {{yes}} || {{yes}} || {{yes|2009}} || {{yes|2009}} || {{no}} |- | rowspan=9 | C family | [[C (programming language)|C]] || {{yes}} || {{yes}} || {{Partial|Yes in GNU C}} || {{Partial|Yes in Clang([[Blocks (C language extension)|Blocks]])}} || {{Partial|Yes in Clang([[Blocks (C language extension)|Blocks]])}} || {{no}} || Has [[function pointer]]s. |- | [[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.) Explicit partial application possible with <code>std::bind</code>. |- | [[C Sharp (programming language)|C#]] || {{yes}} || {{yes}} || {{yes|7}} || {{yes|2.0 / 3.0}} || {{yes|2.0}} || {{yes|3.0}} || Has [[Delegate (CLI)|delegate]]s (2.0) and lambda expressions (3.0). |- | [[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}} || {{yes}} || Has [[anonymous inner class]]es. |- | [[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> || |- | [[Limbo (programming language)|Limbo]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{no}} || |- | [[Newsqueak]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{no}} || |- | [[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=12 | Functional languages || [[Lisp (programming language)|Lisp]] || {{partial|Syntax}} || {{partial|Syntax}} || {{yes}} || {{yes}} || {{partial|Common Lisp}} || {{no}} || (see below) |- | [[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> || |- | [[Julia (programming language)|Julia]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || |- | [[Clojure]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || |- | [[ML (programming language)|ML]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || |- | [[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}} || |- | [[OCaml]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || |- | rowspan=7 | Scripting languages | [[Io (programming language)|Io]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{no}} || |- | [[JavaScript]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes|ECMAScript 5}} || Partial application possible with user-land code on ES3 <ref>{{Cite web|url=http://ejohn.org/blog/partial-functions-in-javascript/|title=John Resig - Partial Application in JavaScript}}</ref> |- | [[Lua (programming language)|Lua]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}}<ref>{{cite web |last1=Katz |first1=Ian |url=http://tinylittlelife.org/?p=249 |title=Lua Code for Curry (Currying Functions) |date=2010-07-23 |df=mdy |archive-url=https://web.archive.org/web/20181106235506/http://tinylittlelife.org/?p=249 |archive-date=2018-11-06}}</ref> || |- | [[PHP]] || {{yes}} || {{yes}} || {{partial|Using anonymous}} || {{yes|5.3}} || {{yes|5.3}} || {{no}} || Partial application possible with user-land code. |- | [[Perl]] || {{yes}} || {{yes}} || {{yes|6}} || {{yes}} || {{yes}} || {{yes|6}}<ref>{{Cite web|url=http://perlgeek.de/blog-en/perl-5-to-6/28-currying.html|title = Blog | Perlgeek.de :: Currying}}</ref> || |- | [[Python (programming language)|Python]] || {{yes}} || {{yes}} || {{yes}} || {{partial|Expressions only}} || {{yes}} || {{yes|2.5}}<ref>{{Cite web|url=https://docs.python.org/whatsnew/2.5.html#pep-309-partial-function-application|title=What's New in Python 2.5 — Python 3.10.0 documentation}}</ref> || (see below) |- | [[Ruby (programming language)|Ruby]] || {{partial|Syntax}} || {{partial|Syntax}} || {{no|Unscoped}} || {{yes}} || {{yes}} || {{partial|1.9}} || (see below) |- | rowspan=6 | Other languages | [[Fortran]] || {{yes}} || {{yes}} || {{yes}} || {{no}} || {{no}} || {{no}} || |- | [[Maple (software)|Maple]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{no}} || |- | [[Mathematica]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{no}} || |- | [[MATLAB]] || {{yes}} || {{yes}} || {{yes}} || {{yes}}<ref>{{Cite web|url=http://www.mathworks.co.uk/help/matlab/matlab_prog/anonymous-functions.html|title=Anonymous Functions - MATLAB & Simulink - MathWorks United Kingdom}}</ref> || {{yes}} || {{yes}} || Partial application possible by automatic generation of new functions.<ref>[https://stackoverflow.com/q/9154271 Partial Function Evaluation in MATLAB]</ref> |- | [[Smalltalk]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{partial}} || Partial application possible through library. |- | [[Swift (programming language)|Swift]] || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || {{yes}} || |} ; C++: [[C++11]] closures can capture non-local variables by copy construction, by reference (without extending their lifetime), or by [[C++11#Rvalue references and move constructors|move construction]] (the variable lives as long as the closure does). The first option is safe if the closure is returned but requires a copy and cannot be used to modify the original variable (which might not exist any more at the time the closure is called). The second option potentially avoids an expensive copy and allows to modify the original variable but is unsafe in case the closure is returned (see [[dangling reference]]s). The third option is safe if the closure is returned and does not require a copy but cannot be used to modify the original variable either. ; Java: [[Java 8]] closures can only capture final or "effectively final" non-local variables. Java's [[function type]]s are represented as Classes. Anonymous functions take the type inferred from the context. Method references are limited. For more details, see {{slink|Anonymous function|Java limitations}}. ; Lisp : [[Lexically scoped]] Lisp variants support closures. [[Dynamically scoped]] variants do not support closures or need a special construct to create closures.<ref>[https://common-lisp.net/project/bknr/static/lmman/fd-clo.xml Closures in ZetaLisp] {{webarchive|url=https://web.archive.org/web/20120319071329/http://common-lisp.net/project/bknr/static/lmman/fd-clo.xml |date=2012-03-19 }}</ref> : In [[Common Lisp]], the identifier of a function in the function namespace cannot be used as a reference to a first-class value. The special operator <code>function</code> must be used to retrieve the function as a value: <code>(function foo)</code> evaluates to a function object. <code>#'foo</code> exists as a shorthand notation. To apply such a function object, one must use the <code>funcall</code> function: <code>(funcall #'foo bar baz)</code>. ; Python : Explicit partial application with <code>[https://docs.python.org/library/functools.html#functools.partial functools.partial]</code> since version 2.5, and <code>[https://docs.python.org/library/operator.html#operator.methodcaller operator.methodcaller]</code> since version 2.6. ; Ruby : 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>[https://docs.ruby-lang.org/en/master/Proc.html#method-i-curry]</code>. ==See also== * [[Defunctionalization]] * [[eval]] * [[First-class message]] * [[Kappa calculus]] – a formalism which excludes first-class functions * [[Man or boy test]] * [[Partial application]] == Notes == {{reflist|2}} == References == * [[Leonidas Fegaras]]. [https://web.archive.org/web/20110720102933/http://lambda.uta.edu/cse5317/l12.ppt "Functional Languages and Higher-Order Functions"]. CSE5317/CSE4305: Design and Construction of Compilers. University of Texas at Arlington. ==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 IBM developerWorks {{data types}} {{DEFAULTSORT:First-class function}} [[Category:Articles with example C code]] [[Category:Articles with example Haskell code]] [[Category:Compiler construction]] [[Category:Data types]] [[Category:Functional programming]] [[Category:Primitive types]] [[Category:Programming language theory]] [[Category:Subroutines]]
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)
Pages transcluded onto the current version of this page
(
help
)
:
Template:Citation needed
(
edit
)
Template:Cite book
(
edit
)
Template:Cite journal
(
edit
)
Template:Cite web
(
edit
)
Template:Data types
(
edit
)
Template:Further information
(
edit
)
Template:Main
(
edit
)
Template:No
(
edit
)
Template:Partial
(
edit
)
Template:Reflist
(
edit
)
Template:Short description
(
edit
)
Template:Slink
(
edit
)
Template:Webarchive
(
edit
)
Template:Yes
(
edit
)