None 比 null 更邪恶吗?
在 F# 中,他们没有空值并且不想支持它是一件大事。程序员仍然必须为 None 提供案例,类似于 C# 程序员必须检查 != null。
None 真的比 null 更邪恶吗?
In F# its a big deal that they do not have null values and do not want to support it. Still the programmer has to make cases for None similar to C# programmers having to check != null.
Is None really less evil than null?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
null
的问题在于您几乎可以在任何地方使用它,即引入无效状态,这既不是预期也不是有道理。。拥有
'a option
始终是一件明确的事情。您声明操作可以产生Some
有意义的值或None
,编译器可以强制正确检查和处理这些值。通过不鼓励
null
而支持'a option
类型,您基本上可以保证程序中的任何值在某种程度上都是有意义的。如果某些代码被设计为使用这些值,则您不能简单地传递无效值,并且如果存在option
类型的函数,您将必须涵盖所有可能性。The problem with
null
is that you have the possibility to use it almost everywhere, i.e. introduce invalid states where this is neither intended nor makes sense.Having an
'a option
is always an explicit thing. You state that an operation can either produceSome
meaningful value orNone
, which the compiler can enforce to be checked and processed correctly.By discouraging
null
in favor of an'a option
-type, you basically have the guarantee that any value in your program is somehow meaningful. If some code is designed to work with these values, you cannot simply pass invalid ones, and if there is a function ofoption
-type, you will have to cover all possibilities.当然是少邪恶啦!
如果您不检查 None,那么大多数情况下您的应用程序中都会出现类型错误,这意味着它将无法编译,因此它不会因 NullReferenceException 而崩溃(因为 None 会转换为 null)。
例如:
仍然可以实现类似 C# 的行为,但不太直观,因为您必须明确地说“忽略这可能是 None”:
在 C# 中,您不必考虑变量的情况为空,因此您可能只是忘记进行检查。与上面相同的示例:
编辑:Stephen Swensen 是绝对正确的,我的示例代码有一些缺陷,是匆忙编写的。固定的。谢谢你!
Of course it is less evil!
If you don't check against None, then it most cases you'll have a type error in your application, meaning that it won't compile, therefore it cannot crash with a NullReferenceException (since None translates to null).
For example:
It is still possible to achieve C#-like behavior, but it is less intuitive, as you have to explicitly say "ignore that this can be None":
In C#, you're not forced to consider the case of your variable being null, so it is possible that you simply forget to make a check. Same example as above:
Edit: Stephen Swensen is absolutely right, my example code had some flaws, was writing it in a hurry. Fixed. Thank you!
假设我向您展示了这样一个函数定义:
当您传入数据存储中不存在的人的
name
时,您认为会发生什么?如果不阅读代码(如果您有权访问它)、阅读文档(如果有人好心地编写了它),或者只是调用该函数,您将无从得知。这基本上就是空值的问题:它们的外观和行为就像非空值一样,至少在运行时是这样。
现在,假设您有一个带有此签名的函数:
这个定义非常明确地表明了所发生的情况:您要么会带回一个人,要么不会,并且此类信息以函数的数据类型进行传达。 通常,与潜在的空值相比,您可以更好地保证处理选项类型的两种情况。
我想说选项类型比空值要仁慈得多。
Let's say I show you a function definition like this:
What do you think happens when you pass in a
name
of a person who doesn't exist in the data store?Short of reading the code (if you have access to it), reading the documentation (if someone was kindly enough to write it), or just calling the function, you have no way of knowing. And that's basically the problem with null values: they look and act just like non-null values, at least until runtime.
Now let's say you have a function with this signature instead:
This definition makes it very explicit what happens: you'll either get a person back or you won't, and this sort of information is communicated in the function's data type. Usually, you have a better guarantee of handling both cases of a option type than a potentially null value.
I'd say option types are much more benevolent than nulls.
每次在 C# 中取消引用对象时,
null
都会引入潜在的运行时错误源 (NullRefereceException
),而None
会强制您创建源F# 中显式的运行时错误。例如,对给定对象调用
GetHashCode
会导致 C# 静默注入运行时错误源:相比之下,F# 中的等效代码预计不会产生
null
:如果您确实想要在 F# 中使用可选值,那么您将使用
option
类型,并且必须显式处理它,否则编译器将给出警告或错误:您仍然可以获得
NullReferenceException 在 F# 中通过绕过类型系统(这是互操作所必需的):
Whereas
null
introduces potential sources of run-time error (NullRefereceException
) every time you dereference an object in C#,None
forces you to make the sources of run-time error explicit in F#.For example, invoking
GetHashCode
on a given object causes C# to silently inject a source of run-time error:In contrast, the equivalent code in F# is expected to be
null
free:If you really wanted an optional value in F# then you would use the
option
type and you must handle it explicitly or the compiler will give a warning or error:You can still get
NullReferenceException
in F# by circumventing the type system (which is required for interop):