Scala之偏函数Partial Function

http://blog.csdn.net/bluishglc/article/details/50995939

```scala> List(1,2,3) map {case i:Int=>i+1}
res1: List[Int] = List(2, 3, 4)```

```scala> List(1,2,3) map {(i:Int)=>i+1}
res2: List[Int] = List(2, 3, 4)```

scala In Programming》一书对独立的case语句作为匿名函数（函数字面量）有权威的解释：

Essentially, a case sequence is a function literal, only more general. Instead of having a single entry point and list of parameters, a case sequence has multiple entry points, each with their own list of parameters. Each case is an entry point to the function, and the parameters are specified with the pattern.

```List(1, 3, 5, "seven") map { case i: Int => i + 1 } // won't work
// scala.MatchError: seven (of class java.lang.String)
List(1, 3, 5, "seven") collect { case i: Int => i + 1 }
// verify
assert(List(2, 4, 6) == (List(1, 3, 5, "seven") collect { case i: Int => i + 1 }))```

```scala> val inc = new PartialFunction[Any, Int] {
| def apply(any: Any) = any.asInstanceOf[Int]+1
| def isDefinedAt(any: Any) = if (any.isInstanceOf[Int]) true else false
| }
inc: PartialFunction[Any,Int] = <function1>

scala> List(1, 3, 5, "seven") collect inc
res4: List[Int] = List(2, 4, 6)```

PartialFunction特质规定了两个要实现的方法：apply和isDefinedAt，isDefinedAt用来告知调用方这个偏函数接受参数的范围，可以是类型也可以是值，在我们这个例子中我们要求这个inc函数只处理Int型的数据。apply方法用来描述对已接受的值如何处理，在我们这个例子中，我们只是简单的把值+1，注意，非Int型的值已被isDefinedAt方法过滤掉了，所以不用担心类型转换的问题。 上面这个例子写起来真得非常笨拙，和前面的case语句方式比起来真是差太多了。这个例子从反面展示了：通过case语句组合去是实现一个偏函数是多么简洁。实际上case语句组合与偏函数的用意是高度贴合的，所以使用case语句组合是最简单明智的选择，同样是上面的inc函数，换成case去写如下：

```scala> def inc: PartialFunction[Any, Int] =
| { case i: Int => i + 1 }
inc: PartialFunction[Any,Int]

scala> List(1, 3, 5, "seven") collect inc
res5: List[Int] = List(2, 4, 6)```

Case语句是如何被编译成偏函数的 关于这个问题在《Programming In Scala》中有较为详细的解释。对于这样一个使用case写在的偏函数：

```val second: PartialFunction[List[Int],Int] = {
case x :: y :: _ => y
}```

In fact, such an expression gets ranslated by the Scala compiler to a partial function by translating the patterns twice—once for the implementation of the real function, and once to test whether the function is defined or not. For instance, the function literal { case x :: y :: _ => y }above gets translated to the following partialfunction value:

```new PartialFunction[List[Int], Int] {
def apply(xs: List[Int]) = xs match {
case x :: y :: _ => y
}
def isDefinedAt(xs: List[Int]) = xs match {
case x :: y :: _ => true
case _ => false
}
}```

```scala> var inc = (x: Int) => x + 1
inc: Int => Int = <function1>

scala> inc.isInstanceOf[Function1[Int,Int]]
res0: Boolean = true```

494 篇文章48 人订阅

0 条评论

相关文章

2906

ruby学习笔记(6)-Array的使用

ruby的数组基本使用，跟c#中的数组比起来，最不习惯的区别在于允许负索引（跟javascript到有几分相似） arr=[3,4,5,6,7,8,9] pu...

1905

2376

1966

1783

为什么构造函数不能为虚函数

1、从使用角度         虚函数主要用于在信息不全的情况下，能使重载的函数得到对应的调用。构造函数本身就是要初始化实例，那使用虚函数也没有实际意义呀。所以...

2049

812

1255

1898