2

ドメインが重複している可能性のある部分関数がいくつかあるとします。

val funcs: Seq[PartialFunction[Any, Int]] = Vector(
{ case i: Int if i % 2 == 0 => i*2 }
,
{ case i: Int if i % 2 == 1 => i*3 }
,
{ case i: Int if i % 6 == 0 => i*5 }
)

それらを値に適用し、その値で定義されている結果を収集したいと考えています。これを使用するエレガントな方法があると思いcollectましたが、私ができる最善の方法は

val num = 66
funcs.collect { case func if func.isDefinedAt(num) => func(num) }
// or 
funcs.filter(_.isDefinedAt(num)).map(_(num))

これはきれいに見えません。ビルトイン ケース メカニズムを使用して定義性をテストし、同時に評価する方法はありますか?

4

2 に答える 2

8

部分関数には、PF が定義されている場合と定義されていない場合のliftメソッドがあります。また、 を使用すると、本質的に s を無視して、値のみを取得できます。Some(res)NoneflatMapNoneSome

funcs.flatMap { func => func.lift(num) }

または、そのようなものを楽しむ場合は圧縮します:

funcs.flatMap(_.lift(num))
于 2015-06-08T19:19:40.420 に答える
1

定義性をテストし、同時に評価する

それはapplyOrElseです。二重評価を回避するために使用されcollectます。lift

この再帰的なバージョンは、次の関数を適用して結果を構築するために使用するか、続行して残りの結果を構築することを示しています。

def f(ff: List[PartialFunction[Any, Int]]): List[Int] = ff match {
  case hd :: tail => hd.applyOrElse(num, (_: Any) => return f(tail)) :: f(tail)
  case _ => Nil
}

returnScalaで使ったのは初めてです。索引で調べる必要がありました。

この手動の構築により、 でのオブジェクトの作成とLifted、 のOption適応が回避されOptionます。

scala> :pa
// Entering paste mode (ctrl-D to finish)

val funcs: Seq[PartialFunction[Any, Int]] = Vector(
{ case i: Int if i % 2 == 0 => i*2 }
,
{ case i: Int if i % 2 == 1 => i*3 }
,
{ case i: Int if i % 6 == 0 => i*5 }
)
val num = 66

def f(ff: List[PartialFunction[Any, Int]]): List[Int] = ff match {
  case hd :: tail => hd.applyOrElse(num, (_: Any) => return f(tail)) :: f(tail)
  case _ => Nil
}

// Exiting paste mode, now interpreting.

funcs: Seq[PartialFunction[Any,Int]] = Vector(<function1>, <function1>, <function1>)
num: Int = 66
f: (ff: List[PartialFunction[Any,Int]])List[Int]

scala> f(funcs.toList)
res0: List[Int] = List(132, 330)

scala> funcs flatMap (_ lift num)
res1: Seq[Int] = Vector(132, 330)

2 番目のバージョンは、同じアイデアに対してフラグを使用するだけです。

scala> :pa
// Entering paste mode (ctrl-D to finish)

def f(ff: List[PartialFunction[Any, Int]]): List[Int] = ff match {
  case hd :: tail =>
    var ok = true
    val x  = hd.applyOrElse(num, (_: Any) => { ok = false ; 0 })
    if (ok) x :: f(tail) else f(tail)
  case _ => Nil
}

// Exiting paste mode, now interpreting.

f: (ff: List[PartialFunction[Any,Int]])List[Int]

scala> f(funcs.toList)
res2: List[Int] = List(132, 330)
于 2015-06-09T06:38:49.307 に答える