为什么 ((_: Int, _: Int) => _ / _) 在 ((_: Int) / (_: Int)) 编译时不编译?
Why does ((_: Int, _: Int) => _ / _) not compile when ((_: Int) / (_: Int)) does?
我正在学习 Scala,有一个非常基本的问题。考虑以下两个使用占位符语法的表达式 -
// Syntax A
val fnA = (_: Int, _: Int) => _ / _
// Syntax B
val fnB = (_: Int) / (_: Int)
及其尝试的应用程序 -
// Syntax A
fnA(33, 3)
// Syntax B
fnB(33, 3)
在这两个中,只有 B 和 App(B) 是有效语法,我不确定为什么。如果编译器能够推断出 fnB
中的参数(以及应用它们的顺序),为什么它不能为 fnA
做到这一点?我提出问题的前提是 fnB
是 fnA
的 shorthand,而且我很确定这种推理存在缺陷。我只是不确定这个缺陷是什么。
箭头左边下划线的含义=>
(_: Int, _: Int) => ...
与中缀运算符周围的下划线的含义不同 /
(_: Int) / (_: Int)
前者的意思是
"We are defining a function that takes two arguments, however
we will not use these arguments in the body of the function"
而后者是 shorthand 用于定义两个参数的函数
(x: Int, y: Int) => x / y
例如,
(_: Int, _: Int) => (_: Int) / (_: Int)
脱糖成
(a: Int, b: Int) => ((x: Int, y: Int) => x / y)
我们看到参数 a
和 b
没有在正文中使用,而正文恰好是另一个函数 ((x: Int, y: Int) => x / y)
.
Daniel将这两个意思记录为
_ + _ // Anonymous function placeholder parameter
_ => 5 // Discarded parameter
作为旁注,考虑类型级别的一些类似情况,涉及类型构造函数及其边界,其中下划线的含义取决于上下文
CC[_] <: Iterable[_]
就我个人而言,我的头脑欺骗我认为它等同于
CC[x] <: Iterable[x]
然而事实并非如此,<:
左边的下划线与右边
的意思不同
CC[x] <: Iterable[y] forSome {type y}
请注意 x
没有出现在 Iterable[y] forSome {type y}
中。 Adrian 在 Common Pitfalls:
下记录了这一点
...perhaps surprisingly, CC[_] <: Traversable[_]
is not equivalent to
CC[X] <: Traversable[X]
. The former expands to CC[X] <: Traversable[T] forSome {type T}
, where T
is existentially bound and thus unrelated to
X
.
并在 comment to type bounds on type constructor
comparing the level of types and values, it is quite unfortunate that
the type-level underscore behaves differently from the value-level
underscore. At the value level, _ + _
indeed stands for (x, y) => x + y
, a function. As hinted at in my other comment, the type-level
underscore is context-sensitive, and it never introduces a type-level
function. It's either an anonymous type parameter definition or an
anonymous existential. Neither of these have value-level equivalents.
因此,我们应该小心地在其上下文中解释下划线的含义。
我正在学习 Scala,有一个非常基本的问题。考虑以下两个使用占位符语法的表达式 -
// Syntax A
val fnA = (_: Int, _: Int) => _ / _
// Syntax B
val fnB = (_: Int) / (_: Int)
及其尝试的应用程序 -
// Syntax A
fnA(33, 3)
// Syntax B
fnB(33, 3)
在这两个中,只有 B 和 App(B) 是有效语法,我不确定为什么。如果编译器能够推断出 fnB
中的参数(以及应用它们的顺序),为什么它不能为 fnA
做到这一点?我提出问题的前提是 fnB
是 fnA
的 shorthand,而且我很确定这种推理存在缺陷。我只是不确定这个缺陷是什么。
箭头左边下划线的含义=>
(_: Int, _: Int) => ...
与中缀运算符周围的下划线的含义不同 /
(_: Int) / (_: Int)
前者的意思是
"We are defining a function that takes two arguments, however we will not use these arguments in the body of the function"
而后者是 shorthand 用于定义两个参数的函数
(x: Int, y: Int) => x / y
例如,
(_: Int, _: Int) => (_: Int) / (_: Int)
脱糖成
(a: Int, b: Int) => ((x: Int, y: Int) => x / y)
我们看到参数 a
和 b
没有在正文中使用,而正文恰好是另一个函数 ((x: Int, y: Int) => x / y)
.
Daniel将这两个意思记录为
_ + _ // Anonymous function placeholder parameter
_ => 5 // Discarded parameter
作为旁注,考虑类型级别的一些类似情况,涉及类型构造函数及其边界,其中下划线的含义取决于上下文
CC[_] <: Iterable[_]
就我个人而言,我的头脑欺骗我认为它等同于
CC[x] <: Iterable[x]
然而事实并非如此,<:
左边的下划线与右边
CC[x] <: Iterable[y] forSome {type y}
请注意 x
没有出现在 Iterable[y] forSome {type y}
中。 Adrian 在 Common Pitfalls:
...perhaps surprisingly,
CC[_] <: Traversable[_]
is not equivalent toCC[X] <: Traversable[X]
. The former expands toCC[X] <: Traversable[T] forSome {type T}
, whereT
is existentially bound and thus unrelated toX
.
并在 comment to type bounds on type constructor
comparing the level of types and values, it is quite unfortunate that the type-level underscore behaves differently from the value-level underscore. At the value level,
_ + _
indeed stands for(x, y) => x + y
, a function. As hinted at in my other comment, the type-level underscore is context-sensitive, and it never introduces a type-level function. It's either an anonymous type parameter definition or an anonymous existential. Neither of these have value-level equivalents.
因此,我们应该小心地在其上下文中解释下划线的含义。