使用NIL表示空节点的目的是什么?


17

在我的算法和数据结构课程中,教授,幻灯片和这本书(算法简介,第3版)都使用了这个词NIL来表示例如不存在的节点(在树中)的子代。

有一次,在一次演讲中NIL,我的同学没有说,而是null教授纠正了他,而我不明白为什么教授强调这个词。

人们为什么使用单词NIL代替null,或none或任何其他单词?是否NIL具有其他人没有的某些特定含义?有历史原因吗?

请注意,我在网络上也看到了一些地方,例如,使用单词null代替NIL,但是通常使用最后一个。

Answers:


25

就我而言,nullnilnonenothing为同一概念共同的名字:它表示“没有价值”的值,它存在于许多不同类型的(称为可空类型)。此值通常在通常存在值的地方使用,但可以省略,例如可选参数。不同的编程语言以不同的方式实现此功能,某些语言可能没有这样的概念。在带有指针的语言中,它是一个null指针。在许多面向对象的语言中,null不是对象:在其上调用任何方法都是错误。举几个例子:

  • 在Lisp中,nil通常用于表示不存在值。与大多数其他语言不同,nil它具有结构-它是名称为的符号"NIL"。它也是一个空列表(因为一个列表应该是一个cons单元格,但是有时由于列表为空所以没有cons单元格)。它是由幕后的空指针实现还是像其他符号一样实现,都取决于实现。
  • 在Pascal中,nil是可能未取消引用的指针值(在任何指针类型中均有效)。
  • 在C和C ++中,任何指针类型都包含一个NULL值,该值不同于指向有效对象的任何指针。
  • 在Smalltalk中,nil是未定义方法的对象。
  • 在Java和C#中,null是任何对象类型的值。任何尝试访问以下领域或方法的尝试null触发异常。
  • 在Perl中,undef它与任何其他标量值都不同,并且在整个语言和库中都使用它来表示缺少“真实”值。
  • 在Python中,None它与任何其他值均不同,并且在整个语言和库中都使用它来表示缺少“真实”值。
  • 在ML(SML,OCaml)中,None是类型方案中任何类型的值'a option,其中包含NoneSome x表示任何xtype 'a
  • 在Haskell中,类似的概念使用名称NothingJust x表示值和Maybe a类型。

在算法演示中,使用的名称往往源于演示者的背景或代码示例中使用的语言。

在语义演示,不同的名称可被用于指例如在NULL其表示在语言中的指针恒定标识符,以及在语义值。我认为没有任何标准的命名方案,有些演示文稿将其留给了字体差异,或者根本没有涉及具体的语法。ñ一世

您的讲师可能想null在课程中使用的编程语言(Java或C#?)中使用该单词作为空指针常量,并NIL表示某些数据结构中不存在节点,这可能会或可能不会实现作为空指针常量(例如,如上所示,在Lisp中,NIL通常不实现为空指针)。在讨论数据结构的实现技术时,这种区别将是有意义的。在讨论数据结构本身时,空指针常量的概念无关紧要,只有不等于任何其他值的概念才重要。

没有标准的命名方案。另一位讲师或课本可以使用不同的名称。


还有两个例子。目标C同时具有NULL(出于C兼容性)和nil;调用方法nil是无操作的。JavaScript同时具有null(一个不代表任何值的值)和undefined(一个值均未设置)。
200_success 2015年

1
“在面向对象的语言中,null不是对象:对其调用任何方法都是错误。” –并非所有的语言都正确,包括您列出的某些语言。在Ruby和Smalltalk中,它nil是一个与其他对象一样的对象,是的实例NilClass,没有其他“空值”概念,尤其是没有空指针。在Scala中,Nil它与nullnull有很大的不同,有点像空指针,但是,它实际上具有类型(Null),Nil是常规的旧对象,EmptyList如果可以的话,是类的单例实例,并且还有……
约尔格W¯¯米塔格

1
Nothing是底部类型,没有实例,Unit这是不返回值且具有singleton实例的子例程的类型()null它以某种方式带有“空指针”或“空引用”的概念,这并不是因为该术语固有于某种含义,而仅仅是因为诸如C,C ++,D,Java,C#这样的语言无处不在方式。NIL即使它实际上是在Pascal,Modula-2和Oberon中使用的,也没有这种含义。在Ruby中,nil有许多有用的方法:nil.to_i # => 0nil.to_s # => '',...
约尔格W¯¯米塔格

1
... nil.to_a # => []nil.to_h # => {}nil.to_f # => 0.0nil.inspect # => 'nil',等。您可以在此处查看完整列表。
约尔格W¯¯米塔格

3

我相信同时使用nilnull的原因是,前者主要是名词,而后者主要是形容词(我在网上和在我的词典中就读过:American Heritage 1992)。

关于含义和历史,NIL是拉丁文“ nihil”的缩写,意思是“无”。

据我所知,编程语言Lisp(1958)引入了使用名称nil表示空指针的方法

一个空指针是应该指向什么指针的值,因此不应该取消引用。在大多数情况下,指针只是内存地址。旨在包含此类指针的任何变量(即,任何位置)将始终包含某些位配置,并且任何此类配置都可以读取为内存地址。因此,通常情况下,该值nil将是程序禁止的内存区域的地址,如果程序尝试取消引用nil,则会导致某种形式的故障(可能是中断),这只能是错误。

在显式使用指针的语言中,拥有唯一的预定义标准值来发挥作用是至关重要的,因为能够测试指针是否正确指向某个内存位置非常重要。通常,在Lisp中,列表是作为连续的“ cons”对构建的,这些对包含指向列表元素的“ car”指针和指向下一个对的“ cdr”指针。在列表的最后一对中,第二个指针是nil

这与列表的递归定义相对应,即空列表或串联到列表的列表元素。因此,没有元素的列表由表示nil。此空列表恰好是列表半身像的标识。

由于列表可以用来表示集合,因此在这种情况下,空集合也可以由表示nil

因此nil从历史上讲是一个特殊的指针值,但后来被理解为其他更抽象的域(如列表或集合)的特殊标识值。

等于的指针nil是空指针,null是形容词而不是实体(即名词)。

单词(如形容词和名词)的协调使用与其他惯例非常一致。限定词null通常用于代数结构的零,例如monoid的标识:null元素。列表形成一个monoid,其中值nil是标识。集也是如此(尽管它们形成了具有更多特性的代数)。类似地,当整数为零时,它为null

这些单词和其他单词的用法有很多变化,例如没有变化,这取决于编程语言的作者和特质。

两个主要内涵是,如上所述

  • 作为标准的“未定义值”,实际上表示不存在任何可用值。

  • 作为某个域的标识值

这表明,如Gilles在公认的答案中所做的那样,断言NIL是“ 表示“缺少值的值 ” 并不是很准确。这取决于语言及其用途。该编程语言LISP大概介绍NIL在编程术语55年前。在LISP中,是一个空列表,可以等效地指出它,它并不表示没有值。它有时被用作丢失值的占位符,尽管由于空列表是一个值,通常应避免使用它。由程序员选择的任何对象中的结构中的缺失值,不能与可接受的值混淆。NIL()它是空列表的自然表示。

即使我们在上面已经表明它们可以关联,但这两个概念却大不相同。吉尔斯的答案所列举的术语使用方式的详细分类法可能很有趣,以查看这些单词中每个单词的使用是否更偏向于一个内涵或另一个内涵。

名称只不过是定义语篇的人在给定上下文中所赋予的含义。某些用法更常见,更自然或更一致,但应始终检查定义,并确保每种情况下的含义是什么。而且,人们不应该总是期望选择具有味道或一致性的术语。


0

NIL是一个对象,其值告诉程序员该对象无效。在NULL定义为0的C ++中,它特别有用。如果在C ++中取消引用NULL,则会得到未定义的行为。如果取消引用NIL(指向您定义的空对象的指针),则会得到一个可以告诉您的对象,该对象超出了数据结构的末尾。这对于防止灾难性程序故障和检测错误非常有用。

在双链表之类的情况下,可以使用NIL,使其成为列表的开头和结尾,以跟踪头和尾,并确保-> next和-> prev指针永远不会取消引用NULL。


据我所知,这是完全错误的。C ++中没有“ NIL”
大卫·里奇比

1
我认为您误解了我的答案。您提供的链接与我的答案无关。我建议nil是一个用户定义的对象,该对象在每个类的基础上定义,以指向该类的空(但有效)对象。
堡垒

编写“ NIL 一个对象”(我的重点)而不是说“可以将NIL定义为一个对象”的方式使您看起来好像在描述语言功能,而不是编程风格。但是,如果您的答案纯粹是关于一种编程风格的,那么这里并不是真正的话题。
David Richerby
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.