Freewind @ Thoughtworks scala java javascript dart 工具 编程实践 月结 math python english [comments admin] [feed]

(2011-09-13) 关于flatMap的用法

广告: 云梯:翻墙vpn (省10元) 土行孙:科研用户翻墙http proxy (有优惠)

我将从下面这段简单的代码,引申出不少问题:

val list = List(1,2,3)

val result = list map ( _+1 )
println(result)
// -> List(2,3,4)` <br /><p>1. 如果把map改为flatMap,则: <br /><pre class="csharpcode">list flatMap ( _+1 )`

编译出错,为什么?


原因是flatMap的定义如下:

flatMap [B](f : (A) => Iterable[B]) : List[B]```

可见,flatMap的参数必须是一个返回Iterable的函数。

所以,如果把代码改成 list flatMap ( List(_) ),即可得到正确答案

  1. 为什么list flatMap ( List(_+1) ) 编译出错呢?

出错信息为:

:7: error: missing parameter type for expanded function ((x$1) => x$1.$plus(1))

       list flatMap ( List(_+1) )

说是不知道参数类型。

为什么List()可以而List(+1)不可以,是因为List()不需要知道参数类型,而List(+1),调用了+函数,所以需要知道类型,而我们没有提供。所以应该改成:

list flatMap ( it => List(it + 1) )```

这样,scala就能推断出it的类型了。

  1. 既然在2中,scala无法推荐_的类型,那我们手动设定类型,如下:
    list flatMap ( List( (:Int) + 1 ))`
    <br /><p>应该可以了吧。可惜编译还是出错:
    <br /><pre class="csharpcode">scala> list flatMap ( List( (_:Int) +1 ))
    <br /><console>:7: error: type mismatch;
    <br />found   : List[(Int) => Int]
    <br />required: (Int) => Traversable[?]
    <br />list flatMap ( List( (_:Int) +1 ))`
    

    难道 List( (:Int) + 1 ) 不是一个返回List[Int]的函数吗?

测试:

scala> def g = List ( (_:Int) + 1)

g: List[(Int) => Int]```

原来它是List[(Int)=>Int],为什么不是(Int)=>List[Int]呢?

对最后一个问题,还是想得不太明白。比如说以下这几个例子:

def f = 1 + (:Int)

def f = (
:Int) + 1
def f = 1 to (:Int) +1
def f = 1 to 1 + (
:Int) + 2```

下面这个就不行:

def f = 1 to ( 1 + (_:Int) )```

而def f = List((_:Int)+1)实际上得到的是一个List,里面有一个函数元素。

总之我最后的感觉就是,只在很简单的情况下,使用_,否则还是乖乖的写全,比如:

def f = { x:Int => List(x+1)}```

comments powered by Disqus