Понимать ключевое слово case в частичных функциях - PullRequest
1 голос
/ 16 октября 2019

Я новичок в Scala и пытаюсь декодировать его конструкции, я узнал о сопоставлении с шаблоном , и его синтаксис похож на оператор переключения Java

val x: Int = Random.nextInt(10)

x match {
  case 0 => "zero"
  case 1 => "one"
  case 2 => "two"
  case _ => "other"
}

Этот код здесьдовольно очевидно и читабельно. Я сталкивался с частичными функциями , которые достаточно очевидны и понятны.

Частичная функция - это функция, которая не дает ответа на все возможные входные значения, которые она может дать.

Что меня смущает, так это использование case в теле частичной функции, подобной этой:

val divide2: PartialFunction[Int, Int] = {
    case d: Int if d != 0 => 42 / d // WHAT IS THIS ?! 
}

Я не понимаю, как используется caseбез оператора match как это интерпретируется Scala, как он читается, это метод, класс или другая конструкция? Какие еще способы я могу использовать case без match оператора

* 1023? * Edit:

Я пытался поиграть с этим делом и до сих пор не получил его. Например

val SomeFun: PartialFunction[Int, Int] = {
    case d: Int if d != 0 => 1000 / d
    case f: Int if f != 2 => 100 / f
    case m: Int if m != 1 => 10 / m
  }

Как это работает?

Попытка этого дает ошибку

val SomeFun = {
    case d: Int if d != 0 => 1000 / d
    case f: Int if f != 2 => 100 / f
    case m: Int if m != 1 => 10 / m
  }


Error:(29, 17) missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?

Используется ли регистр без совпадения где-либо еще, кроме частичной функции?

Ответы [ 3 ]

5 голосов
/ 16 октября 2019

Это означает, что частичная функция будет применена только в том случае, если входной параметр может соответствовать регистровому выражению.

Фактический сгенерированный класс выглядит примерно так:

val divide = new PartialFunction[Int, Int] {
    def apply(x: Int) = 42 / x
    def isDefinedAt(x: Int) = x != 0
}

Используя orElse, вы можетеприменить или обработать несколько определений:

funcForInt orElse funcForDouble orElse funcForString

Хорошая композиция?

Редактировать:

val SomeFun: PartialFunction[Int, Int] = {
    case d: Int if d != 0 => 1000 / d
    case f: Int if f != 2 => 100 / f
    case m: Int if m != 1 => 10 / m
  }

Выше используется анонимная функция класса. Если вы удаляете тип переменной, вы просто даете ей выражение блока с некоторыми выражениями регистра, которые компилятор не может реально использовать.

Ссылка: https://www.james -willett.com / scala-anonymous-классы

1 голос
/ 16 октября 2019

Это анонимная функция для сопоставления с образцом, как описано в спецификации .

Попытка это дает ошибку

val SomeFun = ...

Этопотому что тип параметра должен быть известен, как и для «обычных» анонимных функций x => .... Разница в том, что в анонимной функции сопоставления с образцом нет места для непосредственного указания типа параметра (эквивалентного (x: Int) => ...), поэтому должен быть ожидаемым типом, например val SomeFun: PartialFunction[Int, Int] или val SomeFun: Int => Int.

val SomeFun: PartialFunction[Int, Int] = {
    case d: Int if d != 0 => 1000 / d
    case f: Int if f != 2 => 100 / f
    case m: Int if m != 1 => 10 / m
  }

переводится на

val SomeFun: PartialFunction[Int, Int] = new PartialFunction[Int, Int] {
  override def apply(x: Int) = x match {
    case d: Int if d != 0 => 1000 / d
    case f: Int if f != 2 => 100 / f
    case m: Int if m != 1 => 10 / m
  }
  override def isDefined(x: Int) = x match {
    case d: Int if d != 0 => true
    case f: Int if f != 2 => true
    case m: Int if m != 1 => true
    case _ => false
  }
}
0 голосов
/ 16 октября 2019

Компилятор переводит

val divide: PartialFunction[Int, Int] = {
  case d: Int if d != 0 => 42 / d 
}

во что-то вроде

def divide(d: Int) = {
  if (d != 0)
    42 / d
  else
    throw new MatchError(d)
}

, чтобы ответить

... какие еще способы я могу использовать case без match заявления

просто спросите себя, где мы можем использовать переведенную def версию. Обратите внимание, что определение PartialFunction имеет небезопасный throw, который является важным аспектом, о котором следует помнить.

В качестве примечания, использование case для определения функций аналогично кусочно-функциональным определениям из математики.

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