一等值可以是
第二类值只能作为参数传递。
三等值甚至不能作为参数传递。
为什么要定义这些东西呢?据我所知,“可以作为参数传递”意味着它可以被推入运行时堆栈;“可以被分配到变量”意味着它可以被移动到内存的不同位置; “可以从子程序返回”几乎具有“可以分配给变量”的相同含义,因为返回的值总是被放入已知地址,因此第一类值完全是“可移动”或“动态”,第二类value是一半“可移动”,第三类值只是“静态”,例如C / C ++中的标签,只能通过goto语句来解决,除了“goto”之外你不能对该地址做任何事情。。我的理解有意义吗?或者这三种价值究竟是什么意思?
答案 0 :(得分:40)
哦不,我可能要再次编辑维基百科了。
实际上只有两个区别:一流而不是一流。如果Michael Scott谈到第三 - 类任何事情,我会非常沮丧。
好的,那么什么是“一流”呢?嗯,这个术语几乎没有技术含义。当存在时,其含义通常是比较性的,并且它适用于语言中的 thing (我在这里故意模糊),它具有比同类事物更多的特权。这就是所有人的意思。
让我们看一些例子:
C中的函数指针是第一类值,因为它们可以传递给函数,从函数返回,并像任何其他值一样存储在堆分配的数据结构中。 Pascal和Ada中的函数不是第一类值,因为虽然它们可以作为参数传递,但它们不能作为结果返回或存储在堆分配的数据结构中。
结构类型是C中的第二类类型,因为没有结构类型的文字表达式。 (由于C99有文字初始值设定项,带有命名字段,但这仍然不像在任何可以使用表达式的文字中那样通用。)
多态值是ML中的第二类值,因为虽然它们可以与名称绑定,但它们不能是lambda绑定的。因此它们不能作为参数传递。但是在Haskell中,因为Haskell支持更高级别的多态性,所以多态值是一流的。 (它们甚至可以存储在数据结构中!)
在Java中,类型int
是第二类,因为您无法继承它。类型Integer
是第一类。
在C中,标签是第二类,因为它们没有值,您无法使用它们进行计算。在FORTRAN中,行号具有值,因此是第一类。 C的GNU扩展允许您定义一流的标签,它非常有用。在这种情况下,头等舱意味着什么?这意味着标签具有值,可以存储在数据结构中,并且可以在goto
中使用。但是这些值在另一种意义上是第二类,因为来自一个过程的标签不能有意义地用于属于另一个过程的goto
。
我们是否知道这个术语是多么无用?
我希望这些例子让您相信,在考虑整体编程语言时,“一流”的想法并不是一个非常有用的想法。当您谈论特定语言或语言系列的特定功能时,它可能是一种有用的简写(“语言不起作用,除非它具有一流的,嵌套的函数”)但总的来说,你最好说出你的意思,而不是谈论“一流”或“不是一流”的事情。
至于“第三类”,只说不。
答案 1 :(得分:4)
如果在代码中显式可操作,那么它就是一流的。换句话说,如果可以在运行时以编程方式操作,那么某些东西就是一流的。
这与元编程紧密相关,因为您在代码中描述的内容(在开发时)是一个元级别,而在运行时存在的是另一个元级别。但是这两个元级别之间的障碍可能会模糊不清,例如反思。当某些东西在运行时具体化时,它就变得明确可操作了。
我们说的是一流的对象,因为对象可以在运行时以编程方式进行操作(这就是目的)。
在java中,你有类,但它们不是一流的,因为除非你使用反射,否则代码通常不能操作类。但是在Smalltalk中,类是一流的:代码可以像常规对象一样操作类。
在java中,你有包(模块),但它们不是一流的,因为代码不会在运行时操作包。但是在NewSpeak中,包(模块)是一流的,您可以实例化一个模块并将其传递给另一个模块,以在运行时指定模块性。
在C#中,你有一些是一流函数的闭包。它们存在并且可以在运行时以编程方式进行操作。这些东西(现在)在java中还不存在。
对我而言,第一级/非第一级的边界并不完全严格。某些语言结构有时难以发音,例如: java原始类型。我们可以说它不是一流的,因为它不是一个对象,不能通过可以传递的引用来操纵,但原始值仍然存在并且可以在运行时进行操作。
PS:我同意诺曼拉姆齐的观点,二等和三等价值对我来说毫无意义。
答案 2 :(得分:2)
在 Roger Keays和Andry Rakotonirainy。面向情境的编程。第3届ACM国际无线和移动数据工程研讨会,MobiDe '03,第9-16页,纽约,纽约,美国,2003年.ACM。
答案 3 :(得分:0)
这些术语非常广泛,并没有真正全局定义,但这里有最合乎逻辑的定义:
一等值是具有实际有形值的值,因此可以作为变量,参数,返回值或其他任何值进行操作和转换。
这并不需要一个彻底的例子,是吗?在C中,int是一流的。
二等价值更有限。它们具有值,但它们不能直接使用,因此编译器会故意限制您可以使用它做什么。您可以引用它们,因此您仍然可以使用表示它们的第一类值。
例如,在C中,函数是第二类值。它不能被改变,但它可以被调用和引用。
三等价值更加有限。它们不仅没有值,而且完全没有交互,并且通常仅用作编译时属性。
例如,在Rust中,生命周期是第三类值。你根本不能使用它的生命周期。您只能 接收它作为模板参数,您只能 将其用作模板参数(创建新变量时仅 ),并且
。。另一个例子,在C ++中,结构或类是第三类值。这不需要太多解释。