3

このコードはうまくいくとは思いませんが、うまくいきます (Scala 2.10 では):

scala>     ((i: Int) => i.toString match {
     |        case s if s.length == 2 => "A two digit number"
     |        case s if s.length == 3 => "A three digit number"
     |     }): PartialFunction[Int,String]
res0: PartialFunction[Int,String] = <function1>

// other interactions omitted

scala> res0.orElse(PartialFunction((i: Int) => i.toString))
res5: PartialFunction[Int,String] = <function1>

scala> res5(1)
res6: String = 1

それはどのように機能しますか?MatchErrora が の中にスローされることを期待していますres0

res0Scala 言語仕様は、どのように解釈されるべきかを明示的に文書化していないようです。

4

3 に答える 3

3

秘訣は、コンパイラが定義を部分関数に変換された全体関数として解釈していないことです。実際には、最初に部分関数を作成しています。に注意することで確認できますres0.isDefinedAt(1) == false

合計関数を部分関数に実際に変換すると、期待どおりの動作が得られます。

scala> PartialFunction((i: Int) => i.toString match {
     |       case s if s.length == 2 => "A two digit number"
     |       case s if s.length == 3 => "A three digit number"
     |     })
res0: PartialFunction[Int,String] = <function1>

scala> res0 orElse ({ case i => i.toString }: PartialFunction[Int, String])
res1: PartialFunction[Int,String] = <function1>

scala> res1(1)
scala.MatchError: 1 (of class java.lang.String)
// ...

この例では、PartialFunction.applyはその引数を合計関数として扱うため、定義されている場所に関する情報は失われます。

于 2013-11-14T21:04:17.043 に答える
2

orElseは、元の引数が定義されPartialFunctionていない場合のフォールバックとして引数が扱われるように定義されています。APIを参照してください。

于 2013-11-14T08:53:58.163 に答える
1

res0一致しない場合は、代わりに他の pf を試してください。これが基本的にどのように機能するかは次のとおりです。

if (res0.isDefinedAt(1)) {
  res0(1)
} else {
  other(1)
}

orElse 呼び出しは、OrElseから継承するのインスタンスを作成しますPartialFunction: https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L159

これを呼び出すと、次のように呼び出さapplyOrElseますf1.applyOrElse(x, f2): https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L162

これは以下を呼び出しますif (isDefinedAt(x)) apply(x) else f2(x): https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L117-L118

したがってMatchError、どちらの pf も一致しない場合にのみ , を取得します。

于 2013-11-14T08:50:39.303 に答える