Scala 中的函数与方法

发布于 2024-10-14 19:44:35 字数 690 浏览 0 评论 0原文

我正在观看 Runar Bjarnason 演讲《面向初学者的函数式编程》,他在 14:45 定义了方法:

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

和函数:

val isEven = isDivisibleBy(2)

将 isEven 定义为函数而不是方法有何优缺点?

我也读过 Scala 函数与方法作为 Scala 中方法和函数之间的差异,我理解语义差异,但我想知道在这种情况下是否有一些更深层次的原因,为什么函数可能比使用方法更可取:

def isEven = isDivisibleBy(2)

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

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 isEven as a function rather than a method?

I have read Scala Functions vs Methods as 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:

def isEven = isDivisibleBy(2)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

九八野马 2024-10-21 19:44:35

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

但是,如果您尝试不关心这些差异,并将 defvalvar 视为字段,不同的语义,那么很简单, def 每次被调用时都会计算,而 val 仅计算一次。

因此,val isEven = isDivisibleBy(2) 应在定义期间调用 isDivisibleBy(2) 并分配 isDivisibleBy(2) 的结果。例如,它将 k 替换为

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

2 并分配最终表达式的结果(在本例中只有一个表达式):

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

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

这意味着,稍后,当您执行代码时,如果是 val,则生成 isEven(11)

11 % 2 == 0

;如果是 def,则生成 只有在评估 isDivisibleBy 之后你才会

isDivisibleBy(2)(11)

得到结果。

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

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

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 apply method).

However, if you try not to care about those differences and think of def, val and var as fields with different semantics, then it’s simply that def evaluates every time it gets called while val evaluates only once.

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 k in

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

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

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

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

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

11 % 2 == 0

and in case of a def, you’ll have

isDivisibleBy(2)(11)

and only after evaluating isDivisibleBy you’ll get the result.

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

def isDivisibleBy(k: Int): Int => Boolean = {
  println("evaluating isDivisibleBy")
  i => i % k == 0
}
仅此而已 2024-10-21 19:44:35

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

def isEven = isDivisibleBy(2)

这也将 isEven 定义为一种方法:

val isEven = isDivisibleBy(2)

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

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

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

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

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

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

def isEven = isDivisibleBy(2)

And this defines isEven as a method as well:

val isEven = isDivisibleBy(2)

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

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

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 isEven is called. The following example calls isDivisible(2) one time only:

val isEven = isDivisibleBy(2)
List(1,2,3).filter(isEven)
冰雪梦之恋 2024-10-21 19:44:35

我认为将函数 isEven 定义为 val 的主要优点是向观众展示可以通过这种方式定义函数。那么很明显,函数只是一个对象,就像 scala 中的其他所有东西一样。但在非演示编程的世界中,没有必要将函数编写为 val

I think that the main pro of defining the function isEven as val is 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.

一抹苦笑 2024-10-21 19:44:35

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

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

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

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

The method def isDivisibleBy(k: Int): Int => Boolean returns a function which takes an Int (i) as parameter and returns a 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 def instead of val then 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.

You could achieve the same result by writing 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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文