理解 Scala 的下划线和星号魔法

san*_*206 5 scala

我正在阅读和练习 Scala,我发现了这个博客

阅读关于组合谓词的部分我看到了这段代码

def complement[A](predicate: A => Boolean) = (a: A) => !predicate(a)

def any[A](predicates: (A => Boolean)*): A => Boolean =
  a => predicates.exists(pred => pred(a))

def none[A](predicates: (A => Boolean)*) = complement(any(predicates: _*))

def every[A](predicates: (A => Boolean)*) = none(predicates.view.map(complement(_)): _*)
Run Code Online (Sandbox Code Playgroud)

我有 python 背景,想了解下划线和星号的含义,单独或一起使用时,理解它很奇怪,特别是对于noneevery定义。

rad*_*scu 7

SomeExpression* 表示“0 个或多个元素的序列”

_ 可用于指定“我们不需要命名的参数”

参数 tonone是“包含 0 个或多个元素的谓词序列”,而“谓词”是一个接受A并返回的函数Boolean

to 的参数any是一个数组,所以传入的值必须转换为数组,由_*

to 的参数every是一个数组,它的名字并不重要,因为只有一个。它可以传递给complement_


eph*_*ent 5

def any[A](predicates: (A => Boolean)*)
Run Code Online (Sandbox Code Playgroud)

产生相同的功能

def any[A](predicates: Seq[A => Boolean])
Run Code Online (Sandbox Code Playgroud)

除了您可以调用它any(a, b, c)而不是any(List(a, b, c))(编译器转换调用站点)。

鉴于这any是一个可变参数函数,调用any(a)进入anywith的主体predicates = List(a)。但是如果a已经是一个序列,这不是你想要的。这就是: _*符号的用途:它告诉 Scala 编译器“将其视为可变参数的参数序列”。

这大致相当于用 Python 编写,

def complement(predicate):
    return lambda a: not predicate(a)

def any_(*predicates):
    return lambda a: any(pred(a) for pred in predicates)

def none(*predicates):
    return complement(any_(*predicates))

def every(*predicates):
    return none(*map(complement, predicates))
Run Code Online (Sandbox Code Playgroud)