在流中键入推理

时间:2015-08-05 02:21:32

标签: scala

为什么编译器不能推断出filter中通配符的类型?

scala> Stream.from(1) takeWhile(_ < 1000) filter ( ( _ % 3  == 0) || ( _ % 5 == 0)) sum

<console>:18: error: missing parameter type for expanded function ((x$2) => x$2.$percent(3).$eq$eq(0))
              Stream.from(1) takeWhile(_ < 1000) filter ( ( _ % 3  == 0) || ( _ % 5 == 0)) sum

这很好用:

scala> Stream.from(1).takeWhile( x => x < 1000).filter(x => (x % 3 == 0) || (x % 5 == 0)).sum

2 个答案:

答案 0 :(得分:4)

来自SLS 6.23.1

  

如果表达式e绑定下划线部分u1,…,un,则按此顺序,它等同于匿名函数(u′1, ... u′n) => e′,其中每个u′i都来自ui,替换下划线通过e′替换每个下划线部分e,使用新标识符和ui u′i结果。

这意味着使用占位符语法的多个下划线表示具有多个参数的匿名函数。

(_ > 0)扩展为(x => x > 0)

(_ > 0 || _ < -10)扩展为((x, y) => x > 0 || y < -10)

(_ > 0 || _ < -10 || _ % 2 == 0)扩展为((x, y, z) => x > 0 || y < -10 || z % 2 == 0)

等等..这个错误有点令人困惑,因为看起来就像它试图根据错误信息在每组括号内读取它作为arity-1函数。我推测然后它不知道如何处理表达式x => a || y => b以推断类型以某种方式提出Int => Boolean

答案 1 :(得分:3)

_的每个后续实例都引用 next 参数。如果要重用lambda的参数,则必须像在发布的第二个版本中那样命名。

第一个版本的desugared更像是

filter ((x,y) => ( x % 3 == 0) || ( y % 5 == 0))