2017-02-03 61 views
0

我正在阅读和练习斯卡拉,我发现这个blog了解斯卡拉的下划线和星号魔法

阅读有关创作谓词我看到这段代码的一部分

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(_)): _*) 

我有一个Python的背景和想了解下划线和星号的含义单独或一起使用时,这是相当奇怪的是有意义的,特别对于的定义。

+0

'_'一般是指“东西的名字我不关心”。你可能想要探索这个答案的所有可能的含义:http://stackoverflow.com/a/8001065/3314107 – stefanobaghino

回答

1

SomeExpression*意味着

_可以用“0个或多个元素的序列”指定

none的参数是“谓词的序列“我们并不需要命名的参数”包含0个或更多元素“,而”谓词“是一个函数,它需要A并返回Boolean

any的参数是一个数组,所以传入的值必须被转换成一个阵列,其由_*

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

1
def any[A](predicates: (A => Boolean)*) 

产生相同的功能

def any[A](predicates: Seq[A => Boolean]) 

除了你可以这样调用它any(a, b, c)代替any(List(a, b, c))(编译变换调用点)。

鉴于any是可变参数函数,调用any(a)进入any的主体与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)) 
+1

'Seq',而不是'Array'。 –

+0

@AlexeyRomanov对,我的错误。 Array可以通过'@ varargs'注释来实现Java的可比性,但是它对于普通的Scala代码来说是'Seq'。 – ephemient

+0

** **每个**的定义在同一行中使用'_'和'_ *'是什么意思? ** complement **只接受一个谓词,但在这种情况下不是'_'是一个Seq,这就是为什么后面可以使用'_ *'?最后一行是最难理解的。 –