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

在语言中不包含空值的含义?

  •  13
  • Imagist  · 技术社区  · 15 年前

    我知道在编程语言中不需要空值,最近我决定不在编程语言中包含空值。声明是通过初始化完成的,因此不可能有未初始化的变量。我希望这能消除 NullPointerException 支持更有意义的异常或者根本没有某些类型的错误。

    当然,由于该语言是在C语言中实现的,所以在封面下面将使用空值。

    我的问题是,除了使用空值作为错误标志(这是例外情况下处理的)或作为数据结构(如链接列表和二进制树)的终结点(这是用有区别的联合处理的)之外,是否还有其他空值的使用案例需要我解决?不使用空值是否有真正重要的影响,这可能会导致我的问题?

    10 回复  |  直到 12 年前
        1
  •  8
  •   Greg Hewgill    15 年前

    最近有一篇关于LTU的文章,作者是托尼·霍尔,题为 Null References: The Billion Dollar Mistake 它描述了一种允许 存在 编程语言中的空值,但也 消除 引用此类空引用的风险。这看起来很简单,但这是一个很有说服力的想法。

    更新 :这里有一个链接,指向我读过的实际论文,其中讨论了在埃菲尔的实现: http://docs.eiffel.com/book/papers/void-safety-how-eiffel-removes-null-pointer-dereferencing

        2
  •  3
  •   Mark Rushakoff    15 年前

    从中借用页面 Haskell's Maybe monad ,如何处理返回值可能存在或不存在的情况?例如,如果您试图分配内存,但没有可用的内存。或者您已经创建了一个数组来容纳50个foo,但是还没有一个foo被实例化——您需要某种方法来检查这些类型的东西。

    我想您可以使用异常来覆盖所有这些情况,但这是否意味着程序员必须包装 全部的 在一个试抓区?那顶多会让人恼火。或者所有的东西都必须返回它自己的值,再加上一个指示值是否有效的布尔值,这当然不是更好的。

    fwiw,我不知道有什么程序没有 一些 有点像 NULL ——你有 null 在所有的C风格语言和Java中,Python有 None ,scheme,lisp,smalltalk,lua,ruby都有 nil VB使用 Nothing 哈斯克尔有一种不同的 nothing .

    那不代表语言 绝对地 必须有某种类型的空值,但是如果外面所有的其他大型语言都使用它,那么它背后肯定有一些合理的推理。

    另一方面,如果您只制作一个轻量级DSL或其他非通用语言,那么如果您的本地数据类型都不需要它,那么您可能可以不使用空值。

        3
  •  1
  •   Tim    15 年前

    立即想到的是通过引用参数传递。我主要是一个Objective-C编码人员,所以我习惯于看到这样的事情:

    NSError *error;
    [anObject doSomething:anArgumentObject error:&error];
    // Error-handling code follows...

    在执行此代码之后, error 对象具有有关遇到的错误(如果有)的详细信息。但我不在乎是否发生错误:

    [anObject doSomething:anArgumentObject error:nil];

    因为我没有为错误对象传递任何实际值,所以我没有返回任何结果,也不担心分析错误(因为我一开始并不关心是否发生了错误)。

    您已经提到了您正在以不同的方式处理错误,所以这个特定的示例并不真正适用,但要点是:当您通过引用传递某个内容时,您会怎么做?或者你的语言就是不这么做?

        4
  •  1
  •   JRL    15 年前

    我认为对于一个返回空值的方法是有用的——例如对于一个应该返回某个对象的搜索方法,它可以返回找到的对象,或者如果找不到,它可以返回空值。

    我开始学习Ruby,Ruby对于空有一个非常有趣的概念,也许您可以考虑实现一些Silimar。在Ruby中,空被称为nil,它和其他任何对象一样是一个实际的对象。它恰好作为全局单例对象实现。同样在Ruby中,也有一个对象false,在布尔表达式中,nil和false的值都是false,而其他值都是true(例如,甚至0的值都是true)。

        5
  •  0
  •   RHSeeger    15 年前

    在我看来,有两种使用情况通常使用空值:

    • 有问题的变量没有值(无)
    • 我们不知道所讨论的变量的值(未知)

    两种常见的情况,老实说,对两者都使用空值会导致混淆。

    值得注意的是,一些不支持空值的语言确实支持空值/未知值。例如,haskell支持“maybe”,它可以包含值或不包含值。因此,命令可以返回(和接受)他们知道永远都有值的类型,或者他们可以返回/接受“可能”来表示可能没有值。

        6
  •  0
  •   olliej    15 年前

    我更喜欢使用不可空指针的概念作为默认值,可以使用可空指针。你可以通过C++(引用)(而不是指针)来做到这一点,但是在某些情况下它会变得相当粗糙和令人讨厌。

    在Java/C语言中,一种语言可以不使用NULL,例如Haskell(和大多数其他函数语言)都有一个“可能”类型,它实际上是一个构造,它提供了一个可选的空指针的概念。

        7
  •  0
  •   RMorrisey    15 年前

    我不明白你为什么要从语言中消除“空”的概念。如果你的应用程序要求你“懒惰地”进行初始化,你会怎么做——也就是说,在需要数据之前,你不会执行操作?前任:

    public class ImLazy {
     public ImLazy() {
      //I can't initialize resources in my constructor, because I'm lazy.
      //Maybe I don't have a network connection available yet, or maybe I'm
      //just not motivated enough.
     }
    
     private ResourceObject lazyObject;
     public ResourceObject getLazyObject() { //initialize then return
      if (lazyObject == null) {
       lazyObject = new DatabaseNetworkResourceThatTakesForeverToLoad();
      }
     }
    
     public ResourceObject isObjectLoaded() { //just return the object
      return (lazyObject != null);
     }
    }
    

    在这种情况下,我们如何返回getObject()的值?我们可以想出两件事中的一件:

    -要求用户在声明中初始化LazyObject。然后,用户必须填写一些虚拟对象(uselessResSourceObject),这要求他们编写所有相同的错误检查代码(如果(lazyObject.equals(uselessResSourceObject))或:

    -提出一些其他值,其工作方式与空相同,但具有不同的名称

    对于任何复杂的/oo语言,您都需要这个功能,或者类似的功能,据我所见。拥有一个非空的引用类型(例如,在方法签名中,这样您就不必在方法代码中执行空检查)可能很有价值,但是对于确实使用它的情况,空功能应该是可用的。

        8
  •  0
  •   staticsan    15 年前

    有趣的讨论正在这里进行。

    如果我正在构建一种语言,我真的不知道我是否会有 null . 我想这取决于我想让语言看起来怎么样。举个例子:我编写了一种简单的模板化语言,它的主要优点是嵌套的令牌,并且易于将令牌作为值列表。它没有空的概念,但实际上它没有字符串以外的任何类型的概念。

    相比之下,语言是内置的,图标,广泛使用空值。Icon的语言设计者对空值做的最好的事情可能是使其与未初始化的变量同义(即,无法区分不存在的变量和当前持有空值的变量之间的区别)。然后创建两个前缀运算符来检查空值和非空值。

    在PHP中,我有时使用空值作为“第三个”布尔值。这在“黑盒”类型类(例如ORM core)中很好,其中状态可以是真的、假的或我不知道。空用于第三个值。

    当然,这两种语言都没有C所具有的指针,因此空指针不存在。

        9
  •  0
  •   Mr. Shiny and New 安宇    15 年前

    我们在应用程序中一直使用nulls来表示“无”情况。例如,如果要求您在给定ID的数据库中查找一些数据,并且没有与该ID匹配的记录:返回空值。这非常方便,因为我们可以将空值存储在缓存中,这意味着如果有人在几秒钟内再次请求该ID,我们不必返回数据库。

    缓存本身有两种不同的响应:空,这意味着缓存中没有这样的条目,或者条目对象。Entry对象可能有一个空值,这是我们缓存一个空数据库查找时的情况。

    我们的应用程序是用Java编写的,但是即使是未经检查的异常,使用异常来执行这些操作也会令人恼火。

        10
  •  0
  •   supercat    12 年前

    如果一个人接受这样的观点,即强大的语言应该具有某种类型的指针或引用类型(即可以保存对编译时不存在的数据的引用的东西),以及某种形式的数组类型(或具有通过整型索引可按顺序寻址的存储槽集合的其他方法),以及该槽后者的s应该能够容纳前者,并且我们接受这样一种可能性,即在所有指针/引用的显式值存在之前,我们可能必须读取指针/引用数组的某些槽,然后从编译器的角度来看,将有一些程序在写入显式值之前读取数组槽(尝试在一般情况下,确定阵列插槽在写入之前是否可以读取,这等同于暂停问题)。

    虽然一种语言可能要求在读取任何数组槽之前用一些非空引用初始化所有数组槽,但在许多情况下,实际上没有任何可以存储的东西比空更好:如果试图读取尚未写入的数组槽并取消对(非)项的引用,则在那里,它代表一个错误,最好是有系统陷阱的条件,而不是访问一些任意的对象,这些对象的唯一目的是给数组槽一些他们可以引用的非空的东西。