2015-04-30 33 views
5

我有以下Scala代码:斯卡拉Function.tupled VS f.tupled

def f(x: Int, y: Int): Option[String] = x*y match { 
    case 0 => None 
    case n => Some(n.toString) 
} 

val data = List((0, 1), (1, 0), (2, 3), (4, -1)) 

data flatMap {case (x, y) => f(x, y)} 

但是,最后一行是太冗长,所以我尝试了所有的这些,没有他们的编译。

data flatMap f

data flatMap f.tupled

data flatMap Function.tupled(f)

data flatMap {f _}

data flatMap (f _).tupled

data flatMap f(_)

我在做什么错了?唯一可行的事情是这样的:

(data map Function.tupled(f)).flatten

我想到了一个map其次flatten总是可以通过flatMap所取代,不过虽然上面的行编译,这并不:

data flatMap Function.tupled(f)

回答

2

当您返回Options时,您只能使用flatMap,因为隐含的从OptionIterable的转换由隐含的option2Iterable 。您的List[(Int, Int)]上的方法flatMap需要从(Int, Int)GenTraversableOnce[Int]的功能。编译器无法将隐式转换标识为可行的选项。你可以帮助编译器一起通过明确的通用参数:

import Function._ 
data.flatMap[String, Iterable[String]](tupled(f)) 
//Or 
data flatMap tupled[Int, Int, Iterable[String]](f) 

同样的想法的其他制剂也可以让编译器来选择正确的类型和implicits,即使没有明确的仿制药:

data flatMap (tupled(f _)(_)) 
data.flatMap (f.tupled(f _)(_)) 

最后,你可能还需要与collectunlift这里一起玩,它可以表达这种逻辑,以及一个不错的方式:

data collect unlift((f _).tupled) 
data collect unlift(tupled(f)) 

Function.unlift采用返回Option的方法,并将其变为PartialFunction,该方法与原函数返回None的位置不匹配。 collect接受部分函数并收集部分函数的值,如果它在每个元素处定义的话。

+0

'数据收集unlift(tupled(f))'在这里更有意义IMO。谢谢! – pathikrit

0

为进一步非常有用的答案上面,如果你使用collect,你就可以走了一步,并重写你的函数f的部分功能:

val f: PartialFunction[(Int, Int), String] = { 
    case (x, y) if x*y != 0 => (x*y).toString 
} 

然后,您可以这样处理你的数据:

data collect f 

通常,任何返回选项的函数都可以重写为部分函数。在某些情况下,由于您的表达式数量较少,因此不需要在Some()中包含返回值。