Scala 中的函数与方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4839537/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:45:59  来源:igfitidea点击:

Functions vs methods in Scala

scala

提问by earldouglas

I am watching Runar Bjarnason present Functional Programming for Beginners, and at 14:45 he defines a method:

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

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

and a function:

和一个功能:

val isEven = isDivisibleBy(2)

What are the pros and cons of defining isEvenas a function rather than a method?

定义isEven为函数而不是方法的利弊是什么?

I have read Scala Functions vs Methodsas well as Difference between method and function in Scala, and I understand the semantic differences, but I wonder if there's some deeper reason in this case why a function might or might not be preferable to using a method:

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

def isEven = isDivisibleBy(2)

回答by Debilski

Under the hood, there are other differences between functions and methods. Generally, a plain method generated less overhead than a function (which technically is an object with an applymethod).

在幕后,函数和方法之间还有其他区别。通常,普通方法比函数(从技术上讲是具有apply方法的对象)产生的开销更少。

However, if you try not to care about those differences and think of def, valand varas fieldswith different semantics, then it's simply that defevaluates every time it gets called while valevaluates only once.

但是,如果您尽量不关心这些差异并将def,valvar视为具有不同语义的字段,那么它只是在def每次被调用时val进行评估,而仅评估一次。

So, a val isEven = isDivisibleBy(2)should call isDivisibleBy(2)during its definition and assign the result of isDivisibleBy(2). E.g. it replaces the kin

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

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

with 2and assigns the result of the final expression (in this case there is only one expression):

with2并分配最终表达式的结果(在这种情况下只有一个表达式):

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

def isEvenon the other hand does no such evaluation and results in a call to isDivisibleBy(2) every time.

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

That means, later, when you execute the code, isEven(11)generates in case of a val

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

11 % 2 == 0

and in case of a def, you'll have

在 a 的情况下def,您将拥有

isDivisibleBy(2)(11)

and only after evaluating isDivisibleByyou'll get the result.

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

You can add some debug code to isDivisibleByto see the difference:

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

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

回答by Daniel C. Sobral

I'd like to address another point here. This defines isEvenas a method:

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

def isEven = isDivisibleBy(2)

And this defines isEvenas a method as well:

这也定义isEven为一种方法:

val isEven = isDivisibleBy(2)

In both cases, isEvenis a method which, when called, return a function.

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

In the first case, isDivisible(2)is called every time isEvenis called. For example, this calls isDivisible(2)three times:

在第一种情况下,isDivisible(2)每次调用时isEven都会调用。例如,这会调用isDivisible(2)3 次:

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

In the second case, isDivisible(2)is called once (at construction time, or when that line in a definition is executed), and that value is retrieved every time isEvenis called. The following example calls isDivisible(2)one time only:

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

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

回答by coubeatczech

I think that the main pro of defining the function isEvenas valis to show to audience that the function can be defined this way. Then it's clear, that a function is just an object like everything else in scala. But in the world of non-demonstrating programming, there's no need to write functions as vals.

我觉得定义函数的主要职业isEvenval为展现给观众,该函数可以这样来定义。那么很明显,函数只是一个对象,就像 Scala 中的其他一切一样。但是在非演示编程的世界里,没有必要把函数写成vals。

回答by Esko Luontola

The method def isDivisibleBy(k: Int): Int => Booleanreturns a function which takes an Int (i) as parameter and returns a Boolean (i % k == 0).

该方法def isDivisibleBy(k: Int): Int => Boolean返回一个函数,该函数接受一个 Int ( i) 作为参数并返回一个 Boolean ( i % k == 0)。

val isEven = isDivisibleBy(2)on the other hand is a field into which the function returned by isDivisibleBy(2)is stored. If you use definstead of valthen the isDivisibleBy method would be called every time the isEven method is called, but now it's called only once and the result is stored in the field.

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

You could achieve the same result by writing def isEven(i: Int): Boolean = i % 2 == 0

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

I think the point of the example is that you can have functions which return other functions, and you can store the functions as objects, and then call them as if they were traditionally defined methods. The above code is also quite similar to currying, so that might also be one thing demonstrated by the example (although it doesn't use Scala's syntax for currying).

我认为这个例子的重点是你可以有返回其他函数的函数,你可以将函数存储为对象,然后像传统定义的方法一样调用它们。上面的代码也与currying非常相似,因此这也可能是示例演示的一件事(尽管它没有使用Scala 的 currying 语法)。