5

私は次の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)}

しかし、最後の行は冗長すぎるため、これらすべてを試しましたが、どれもコンパイルされません。

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に続くaflattenは常に に置き換えることができると思いましたflatMapが、上記の行はコンパイルされますが、これはそうではありません。

data flatMap Function.tupled(f)

4

2 に答える 2

2

暗黙的な からへの暗黙的な変換があるためflatMap、戻るときにのみ使用できます。あなたのメソッドは からへの関数を期待しています。コンパイラは、ここでその暗黙的な変換を実行可能なオプションとして識別するのに問題があります。汎用パラメーターを明示的に指定することで、コンパイラーを支援できます。OptionsOptionIterableoption2IterableflatMapList[(Int, Int)](Int, Int)GenTraversableOnce[Int]

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

同じアイデアの他の定式化により、明示的なジェネリックがなくても、コンパイラーが正しい型と暗黙を選択できるようになる場合もあります。

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

最後に、ここでcollect一緒に遊ぶunliftこともできます。これは、このロジックを表現する良い方法でもあります。

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

Function.unliftを返すメソッドを取り、元の関数が返す場所と一致しないOptionに変換します。 部分関数を取り、各要素で定義されている場合は部分関数の値を収集します。 PartialFunctionNonecollect

于 2015-04-30T01:26:17.833 に答える
0

上記の非常に役立つ回答をさらに進めるために、 を使用する場合はcollect、さらに一歩進んで関数 f を部分関数として書き直すことができます。

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

その後、次のようにデータを処理できます。

data collect f

一般に、Option を返す関数は、部分関数として書き直すことができます。場合によっては、case式が少なくなり、戻り値を でラップする必要がないため、これがうまくいきますSome()

于 2017-02-01T19:59:59.330 に答える