Scala中的函数与方法

ear*_*las 46 scala

我正在观看Runar Bjarnason的初学者函数式编程,并在14:45他定义了一个方法:

def isDivisibleBy(k: Int): Int => Boolean = i => i % k == 0
Run Code Online (Sandbox Code Playgroud)

和功能:

val isEven = isDivisibleBy(2)
Run Code Online (Sandbox Code Playgroud)

定义isEven为函数而不是方法的优点和缺点是什么?

我已经阅读了Scala函数与方法以及Scala中方法和函数之间的区别,并且我理解语义差异,但我想知道在这种情况下是否有更深层次的原因为什么函数可能或可能不优于使用方法:

def isEven = isDivisibleBy(2)
Run Code Online (Sandbox Code Playgroud)

Deb*_*ski 64

在引擎盖下,功能和方法之间还存在其他差异.通常,普通方法比函数产生更少的开销(技术上是具有apply方法的对象).

但是,如果你试图不关心那些差异和思考def,val并且var作为具有不同语义的字段,那么它只是在def每次调用时val评估,而只评估一次.

因此,val isEven = isDivisibleBy(2)应该isDivisibleBy(2)在定义期间调用并分配结果isDivisibleBy(2).例如,它取代了kin

def isDivisibleBy(k: Int): Int => Boolean = i => i % k == 0
Run Code Online (Sandbox Code Playgroud)

with 2和赋予最终表达式的结果(在这种情况下只有一个表达式):

val isEven: Int => Boolean = i => i % 2 == 0
Run Code Online (Sandbox Code Playgroud)

def isEven 另一方面,没有这样的评估,每次都会调用isDivisibleBy(2).

这意味着,稍后,当您执行代码时,isEven(11)生成一个val

11 % 2 == 0
Run Code Online (Sandbox Code Playgroud)

如果是def,你会有

isDivisibleBy(2)(11)
Run Code Online (Sandbox Code Playgroud)

并且只有在评估之后isDivisibleBy你才会得到结果.

您可以添加一些调试代码isDivisibleBy以查看差异:

def isDivisibleBy(k: Int): Int => Boolean = {
  println("evaluating isDivisibleBy")
  i => i % k == 0
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*ral 20

我想在这里谈另一点.这定义isEven为一种方法:

def isEven = isDivisibleBy(2)
Run Code Online (Sandbox Code Playgroud)

这也定义isEven为一种方法:

val isEven = isDivisibleBy(2)
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,isEven都是一种方法,当被调用时,返回一个函数.

在第一种情况下,isDivisible(2)每次调用都会isEven被调用.例如,这会调用isDivisible(2)三次:

def isEven = isDivisibleBy(2)
List(1,2,3).filter(isEven)
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,isDivisible(2)调用一次(在构造时,或者在执行定义中的那一行时),并且每次isEven调用该值时都会检索该值.以下示例isDivisible(2)仅调用一次:

val isEven = isDivisibleBy(2)
List(1,2,3).filter(isEven)
Run Code Online (Sandbox Code Playgroud)

  • 据我所知,`val`没有定义方法.也许你的意思是它由于某种原因被转换为java字节代码中的方法(虽然我不明白为什么会这样).我认为它只是对函数对象的引用.毕竟你可以像其他对象一样传递引用. (3认同)

cou*_*ech 6

我觉得定义函数的主要职业isEvenval为展现给观众,该函数可以这样来定义.然后很明显,一个函数只是一个像scala中的其他东西一样的对象.但在非演示编程的世界中,没有必要将函数编写为vals.