Scala Function.tupled vs f.tupled

pat*_*rit 5 functional-programming scala tuples flatmap

我有以下Scala代码:

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)}
Run Code Online (Sandbox Code Playgroud)

但是,最后一行太冗长,所以我尝试了所有这些并且没有一个编译.

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)

Ben*_*ich 2

您只能flatMap在返回时使用Options,因为隐式 存在从OptionIterable的隐式转换option2IterableflatMap您的方法需要一个从到 的List[(Int, Int)]函数。编译器无法将隐式转换识别为此处的可行选项。您可以通过显式指定通用参数来帮助编译器:(Int, Int)GenTraversableOnce[Int]

import Function._
data.flatMap[String, Iterable[String]](tupled(f))
//Or
data flatMap tupled[Int, Int, Iterable[String]](f)
Run Code Online (Sandbox Code Playgroud)

相同想法的其他表述也可能允许编译器选择正确的类型和隐式,即使没有显式泛型:

data flatMap (tupled(f _)(_))
data.flatMap (f.tupled(f _)(_))
Run Code Online (Sandbox Code Playgroud)

最后,您可能还想collectunlift此处一起使用,这也是表达此逻辑的好方法:

data collect unlift((f _).tupled)
data collect unlift(tupled(f))
Run Code Online (Sandbox Code Playgroud)

Function.unlift接受一个返回 an 的方法Option,并将其转换为与PartialFunction原始函数返回的位置不匹配的位置Nonecollect接受一个偏函数并收集偏函数的值(如果它在每个元素上定义)。