(A) => B
がPartialFunction[A, B]
から継承されるべきでないという同じ理由で、暗黙の変換でこれを行うと、危険です。つまり、PartialFunctionの契約では、isDefinedAt
がtrue
を返す場合は、apply
と安全に電話できることが保証されます。 Function1の契約はそのような保証を提供しません。
暗黙の変換では、どこにも定義されていない関数に適用すると、契約に違反するPartialFunctionが発生します。代わりに、変換を明示的にするために売春斡旋業者を使用します。
implicit def funcAsPartial[A, B](f: A => B) = new {
/** only use if `f` is defined everywhere */
def asPartial(): PartialFunction[A, B] = {
case a => f(a)
}
def asPartial(isDefinedAt: A => Boolean): PartialFunction[A, B] = {
case a if isDefinedAt(a) => f(a)
}
}
// now you can write
val f = (i: Int) => i * i
val p = f.asPartial // defined on all integers
val p2 = f.asPartial(_ > 0) // defined only on positive integers
*コメントで述べたように、「安全」はここで何を意味するのか完全には明らかではないかもしれません。私はそれについて考える方法は、PartialFunctionがドメインを次のような正確な意味で明示的に宣言していることです。が値x
に対してtrueを返す場合、apply(x)
は関数の作成者の意図と一貫して評価できます。そのはではありません。つまり、apply(x)
は例外をスローしませんが、単にその例外が関数の設計の一部であった(そして文書化されるべきである)ことを意味します。
ありがとうございます。私は、Function1がドメイン全体にわたって定義されていると誤解していました。 –
@AaronNovstrup:PartialFunctionの契約の説明は意味をなさない唯一のものですが、少なくとも2.9.1まではScalaDocsに反映されていません。 'PartialFunction'のScalaDocsは次のように主張しています:" PartialFunction [A、B] '型の部分関数は、ドメインが必ずしも' A'型のすべての値を含むわけではない単項関数です。さらに、 'PartialFunction'という文字列' {case 0 => 1/0} 'のように、定義されていればどこでもfを呼び出すのは安全です(どのような意味で)安全であると主張することは決してありません。 あなたはその情報をどこで取得しましたか?バグレポートを提出する必要がありますか? – Blaisorblade
@ Blaisorblade私はScalaを勉強していたときにメーリングリストでこの説明を読んでいると思いますが、これは私がこの答えを書いたときには何のドキュメントも見ていませんでした。そして、はい、この契約に違反することは(たとえば、catchブロック内で例外をラップ/再スローするなど)簡単に、さらには多少一般的です。本当のポイントは、PartialFunctionsはドメインを定義していますが、通常の関数はそうではありません。 –