Определение типа частичной функции Scala - PullRequest
0 голосов
/ 03 мая 2018
val even: PartialFunction[Int, String] = PartialFunction[Int, String] {
  case i if i % 2 == 0 => i + " is even"
}

val isEven: PartialFunction[Int, String] = {
  case i if i % 2 == 0 => i + " is even"
}

val odd: PartialFunction[Int, String] = PartialFunction[Int, String] {
  case x if x % 2 == 1 => x + " is odd"
}


val isOdd: PartialFunction[Int, String] = {
  case x if x % 2 == 1 => x + " is odd"
}

val tot = even orElse odd
val tot2 = isEven orElse isOdd

println(tot(3))
println(tot2(3))

В этом коде функция tot выдает ошибку совпадения, а функция tot2 работает, как ожидается. Единственная разница между ними заключается в том, как они определены. Кто-нибудь может объяснить, почему такая разница в результате?

Заранее спасибо !!!

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

В основе различие заключается в том, что isDefinedAt в частичной функции не определяется, как можно было бы ожидать в версии с использованием метода PartialFunction.apply. Именно поэтому этот метод теперь устарел, PartialFunction.apply предназначен для преобразования всей функции в частичную функцию с isDefinedAt, всегда возвращающей true, что означает, что он будет считать, что она определена для 3 в вашем примере, и попытаться применить функцию вместо возврата к четной функции, которую вы предоставили в качестве альтернативы.

Это поднимает общую больную точку в сообществе относительно полных функций против частичных функций. PartialFunction является подтипом Function, я предполагаю, что в смысле разработки ОО это функция с дополнительным методом (isDefinedAt), который сообщает вам, определена ли функция для определенного значения. Многие считают, что это ошибка, так как в смысле Лискова, Function должна быть подтипом PartialFunction, потому что вы можете использовать функцию везде, где ожидается PartialFunction, но если вы используете PartialFunction там, где ожидается функция, она скомпилируется, то может произойти сбой во время выполнения. Мне кажется, это потому, что Function может иметь неявный isDefinedAt, который всегда возвращает true, что позволит вам исправить отношение и сделать Function подтипом PartialFunction. Это происходит в PartialFunction.apply, которая ожидает итоговую функцию и из-за этого ожидания определяет, что isDefinedAt всегда возвращает true, но не может обеспечить это ожидание, поэтому, если вы вызываете PartialFunction.apply (somePartialFunction), происходят плохие вещи, которые программисты не ожидают.

B):PartialFunction[A,B]" rel="noreferrer"> PartialFunction.apply Scaladoc

PartialFunction[Int, String]{...} is syntactic sugar for
PartialFunction[Int, String].apply({...})

Чтобы минимизировать:

val even: PartialFunction[Int, String] = PartialFunction[Int, String]{
  case i if i % 2 == 0 => i + " is even"
}

val isEven: PartialFunction[Int, String] = {
  case i if i % 2 == 0 => i + " is even"
}

println(even.isDefinedAt(3)) //true
println(isEven.isDefinedAt(3)) //false
0 голосов
/ 03 мая 2018

В первых двух случаях вы вызываете функцию apply в сопутствующем объекте PartialFunction. Я знаю, это звучит так, как будто это должно Работа. Но это не так, потому что PartialFunction.apply должно читать PartialFunction.fromTotalFunction.

Это проблема языка Scala, и, если я правильно помню (не могу найти билет в данный момент, посмотрю позже), эта функция apply исчезнет и будет заменена на fromTotalFunction в Scala 2.13.

UPDATE

Я имел в виду билет # 6005

Похоже, что PartialFunction.apply уже устарел с Scala 2.12.5 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...