在 Scala 中使用部分函数 - 它是如何工作的? [英] Using partial functions in Scala - how does it work?
问题描述
我是 Scala 的新手,我使用的是 2.9.1,我正在尝试了解如何使用部分函数.我对柯里化函数有基本的了解,我知道偏函数有点像柯里化函数,它们只有 2nary 或类似的函数.正如你所知道的,我对此有点不相信.
I'm new to Scala, I'm using 2.9.1, and I'm trying to get my head around how to use partial functions. I have a basic understanding of curried functions, and I know that partial functions are kind of like curried functions where they are only 2nary or some such. As you can tell I'm a bit green at this.
似乎在某些情况下,例如 XML 过滤,能够使用部分函数会非常有利,所以我希望能够更好地了解如何使用它们.
It does seem that in certain cases like XML filtering, being able to partial functions would be highly advantageous, so I'm hoping get a better understanding of how to use them.
我有一个使用 RewriteRule 结构的函数,但我需要它处理两个参数,而 RewriteRule 结构只需要一个参数,或者一个部分函数.我认为这是我认为有帮助的案例之一.
I have a function that uses the RewriteRule structure, but I need it to work with two arguments, whereas the RewriteRule structure only takes one, OR a partial function. I think this is one of the cases I'm thinking about it being helpful.
欢迎提供任何建议、链接、智慧之言等!
Any advice, links, words of wisdom etc. welcome!
到目前为止的答案都非常好,并且澄清了我的一些基本误解.我认为他们也解释了我在哪里挣扎 - 我认为发布一个更具体的新问题会有所帮助,所以我也会这样做.
The answers so far are excellent, and have cleared up a few fundamental misconceptions I have. I think they also explain where I'm struggling - I think maybe posting a new question being a bit more specific will help, so I'll do that too.
推荐答案
偏函数是一种仅对您可能传递给它的那些类型的值的子集有效的函数.例如:
A partial function is a function that is valid for only a subset of values of those types you might pass in to it. For example:
val root: PartialFunction[Double,Double] = {
case d if (d >= 0) => math.sqrt(d)
}
scala> root.isDefinedAt(-1)
res0: Boolean = false
scala> root(3)
res1: Double = 1.7320508075688772
当您知道如何检查函数是否已定义时,这很有用.收集,例如:
This is useful when you have something that knows how to check whether a function is defined or not. Collect, for instance:
scala> List(0.5, -0.2, 4).collect(root) // List of _only roots which are defined_
res2: List[Double] = List(0.7071067811865476, 2.0)
这不会帮助你将两个参数放在你真正想要的地方.
This is not going to help you place two arguments where you really want one.
相比之下,部分应用函数是一个函数,它的一些参数已经被填充.
In contrast, a partially applied function is a function where some of its arguments have already been filled in.
def add(i: Int, j: Int) = i + j
val add5 = add(_: Int,5)
现在你只需要一个参数——要加 5 的东西——而不是两个:
Now you only need one argument--the thing to add 5 to--instead of two:
scala> add5(2)
res3: Int = 7
你可以从这个例子中看到如何使用它.
You can see from this example how to use it.
但是如果你需要指定这两个参数,这个仍然不会这样做——比如你想使用map
,并且你需要给它一个参数的函数,但你希望它添加两个不同的东西.那么你可以
But if you need to specify those two arguments, this still won't do it--say you want to use map
, for instance, and you need to give it a function of one argument, but you want it to add two different things. Well, then you can
val addTupled = (add _).tupled
这将部分应用该函数(实际上,只需从该方法中创建一个函数,因为尚未填充任何内容),然后将单独的参数组合成一个元组.现在你可以在需要单个参数的地方使用它(假设类型正确):
which will partially apply the function (really, just create a function out of the method, since nothing has been filled in) and then combine the separate arguments into a tuple. Now you can use this in places that require a single argument (assuming that the type is correct):
scala> List((1,2), (4,5), (3,8)).map(addTupled)
res4: List[Int] = List(3, 9, 11)
相比之下,currying 再次不同;它转换为 (A,B) => 形式的函数.C
变成 A =>B=>C
.也就是说,给定一个有多个参数的函数,它将产生一个函数链,每个函数接受一个参数并返回一个较短的链(您可以将其视为一次部分应用一个参数).
In contrast, currying is different yet again; it turns functions of the form (A,B) => C
into A => B => C
. That is, given a function of multiple arguments, it will produce a chain of functions that each take one argument and return a chain one shorter (you can think of it as partially applying one argument at a time).
val addCurried = (add _).curried
scala> List(1,4,3).map(addCurried)
res5: List[Int => Int] = List(<function1>, <function1>, <function1>)
scala> res5.head(2) // is the first function, should add 1
res6: Int = 3
scala> res5.tail.head(5) // Second function should add 4
res7: Int = 9
scala> res5.last(8) // Third function should add 3
res8: Int = 11
这篇关于在 Scala 中使用部分函数 - 它是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!