Rust 之坑:啰嗦的浮点数排序

最近,一篇比较 Rust 和新出的 Nim 的语言的文章出现了,作者列举了 Rust 总总繁琐啰嗦的地方,然后在 Hacker News 中提供了新的弹药

如果要对一个浮点数数组进行排序,在 Python 中非常简单:

在 Haskell 中也非常简洁:

而在 Rust 中你得写这么一长串怪物:

是不是很坑?太恶心了吧。他将这种代码归咎于 Rust 的宗教原因,认为这是一种惩罚。是挺宗教的,把简单的事情搞复杂。

且慢,来,我们回想一下浮点数包括哪些东东:正常的数字,+0 -0 +∞ -∞,还有 NaN……

等等 NaN?NaN 的意思是“不是一个数字”。既然不是数字,也就没有办法和数字比较大小了。

稍微解释一下,xs 是一个数组,sort_by 传入一个闭包函数,通过闭包函数进行排序,先用前一个数比较后一个数 a.partial_cmp(b) ,它的返回值是一个 Option,表示这个函数有可能运行失败,.unwrap_or(Less) 就是说当运行失败的时候,返回 Less。

在这种情况下,两个数进行比较,如果其中是一个是 NaN 就会返回 Less。

这里用我很喜欢的 Python 来做反面教材:

Oh,要死啦。

Ruby 要好得多,会抛出错误:

(补充一下,Haskell 貌似不是 IEEE 标准的浮点数,没有 NaN。)

尽管你说或许你能保证不出现 NaN,但是无论如何对于 IEEE Float 来说,都不是良序的,所以你必须考虑到这种极端的边界情况,正是因此才能保证安全。而且不是像 Ruby 靠运行时抛出和捕获异常,而是靠编译时的类型安全。

如果这就是 Rust 的宗教,那么这一定是我喜欢的宗教了,

Rust 之坑:啰嗦的浮点数排序》上有5条评论

  1. yukirock

    Haskell 的做法似乎倾向于统一用 Maybe 来搞定,所以如果有风险就包成 Maybe Float 之类的东西,万一死了就踢出一个 Nothing 来。当然以 Haskell 的做派 IEEE float 肯定是不能用的就是了。

    回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注