3

我正在学习 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我很确定这种推理存在缺陷。我只是不确定缺陷是什么。

4

1 回答 1

5

箭头左边下划线的含义=>

(_: Int, _: Int) => ...

与中缀运算符周围的下划线含义不同/

(_: Int) / (_: Int) 

前者的意思是

“我们正在定义一个带有两个参数的函数,但是我们不会在函数体中使用这些参数”

而后者是定义两个参数的函数的简写

(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)

丹尼尔将这两种含义记录为

_ + _             // 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下记录了这一点:

...也许令人惊讶的CC[_] <: Traversable[_]是,不等于 CC[X] <: Traversable[X]. 前者扩展为CC[X] <: Traversable[T] forSome {type T},其中T存在存在约束,因此与 无关 X

并在对类型构造函数的类型边界的评论

比较类型和值的级别,很不幸的是,类型级别的下划线与值级别的下划线表现不同。在价值层面,_ + _确实代表(x, y) => x + y一个函数。正如我在其他评论中所暗示的那样,类型级下划线是上下文相关的,它从不引入类型级函数。它要么是匿名类型参数定义,要么是匿名存在。这些都没有价值级别的等价物。

因此,我们应该小心地在其上下文中解释下划线的含义。

于 2020-01-11T21:36:01.503 回答