函数与Scala中的方法

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

def isDivisibleBy(k: Int): Int => Boolean = i => i % k == 0 

和一个function:

 val isEven = isDivisibleBy(2) 

定义isEven作为一个函数而不是一个方法有什么好处和坏处?

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

 def isEven = isDivisibleBy(2) 

在引擎盖下,function和方法还有其他的区别。 一般来说,一个普通的方法产生的开销比一个函数(技术上是一个具有apply方法的对象)less。

然而,如果你不关心这些差异,并把defvalvar当作不同语义的字段 ,那么简单地说就是def每次被调用的时候评估,而val只评估一次。

因此, val isEven = isDivisibleBy(2)应该在其定义期间调用isDivisibleBy(2)并指定isDivisibleBy(2)的结果。 例如,它取代了k

 def isDivisibleBy(k: Int): Int => Boolean = i => i % k == 0 

2并分配最终expression式的结果(在这种情况下,只有一个expression式):

 val isEven: Int => Boolean = i => i % 2 == 0 

def isEven另一方面没有这样的评价,并且每次都会调用isDivisibleBy(2)。

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

 11 % 2 == 0 

如果是def ,你会有的

 isDivisibleBy(2)(11) 

只有在评估isDivisibleBy你会得到结果。

你可以添加一些debugging代码到isDivisibleBy看看不同之处:

 def isDivisibleBy(k: Int): Int => Boolean = { println("evaluating isDivisibleBy") i => i % k == 0 } 

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

 def isEven = isDivisibleBy(2) 

而且这个定义isEven一个方法:

 val isEven = isDivisibleBy(2) 

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

在第一种情况下, isDivisible(2)每次调用isEven被调用。 例如,这个调用是isDivisible(2)三次:

 def isEven = isDivisibleBy(2) List(1,2,3).filter(isEven) 

在第二种情况下, isDivisible(2)被调用一次(在构build时,或者当定义中的行被执行时),并且每次调用isEvenisEven检索该值。 下面的例子只调用isDivisible(2)

 val isEven = isDivisibleBy(2) List(1,2,3).filter(isEven) 

我认为,定义函数的主要方法是将函数作为val来向观众展示函数可以这样定义。 那么很明显,函数就像scala中的其他所有东西一样。 但在非演示编程的世界中,不需要写入函数作为val

方法def isDivisibleBy(k: Int): Int => Boolean返回一个函数,它接受一个I​​nt( i )作为参数并返回一个布尔值( i % k == 0 )。

val isEven = isDivisibleBy(2)另一方面是存储由isDivisibleBy(2)返回的函数的字段。 如果使用def而不是val那么每次调用isEven方法时都会调用isDivisibleBy方法,但现在只调用一次,结果存储在字段中。

您可以通过编写def isEven(i: Int): Boolean = i % 2 == 0来实现相同的结果def isEven(i: Int): Boolean = i % 2 == 0

我认为这个例子的意义在于,你可以有返回其他函数的函数,并且可以把函数存储为对象,然后像调用传统的方法一样调用它们。 上面的代码也和currying非常相似,所以这也可能是这个例子演示的一个东西(尽pipe它没有使用Scala的currying语法 )。