2

我明白为什么推断的返回类型max({})Null(我认为该函数如何与空/可能为空/非空的可迭代对象一起工作真是太棒了),但为什么使用空的命名参数列表 - <code>max{} - 推断返回Nothing?为什么这些情况不同?这是故意的吗?

这编译并运行得很好,

Nothing foo = max{};

尽管我预计如果它实际评估它会立即失败nothing。既然Nothing是一切的子类型,你甚至可以这样做,

Integer bar = max{};

并且编译器不会抱怨,但运行它会产生一个java.lang.NullPointerException. 什么?!我以为我们永远不应该在锡兰看到这种情况!

4

1 回答 1

4

哇,不错的一个!我花了几分钟思考了解这里发生了什么。所以,我猜你知道,这个:

max {}

从理论上讲,应该与以下内容相同:

max({})
max { values={}; }

现在,如果您编写这些排列中的任何一个,您将获得为Null推断出的正确返回类型max()。而且,确实,如果您执行任一示例,结果是正确的,null.

事实上,即使我运行以下程序:

void run() => print( max{} );

<null>正如我们所期望的那样,它会打印出来。

所以这里发生的事情是我的类型参数推断算法中有一个错误,在推断类型参数时它没有考虑“隐式”空可迭代参数 a {Nothing*}。因此,您将获得 的Nothing两个类型参数的推断类型max(),因为类型参数被视为不受约束。然后,由于Nothing是 的子类型Integer,类型检查器允许您将结果分配给Integer。当然,函数实际返回的 null 值不可分配给Integer,因此您会得到一个当然永远不会发生的 NPE。

解决方案是我需要修复错误。这将是一个很小的衬里。

如果您不介意,请您向 ceylon-spec 提交错误报告,我将在明天修复它。

谢谢!

于 2013-12-04T02:19:59.120 回答