Составление PartialFunctions с помощью orElse при наличии символа подстановки - PullRequest
3 голосов
/ 26 апреля 2019

Можно ли orElse составить два PartialFunction с, когда первая функция имеет шаблон подстановки case _ =>, который соответствует чему-либо, таким образом, фактически являясь полной функцией.

Например, учитывая

val pf1: PartialFunction[Int, String] = {
  case 1 => "foo"
  case 2 => "bar"
  case _ => "wildcard"
}

val pf2: PartialFunction[Int, String] = {
  case 3 => "baz"
  case _ => "wildcard"
}

затем, из коробки

(pf1 orElse pf2)(3)

вывод wildcard.Однако, предполагая, что мы не можем изменить pf1, можем ли мы составить с pf2, используя некоторые compfn, такие, что мы получим

{
  case 1 => "foo"
  case 2 => "bar"
  case 3 => "baz"
  case _ => "wildcard"
}

, где (pf1 compfn pf2)(3) выдаст baz?

Ответы [ 2 ]

6 голосов
/ 26 апреля 2019

Вы можете превратить pf1 в истинную частичную функцию, выполнив секунду match, чтобы преобразовать результат "подстановочный знак" в неудачное совпадение.

val pf3: PartialFunction[Int, String] = (i: Int) => pf1(i) match {
  case s if s != "wildcard" => s
}

А потом

(pf3 orElse pf2)(3)

Если вам нужен точный синтаксис, который вы показали, вам нужно использовать неявный класс:

implicit class addCompfn(f1: PartialFunction[Int, String]) {
  def compfn(f2: PartialFunction[Int, String]) = (i: Int) => f1(i) match {
    case s if s != "wildcard" => s
    case s => f2(i)
  }
}

А потом

(pf1 compfn pf2)(3)
0 голосов
/ 26 апреля 2019

Почему бы не выбрать что-то вроде этого:

val pf1: PartialFunction[Int, String] = {
  case 1 => "foo"
  case 2 => "bar"
}

val pf2: PartialFunction[Int, String] = {
  case 3 => "baz"
}

def composeOrElseWildcard(input: Int) = (pf1 orElse pf2).applyOrElse(input,(_: Int) => "wildcard")

В противном случае, для меня нет решения избавиться от эффекта шаблонов в pf1.

(composeOrElseWildcard(3) дает "baz" и composeOrElseWildcard(4) дает "wildcard") *

...