在Scala中使用部分函数 - 它是如何工作的? [英] Using partial functions in Scala - how does it work?

查看:134
本文介绍了在Scala中使用部分函数 - 它是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Scala的新手,我正在使用2.9.1,并且正在努力探索如何使用部分函数。我对咖喱函数有一个基本的了解,并且我知道局部函数就像咖喱函数,它们只是二元函数或其他函数。正如你所看到的,我对此有点绿。



似乎在某些情况下,比如XML过滤,能够部分功能会非常有利,所以我希望能够更好地理解如何使用它们。



我有一个使用RewriteRule结构的函数,但我需要它使用两个参数,而RewriteRule结构只需要一个,或者一个部分函数。我认为这是我认为它有帮助的一种情况。



任何建议,链接,智慧等字样都欢迎!



到目前为止的答案非常好,并且已经澄清了我的一些基本误解。我想他们也会解释我在哪里挣扎 - 我想可能发布一个更具体的新问题会有所帮助,所以我也会这样做。

解决方案

部分函数是一个函数,它只对您可能传入的那些类型的值的子集有效。例如:

  val root:PartialFunction [Double,Double] = {
case d if(d> = 0)=> math.sqrt(d)
}

scala> root.isDefinedAt(-1)
res0:布尔值= false

scala> root(3)
res1:Double = 1.7320508075688772

知道如何检查函数是否被定义。收集,例如:

  scala> List(0.5,-0.2,4).collect(root)//定义的唯一根的列表_ 
res2:List [Double] = List(0.7071067811865476,2.0)



这是不是可以帮助您在两个真正想要的地方放置两个参数。



相比之下,一个部分应用的函数是一个函数,其中一些参数已经被填充了。

 def add(i:Int,j:Int)= i + j 
val add5 = add(_:Int,5)

现在你只需要一个参数 - 将5添加到 - 而不是两个:

 阶> add5(2)
res3:Int = 7

你可以从这个例子中看到如何使用它。



但是如果你需要指定这两个参数,这个仍然不会这么做 - 比如说你想使用<例如,code> map ,并且您需要给它一个参数的函数,但是您希望它添加两个不同的东西。那么,你可以

  val addTupled =(add _)。tupled 

它将部分应用该函数(实际上,只是从方法中创建一个函数,因为没有填充任何内容),然后将单独的参数组合到一个元组。现在,您可以在需要单个参数的地方使用它(假设类型正确):

  scala> List((1,2),(4,5),(3,8))。map(addTupled)
res4:List [Int] = List(3,9,11)

相比之下, 又是不同的;它变成(A,B)=> C 转换为 A => B => ç。也就是说,给定多个参数的函数,它会产生一个函数链,每个函数都带一个参数并返回一个更短的链(可以把它看作是一次部分应用一个参数)。

  val addCurried =(add _)。curried 

scala> List(1,4,3).map(addCurried)
res5:List [Int => Int] = List(< function1>,< function1>,< function1>)

scala> res5.head(2)//是第一个函数,应该添加1
res6:Int = 3

scala> res5.tail.head(5)//第二个函数应该添加4
res7:Int = 9

scala> res5.last(8)//第三个函数应该添加3
res8:Int = 11


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.

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.

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)

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.

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)

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屋!

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