2015-02-20 3 views
1

Я пытаюсь отделить обычное поведение от длинных операторов сопоставления шаблонов с DRY кодом моего кода. Идея состоит в том, чтобы связать общий код с частичными функциями и оценить его с помощью оператора соответствия. Мой идеал - это что-то вродеЦепочные частичные функции с утверждениями соответствия

type pf = PartialFunction[Int, String] 
// Our common behaviour 
val common: pf = { 
    case 0 ⇒ "zero" 
    case 1 ⇒ "one" 
} 

val a = 2 
// speculative match statement with extended behaviour 
val b = a match (common orElse { 
    case 2 ⇒ "two" 
    case 3 ⇒ "three" 
    case _ ⇒ "None" 
}) 

К сожалению, аргумент утверждения соответствия, по-видимому, не является частичной функцией. Очевидно, что проблема может быть решена с помощью частичных функций, этот код делает трюк, но я теряю на традиционном синтаксисе матча картины:

val c: String = (common orElse { 
    case 2 ⇒ "two" 
    case 3 ⇒ "three" 
    case _ ⇒ "None" 
}: pf)(a) 

В приведенном ниже примере на уродливой стороне то, что я ищу. Он компилируется, но не с scala.MatchError, если аргумент a не определен в частичной функции common.

val d = common(a) orElse (a match { 
    case 2 ⇒ "two" 
    case 3 ⇒ "three" 
    case _ ⇒ "None" 
}) 

Я ищу следующие ответы:

  • Почему аргумент заявления матча не переведен на частичную функцию?
  • Почему уродливый пример выше не работает?
  • Есть ли умный способ достижения цели?

ответ

1

Матч не был обобщен для улова, совсем недавно здесь:

https://github.com/scala/scala/pull/4334

, где вы можете поставить частичную функцию уловом.

catch легко в том, что он должен быть PartialFunction[Throwable, ?], но для меня не очевидно, что аналогичные шаблоны совпадают. Речь идет об исчерпывающих проверках, ожидаемом типе проверяющего, кто знает что.

0

Что случилось с этим ...?

type Pfis = PartialFunction[Int, String] 

val common: Pfis = { 
    case 0 ⇒ "zero" 
    case 1 ⇒ "one" 
} 

val a = 2 

val other: Pfis = { 
    case 2 ⇒ "two" 
    case 3 ⇒ "three" 
    case _ ⇒ "None" 
} 

val b = (common orElse other)(a) 

// If you feel like using the "conventional match-case" 
val f = common orElse other 
val c = a match { case x => f(x) } 

Кроме того, нет такого понятия, как conventional pattern matching syntax ... match это ключевое слово, которое «можно мыслить, чтобы действовать» как right-associative function, что означает, что a match pf очень же (на самом деле не то же самое ... a match pf не работает) как pf.apply(a) или просто pf(a).

Кроме того, orElse используется для functional-composition, поэтому в основном вы создаете новую частичную функцию orElse, используя две частичные функции. Затем вы вызываете эту новую функцию parital, так же, как и какую-либо частичную функцию.

думаю, если вы понимаете, что такое orElse ... вы поймете ответ на свой второй пункт. Ну, это не удается, потому что вы применяете partial-functioncommon для аргумента 2 и она не определена 2.

Кроме того, еще одна вещь ... даже если common был определен в a, вы делаете что-то очень неправильно. Позвольте мне объяснить,

val t = 1 

val d = common(t) orElse (t match { 
    case 2 ⇒ "two" 
    case 3 ⇒ "three" 
    case _ ⇒ "None" 
}) 

// Now d is same as following, 
val k = "one" orElse "None" 

// Here, k and d both are actually PartialFunction[Int,Char] = <function1> 

// basically, both k and d take an Int i as argument and return the (character at index i in "one") orElse (character at index i in "None") 

// So, 

println(d(2)) 
// Will print - e 

println(d(3)) 
// since "one" does not have index 3, it will return index 3 in "None" 
// will print - e 

println(d(4)) 
// None of "one" and "None" have index 4 
// So, you will get - scala.MatchError: 4 (of class java.lang.Integer)