“Functions As First-Class Objects In JavaScript, functions are first-class objects. They can be stored in variables, passed into other functions as arguments, passed out of functions as return values, and constructed at run-time. These features provide a great deal of flexibility and expressiveness when dealing with functions.As you will see throughout the book, these features are the foundation around which you will build a classically object-oriented framework.”
"In computer science, a programming language is said to have first-class functions if it treats functions as first-class citizens."显然,对于函数是一等“对象”的说法,自己就是源于程序自己的,也就是说当一个编程语言自己就是把函数当成一等公民的时候,那么咱们就称呼这个语言拥有“first-class function”,咋一看,这尼玛不就等于没说么?其实否则,间接地,它是在告诉咱们:在不一样编程语言里面,函数(对象)是处于不一样地位的,怎么去理解这句话,固然要继续阅读下去,咱们继续看原文:
"Specifically, this means that 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. [1] [2] Some programming language theorists require support for anonymous functions as well. [3] In languages with first-class functions, the names of functions do not have any special status, they are treated like ordinary variables with a function type. [4] The term was coined by Christopher Strachey in the context of “functions as first-class citizens” in the mid-1960s. [5]"从上面语句中,咱们大致能够得到这样的信息:
"A simple example of a higher-ordered function is the 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."颇有意思的函数,就好像C语言的main函数似的(固然有本质的区别),它好像有一种把全部函数集合在一块儿,再综合调用的意思,可是它实现的功能是远远强大于C的main函数的,这里我也不便多说,须要本身去体会。
1 void map(int (*f)(int), int x[], size_t n) { 2 for (int i = 0; i < n; i++) 3 x[i] = (*f)(x[i]); 4 }
注意:C语言采用指针类型来实现。javascript
1 int f(int x) { 2 return 3 * x + 1; 3 } 4 int main() { 5 int l[] = {1, 2, 3, 4, 5}; 6 map(f, l, 5); 7 }
1 typedef struct { 2 int (*f)(int, int, int); 3 int *a; 4 int *b; 5 } closure_t; 6 void map(closure_t *closure, int x[], size_t n) { 7 for (int i = 0; i < n; ++i) 8 x[i] = (*closure->f)(*closure->a, *closure->b, x[i]); 9 } 10 int f(int a, int b, int x) { 11 return a * x + b; 12 } 13 void main() { 14 int l[] = {1, 2, 3, 4, 5}; 15 int a = 3; 16 int b = 1; 17 closure_t closure = {f, &a, &b}; 18 map(&closure, l, 5); 19 }
“Also note that the由此本质上,C语言是不支持内嵌函数的,然而在 C语言中,存在一些模拟闭包的库,支持 回调函数callback的库有时在注册时须要两个参数:一个函数指针,一个独立的map
is now specialized to functions referring to twoint
s outside of their environment. This can be set up more generally, but requires more boilerplate code. Iff
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.”
void*
指针用以保存用户数据。这样的作法容许回调函数恢复其调用时的状态。这样的惯用法在功能上相似于闭包,但语法上有所不一样。
"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."
“当返回一个函数自己时,咱们其实是返回了这个闭包(由于闭包就是一种函数),在这个C语言示例里面,一旦咱们返回那些闭包,那么那些闭包所约束的局部变量将会溢出它的做用域,强行返回一个‘later point’将会致使一个未定义行为,颇有可能就是堆栈溢出,这就是所谓的‘ upwards funarg problem“这是我对这句话的拙劣的翻译,抛开各类专业性的问题,显然它是在告诉咱们C语言对这种机制的实现是不完善的。换一个角度来讲,C语言或许在构造的时候就天生不是实现闭包的最佳语言,它是不太适合进行函数式编程模式的。 这里,又有来自于wiki的一个总结:
"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 does 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 language are generally not considered to have first-class functions."这里面大体的意思是这样的,C语言家族里面,它是能够实现函数的参数传入和函数类型的返回(大体都是用指针来模拟实现的),可是因为内嵌函数的不支持性(除了gcc编译器对其的扩展,ps:多是一个特例吧),而且针对返回的函数必定要是有意义的这一层面来讲,返回内嵌函数显然是意义斐然的,因此C语言是不具备一等函数(first-class function)的,这里我能够补充一个javacript的例子:
1 var outer = function(){ 2 var innerNum = 123; 3 return function(){ 4 console.log(++innerNum); 5 }; 6 }(); 7 outer();
Language | Higher-order functions | Non-local variables | Partial application | Notes | ||||
---|---|---|---|---|---|---|---|---|
Arguments | Results | Nested functions | Anonymous functions | Closures | ||||
Algol family | ALGOL 60 | Yes | No | Yes | No | No | No | Have function types. |
ALGOL 68 | Yes | Yes[9] | Yes | Yes | No | No | ||
Pascal | Yes | No | Yes | No | No | No | ||
Oberon | Yes | Non-nested only | Yes | No | No | No | ||
C family | C | Yes | Yes | No | No | No | No | Has function pointers. |
C++ | Yes | Yes | No | C++11[10] | C++11[10] | No | Has function pointers, function objects. (Also, see below.) | |
C# | Yes | Yes | No | 2.0 / 3.0 | 2.0 | No | Has delegates (2.0) and lambda expressions (3.0). | |
Objective-C | Yes | Yes | No | 2.0 + Blocks[11] | 2.0 + Blocks | No | Has function pointers. | |
Java | Partial | Partial | No | No | 8 | No | Has anonymous inner classes. | |
Functional languages | Lisp | Syntax | Syntax | Yes | Yes | Common Lisp | No | (see below) |
Scheme | Yes | Yes | Yes | Yes | Yes | SRFI 26[12] | ||
Clojure | Yes | Yes | Yes | Yes | Yes | Yes | ||
ML | Yes | Yes | Yes | Yes | Yes | Yes | ||
Haskell | Yes | Yes | Yes | Yes | Yes | Yes | ||
Scala | Yes | Yes | Yes | Yes | Yes | Yes | ||
Scripting languages | JavaScript | Yes | Yes | Yes | Yes | Yes | ECMAScript 5 | Partial application possible with user-land code on ES3 [13] |
PHP | Yes | Yes | Unscoped | 5.3 | 5.3 | No | (see below) | |
Perl | Yes | Yes | 6 | Yes | Yes | 6[14] | ||
Python | Yes | Yes | Yes | Partial | Yes | 2.5[15] | (see below) | |
Ruby | Syntax | Syntax | Unscoped | Yes | Yes | 1.9 | (see below) | |
Other languages | Mathematica | Yes | Yes | Yes | Yes | Yes | No | |
Smalltalk | Yes | Yes | Yes | Yes | Yes | Partial | Partial application possible through library. | |
Fortran | Yes | Yes | Yes | No | No | No |