在Clojure中是否有除nil-punning以外的惯用替代方法? [英] Is there an idiomatic alternative to nil-punning in Clojure?
问题描述
我正在读取一些Clojure代码,该代码具有大量未初始化的值,例如nil
,用于传递到记录中的数字值.
I'm reading some Clojure code at the moment that has a bunch of uninitialised values as nil
for a numeric value in a record that gets passed around.
Now lots of the Clojure libraries treat this as idiomatic. Which means that it is an accepted convention.
但是它也会导致NullPointerException
,因为并非所有Clojure核心函数都可以将nil
作为输入处理. (他们也不应该).
But it also leads to NullPointerException
, because not all the Clojure core functions can handle a nil
as input. (Nor should they).
其他语言具有Maybe
或Option
的概念,以在值为null的情况下代替该值,以减轻NullPointerException
风险.这在Clojure中是可能的-但不能很常见.
Other languages have the concept of Maybe
or Option
to proxy the value in the event that it is null, as a way of mitigating the NullPointerException
risk. This is possible in Clojure - but not very common.
您可以使用fnil
做一些技巧,但这不能解决所有问题.
You can do some tricks with fnil
but it doesn't solve every problem.
另一种选择是简单地将未初始化的值设置为类似:empty-value
的符号,以强制用户在所有处理代码中显式处理此方案.但这并不是nil
的真正提升,因为您直到运行时才真正发现所有场景(用他人的代码).
Another alternative is simply to set the uninitialised value to a symbol like :empty-value
to force the user to handle this scenario explicitly in all the handling code. But this isn't really a big step-up from nil
- because you don't really discover all the scenarios (in other people's code) until run-time.
我的问题是:在Clojure中是否有除nil-punning以外的惯用替代方法?
推荐答案
不确定您是否已阅读过Lispcast nil-punning上的> post ,但我确实认为这是为什么它很惯用的一个很好的例子,并涵盖了我在其他SO问题中没有提到的各种重要考虑因素.
Not sure if you've read this lispcast post on nil-punning
, but I do think it makes a pretty good case for why it's idiomatic and covers various important considerations that I didn't see mentioned in those other SO questions.
基本上,nil
是Clojure中的头等物品.尽管具有固有的常规含义,它还是一个适当的值,并且可以在许多上下文中以上下文相关的方式处理.与宿主语言中的null
相比,它更加灵活和强大.
Basically, nil
is a first-class thing in clojure. Despite its inherent conventional meaning, it is a proper value, and can be treated as such in many contexts, and in a context-dependent way. This makes it more flexible and powerful than null
in the host language.
例如,类似的东西甚至无法在java中编译:
For example, something like this won't even compile in java:
if(null) {
....
}
与clojure一样,(if nil ...)
也可以正常工作.因此,在许多情况下,您可以安全地使用 nil.我还没有看到一个随处可见if(foo != null) { ...
之类的代码的Java代码库.也许Java 8的Optional
会改变这一点.
Where as in clojure, (if nil ...)
will work just fine. So there are many situations where you can use nil safely. I'm yet to see a java codebase that isn't littered with code like if(foo != null) { ...
everywhere. Perhaps java 8's Optional
will change this.
我认为您可以容易遇到问题的地方是在Java interop场景中,您正在处理实际的null
s.一个好的clojure包装器库在很多情况下也可以帮助您避免这种情况,这是在可能的情况下优于直接Java互操作的一个好理由.
I think where you can run into issues quite easily is in java interop scenarios where you are dealing with actual null
s. A good clojure wrapper library can also help shield you from this in many cases, and its one good reason to prefer one over direct java interop where possible.
鉴于此,您可能需要重新考虑与当前潮流作斗争.但是由于您正在询问替代方案,因此我认为这很棒:棱镜的模式.模式具有Maybe
模式(以及许多其他有用的模式),并且在许多情况下都可以很好地工作.该图书馆非常受欢迎,我已经成功地使用了它. FWIW,建议在最近的 clojure应用书中.
In light of this, you may want to re-consider fighting this current. But since you are asking about alternatives, here's one I think is great: prismatic's schema. Schema has a Maybe
schema (and many other useful ones as well), and it works quite nicely in many scenarios. The library is quite popular and I have used it with success. FWIW, it is recommended in the recent clojure applied book.
这篇关于在Clojure中是否有除nil-punning以外的惯用替代方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!