在Scala中的两种方法:每个用例的用例是什么? [英] Two ways of currying in Scala; what's the use-case for each?

查看:96
本文介绍了在Scala中的两种方法:每个用例的用例是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我围绕 多个参数列表进行了讨论在我维护的Scala Style Guide中。我发现 currying 有两种方法,我想知道用例是什么: / p>

I am having a discussion around Multiple Parameter Lists in the Scala Style Guide I maintain. I've come to realize that there are two ways of currying, and I'm wondering what the use cases are:

def add(a:Int)(b:Int) = {a + b}
// Works
add(5)(6)
// Doesn't compile
val f = add(5)
// Works
val f = add(5)_
f(10) // yields 15

def add2(a:Int) = { b:Int => a + b }
// Works
add2(5)(6)
// Also works
val f = add2(5)
f(10) // Yields 15
// Doesn't compile
val f = add2(5)_

风格指南错误地暗示这些是相同的,当他们显然不是。该指南试图说明创建的curried函数,虽然第二种形式不是通过书的curry,它仍然非常类似于第一种形式(虽然可以说更容易使用,因为你不需要 _

The style guide incorrectly implies these are the same, when they are clearly not. The guide is trying to make a point about created curried functions, and, while the second form is not "by-the-book" currying, it's still very similar to the first form (though arguably easier to use because you don't need the _)

对于使用这些表单的人来说, ?

From those that use these forms, what's the consensus on when to use one form over the other?

推荐答案

多参数列表方法



h2>

具有多个参数部分的方法可以用于辅助局部类型推理,通过使用第一部分中的参数来推断类型参数,该类型参数将为随后的参数提供期望的类型部分。 foldLeft 是标准库中的规范示例。

Multiple Parameter List Methods

For Type Inference

Methods with multiple parameter sections can be used to assist local type inference, by using parameters in the first section to infer type arguments that will provide an expected type for an argument in the subsequent section. foldLeft in the standard library is the canonical example of this.

def foldLeft[B](z: B)(op: (B, A) => B): B

List("").foldLeft(0)(_ + _.length)

如果这写为:

def foldLeft[B](z: B, op: (B, A) => B): B

必须提供更明确的类型:

One would have to provide more explicit types:

List("").foldLeft(0, (b: Int, a: String) => a + b.length)
List("").foldLeft[Int](0, _ + _.length)



对于流利的API



是创建一个看起来像语言构造的API。调用者可以使用大括号而不是括号。

For fluent API

Another use for multiple parameter section methods is to create an API that looks like a language construct. The caller can use braces instead of parentheses.

def loop[A](n: Int)(body: => A): Unit = (0 until n) foreach (n => body)

loop(2) {
   println("hello!")
}

将N个参数列表应用于具有M个参数节的方法,其中N < M,可以使用 _ 显式地转换为函数,或隐式地转换为预期类型 FunctionN [..] 。这是一个安全功能,请参阅Scala参考中的Scala 2.0的更改注释。

Application of N argument lists to method with M parameter sections, where N < M, can be converted to a function explicitly with a _, or implicitly, with an expected type of FunctionN[..]. This is a safety feature, see the change notes for Scala 2.0, in the Scala References, for an background.

Curried函数(或简单地说,返回函数的函数)更容易应用于N个参数列表。

Curried functions (or simply, functions that return functions) more easily be applied to N argument lists.

val f = (a: Int) => (b: Int) => (c: Int) => a + b + c
val g = f(1)(2)

方便有时是值得的。注意,函数不能是类型参数,所以在某些情况下需要一个方法。

This minor convenience is sometimes worthwhile. Note that functions can't be type parametric though, so in some cases a method is required.

你的第二个例子是混合:一个参数节方法返回函数。

Your second example is a hybrid: a one parameter section method that returns a function.

curried函数在哪里有用?这是一个模式,一直出现:

Where else are curried functions useful? Here's a pattern that comes up all the time:

def v(t: Double, k: Double): Double = {
   // expensive computation based only on t
   val ft = f(t)

   g(ft, k)
}

v(1, 1); v(1, 2);

如何共享结果 f(t)?一个常见的解决方案是提供 v 的向量化版本:

How can we share the result f(t)? A common solution is to provide a vectorized version of v:

def v(t: Double, ks: Seq[Double]: Seq[Double] = {
   val ft = f(t)
   ks map {k => g(ft, k)}
}

丑陋我们纠缠不相关的问题 - 计算 g (f(t),k)并映射到 ks 的序列。

Ugly! We've entangled unrelated concerns -- calculating g(f(t), k) and mapping over a sequence of ks.

val v = { (t: Double) =>
   val ft = f(t)
   (k: Double) => g(ft, k)       
}
val t = 1
val ks = Seq(1, 2)
val vs = ks map (v(t))

我们还可以使用一个返回一个函数的方法,在这种情况下它更易读:

We could also use a method that returns a function. In this case its a bit more readable:

def v(t:Double): Double => Double = {
   val ft = f(t)
   (k: Double) => g(ft, k)       
}

但是如果我们尝试与具有多个参数部分的方法相同,我们遇到:

But if we try to do the same with a method with multiple parameter sections, we get stuck:

def v(t: Double)(k: Double): Double = {
                ^
                `-- Can't insert computation here!
}

这篇关于在Scala中的两种方法:每个用例的用例是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆