Wykonanie tego z niejawną konwersją jest niebezpieczne, z tego samego powodu, że (A) => B
nie powinien dziedziczyć po PartialFunction[A, B]
. Oznacza to, że umowa z PartialFunction gwarantuje, że możesz bezpiecznie * zadzwonić pod numer apply
wszędzie tam, gdzie isDefinedAt
zwraca true
. Umowa Function1 nie przewiduje takiej gwarancji.
Twoja niejawna konwersja spowoduje operację częściową, która narusza jej umowę, jeśli zastosujesz ją do funkcji, która nie jest zdefiniowana wszędzie. Zamiast tego należy użyć alfonsa, aby konwersja wyraźne:
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
* Jak wspomniano w komentarzach, to może nie być do końca jasne, co „bezpieczeństwo” oznacza tutaj. Myślę, że funkcja PartialFunction jawnie deklaruje swoją domenę w następujący sposób: jeśli isDefinedAt
zwraca true dla wartości x
, wówczas można oszacować apply(x)
w sposób zgodny z intencją autora tej funkcji. Ten nie oznacza, że oznacza, że apply(x)
nie wyrzuci wyjątku, a jedynie, że wyjątek był częścią projektu funkcji (i powinien być udokumentowany).
Dziękuję; Miałem błędne przekonanie, że Function1 sugeruje bycie zdefiniowanym w całej domenie. –
@AaronNovstrup: twoje wyjaśnienie umowy PartialFunction jest jedyną, która ma sens, ale nie jest odzwierciedlana przez ScalaDocs (przynajmniej do 2.9.1). ScalaDocs firmy PartialFunction twierdzi, że: "Częściowa funkcja typu' PartialFunction [A, B] 'jest funkcją jednoargumentową, w której domena niekoniecznie zawiera wszystkie wartości typu" A "." Co więcej, nigdy nie twierdzą, że jest bezpiecznie (w jakim sensie) wywoływać f wszędzie tam, gdzie jest to zdefiniowane, i jest to raczej łatwe do złamania, jak to robi literał 'PartialFunction'' {case 0 => 1/0} '. Skąd masz te informacje? Czy należy zgłosić zgłoszenie błędu? – Blaisorblade
@ Blaisorblade Uważam, że przeczytałem to wyjaśnienie na liście mailingowej, gdy uczyłem się Scala (już dawno temu), a ja nie patrzyłem na żadną dokumentację, gdy pisałem tę odpowiedź. I tak, jest łatwe, a nawet dość częste, naruszenie tej umowy (np. Zawinięcie/ponowne zgłoszenie wyjątku w bloku catch). Rzeczywistym punktem jest to, że PartialFunctions definiują swoją domenę, podczas gdy zwykłe Funkcje nie (z pewnym rozmytaniem o tym, co to właściwie oznacza). –