In programming language design, a first-class citizen (also object, entity, or value) in a given programming language is an entity which supports all the operations generally available to other entities. These operations typically include being passed as a parameter, returned from a function, and assigned to a variable.
第一类对象(First-class Object)在1960年由Christopher Strachey发明,原来称之为第一类公民(First-class citizen),意思是指函数可以作为电脑中的第一类公民。英文中也称之为First-class entity或First-class value。
定义
第一类对象不一定是指面向对象程序设计中所指的对象,而是指程序中的所有实体(比如:变量、函数、队列、字典等等)。一般第一类对象具有一下特征:
- 可以被存入变量或其他结构
- 可以被作为参数传递给其他方法/函数
- 可以被作为方法/函数的返回值
- 可以在执行期被创建,而无需在设计期全部写出
- 有固定身份
“固有身份”是指实体有内部表示,而不是根据名字来识别,比如匿名函数,还可以通过赋值叫任何名字。大部分语言的基本类型的数值(int, float)等都是第一类对象;但是数组不一定,比如C中的数组,作为函数参数时,传递的是第一个元素的地址,同时还丢失了数组长度信息。对于大多数的动态语言,函数/方法都是第一类对象,比如Python,但是Ruby不是,因为不能返回一个方法。第一类函数对函数式编程语言来说是必须的。
范例
在大多数语言中,数值和基础类型都是第一类对象,然而不同语言中对函数的区别很大,例如C语言与C++中的函数不是第一类对象,因为在这些语言中函数不能在执行期创造,而必须在设计时全部写好。相比之下,Scheme中的函数是第一类对象,因为可以用lambda语句来创造匿名函数并作为第一类对象来操作。
举个例子
在诸如Python、Scala等函数式编程语言中,最主要的基础是λ演算(lambda caculus),而λ演算的函数可以接受函数当作输入输出。因此,这类编程语言往往实现了第一类函数(First-class Function),以Scala为例。
Scala,顾名思义“可伸缩的”,为了使λ演算变得简洁,Scala实现了第一类值(First-class Value),即所有函数都是first-class values ,这意味着Scala中的所有函数都是值,因此,函数可以作为值一样进行参数传递或者从函数中返回。
作为返回,结果为2
val inc = (x : Int) => x + 1
inc(1)
作为传递,结果为List(2,3,4)
List(1, 2, 3).map((x: Int) => x + 1)
从以上结果可以看出,函数是在执行期被创建的;函数可以是匿名的;有返回值;能够被存储;函数作为实体满足了第一对象概念的定义。
历史背景
第一类对象和第二类对象的概念,在1960年由Christopher Strachey引入。实际上他没有提出严格的术语定义,而是给出了Algol语言中实数和过程的对比:
第一类对象和第二类对象。在Algol程序语言中,一个“实数”可能会出现在一个表达式中或被赋给一个变量,并可能在过程调用中作为实际参数出现。而“过程”只可能会出现在另一个过程调用中,最常见的是作为操作符,有时候也作为实参。除此之外,没有表达式会涉及到过程,或者将过程作为计算结果。因此在某种意义上,在Algol程序语言中的过程是第二类变量,它们总是会单独出现,不可能被一个表达式或一个变量表示(形式参数除外)…一些编程语言中允许函数在执行时创建,并将其称为”第一类“(First-class),而函数在C语言中不是第一类对象;相对应的称之为第二类对象(second-class objects),因为从函数角度看这类对象是独立的并且能在各种形式操作。像SmallTalk这种全面向对象语言,函数和方法都是第一类对象,因为操作符(+、-、etc)也是对象,因此操作符也是第一类对象。
来源:oschina
链接:https://my.oschina.net/u/1243149/blog/401272