代码之家  ›  专栏  ›  技术社区  ›  Earlz

如果没有空值,我们会怎么做?

  •  20
  • Earlz  · 技术社区  · 14 年前

    我曾经读到过,拥有可以为空的类型绝对是一种罪恶。我相信这是在一篇文章中写的,这篇文章是由创造它们的人写的(在Ada中?)我相信 this is the article

    不管怎样,如果默认情况下像C这样的语言使用了不可为空的类型呢?您将如何替换C或Ruby中的一些常见习语或任何其他通用语言? null 是否为可接受值?

    11 回复  |  直到 13 年前
        1
  •  26
  •   Richard Berg    14 年前

    我不直接声明可以为空的类型是邪恶的,而是假定: 大多数语言将空性移植到所有类型上,而这两个概念实际上应该是正交的。 .

    例如,所有非原始Java类型(以及所有的C引用类型)都是空的。为什么?我们可以反反复复,但最终我敢打赌答案会归结为“这很容易”。Java语言没有什么本质上需要广泛的可空性。C++引用提供了一个很好的例子,说明如何在编译器级别去掉空值。当然,C++有很多丑陋的语法,Java明确地试图缩减,所以一些好的特性在坏的时候就出现在切割层上。

    C 2.0中的可空值类型为正确的方向提供了一个步骤——从不相关的类型语义中分离可空性,或者更糟的是,从clr实现细节中分离可空性——但它仍然缺少一种与引用类型相反的方法。(代码契约非常好,但它们并不像我们在这里讨论的那样嵌入到类型系统中。)

    很多功能性语言或其他晦涩难懂的语言从一开始就有了这些概念……但如果它们被广泛使用,我们就不会有这样的讨论……

    回答你的问题:禁止现代语言中的空值,批发,和所谓的“十亿美元的错误”一样愚蠢。在空值最好的地方有有效的编程结构:可选参数,任何类型的默认/回退计算,联合运算符导致简洁的代码,与relatio的交互。NAL数据库等。强迫自己使用哨兵值、NAN等将是一种比疾病严重得多的“治疗方法”。

    也就是说,我暂时同意 情绪 在引言中表达,只要我能详细阐述以适合我自己的经验:

    1. 需要空值的情况比大多数人想象的要小。
    2. 一旦您将空值引入库或代码路径,它将 许多的 摆脱它们比增加它们更难。(所以不要让初级程序员一时冲动地去做!)
    3. 可以为空的Bug具有可变的生存期
    4. 与3相关:早期碰撞
        2
  •  23
  •   bcat    14 年前

    我们会用 option types 对于(非常)少数允许空值的地方实际上是可取的,而且我们会有很多不那么模糊的错误,因为任何对象引用都会保证指向适当类型的有效实例。

        3
  •  7
  •   gdj    14 年前

    haskell是一种强大的语言,它没有无效的概念。基本上,每个变量都必须初始化为非空值。如果要表示一个“可选”变量(该变量可能有一个值,但可能没有),可以使用一个特殊的“可能”类型。

    在haskell中实现这个系统比在c中更容易,因为haskell中的数据是不可变的,所以在后面填充一个空引用是没有意义的。但是,在c中,链接列表中的最后一个链接可能具有指向下一个链接的空指针,当列表展开时,该链接将被填充。我不知道没有空类型的过程语言是什么样子的。

    另外,请注意,上面的许多人似乎建议用特定于类型的逻辑“无”值(999-999-9999,) 无效的 “等等”。这些值并不能真正解决任何问题,因为人们使用nulls的问题是,它们是一个特殊情况,但人们忘记了为特殊情况编写代码。对于特定于类型的逻辑无值,人们仍然忘记为特殊情况编写代码,但是他们避免了捕获此错误的错误,这是一件坏事。

        4
  •  4
  •   Darrel Miller    14 年前

    我想你指的是这场谈话:“ Null References: The billion dollar mistake

        5
  •  4
  •   ergosys    14 年前

    您可以采用一个简单的规则:所有变量都被初始化(作为默认值,可以重写)为一个不可变的值,由变量的类定义。对于标量,这通常是某种形式的零。对于引用,每个类都将定义其“null”值是什么,并且将使用指向该值的指针初始化引用。

    这实际上是nullObject模式的语言范围的实现: http://en.wikipedia.org/wiki/Null_Object_pattern 所以它并没有真正摆脱空对象,它只是防止它们成为必须这样处理的特殊情况。

        6
  •  2
  •   slebetman    14 年前

    TCL是一种不仅没有空值概念的语言,而且空值本身的概念与语言的核心不一致。在TCL中,我们说:“一切都是一根弦”。它真正的意思是TCL具有严格的值语义(这只是默认为字符串)。

    那么TCL程序员用什么来表示“无数据”?主要是空弦。在某些情况下,空字符串可以表示数据,那么它通常是:

    1. 无论如何都要使用空字符串-大多数情况下,它对最终用户没有影响。

    2. 使用数据流中不存在的值-例如字符串 "_NULL_" 或数字 9999999 或者我最喜欢的nul字节 "\0" .

    3. 使用围绕值的数据结构-最简单的是列表(其他语言称之为数组)。一个元素的列表表示值存在,零元素表示空。

    4. 变量存在性的检验- [info exists variable_name] .

    值得注意的是,TCL并不是唯一具有严格值语义的语言。C也有严格的值语义,但是值的默认语义恰好是整数而不是字符串。

    哦,差点忘了另一个:

    有些库使用数字2的变体,允许用户指定“无数据”的占位符是什么。基本上,它允许您指定一个默认值(如果您不指定默认值,通常默认值为空字符串)。

        7
  •  2
  •   Aardappel    13 年前

    空不是问题,它是允许您编写代码访问可能为空的值的语言。

    如果语言只需要检查任何指针访问,或者首先将其转换为不可为空的类型,那么99%的与空相关的错误将消失。例如在C++中

    void fun(foo *f)
    {
        f->x;                  // error: possibly null
        if (f)              
        {
            f->x;              // ok
            foo &r = *f;       // ok, convert to non-nullable type
            if (...) f = bar;  // possibly null again
            f->x;              // error
            r.x;               // ok
        }
    }
    

    遗憾的是,这不能被改造为大多数语言,因为它会破坏很多代码,但对于一种新语言来说是相当合理的。

        8
  •  1
  •   supercat    14 年前

    实际上,在任何一种允许指针或对象引用的强大编程语言中,在某些情况下,代码将能够访问没有运行任何初始化代码的指针。可以保证这样的指针将被初始化为某个静态值,但这似乎并不十分有用。如果一台机器具有捕获对未初始化变量(无论是指针还是其他什么)的访问的一般方法,那么这比特殊的大小写空指针要好,但是在允许使用空指针的算术的实现中,我看到的与空指针相关的最大错误是。将5添加到(char*)0不应产生指向地址5的字符指针;它应触发错误(如果创建指向绝对地址的指针是合适的,则应该有其他方法)。

        9
  •  1
  •   Jens    13 年前

    如果没有空值,我们会怎么做? 发明它! :-)如果要查找要表示的带内指针值,则不必成为火箭科学家就可以使用0。 实际上不是指针 .

        10
  •  0
  •   S.Lott    14 年前

    我们使用任一

    1. 鉴别器。一种额外的属性、标志或指示器,表示一个值为“空”,必须被忽略。

    2. 域特定的空值。一个特定的值——在允许的域内——被解释为“忽略这个值”。例如,社会保险号999-99-9999可以是域特定的空值,表示SSN未知或不适用。

        11
  •  0
  •   Community CDub    7 年前

    我们将创建各种奇怪的构造来传递对象“无效”或“不存在”的消息,如其他答案所示。一个信息 null 能很好地传达。

    就个人而言,我会写一些C预处理器,允许我使用 无效的 . 然后这会映射到一些 dynamic 对象,它抛出 NullReferenceException 每当调用方法时。

    早在1965年,空引用看起来像是一个错误。但是现在,有了各种警告我们空引用的代码分析工具,我们不必担心太多。从编程的角度 无效的 是一个非常有价值的关键词。

    推荐文章