使用匹配语句链接部分函数

时间:2015-02-20 06:50:22

标签: scala

我试图将长模式匹配语句中的常见行为分解为干掉我的代码。我们的想法是将公共代码链接到部分函数中,并通过match语句进行评估。我的理想就像是

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"
})

我正在寻找以下答案:

  • 为什么匹配语句的参数没有转换为部分函数?
  • 为什么上面这个丑陋的例子失败了?
  • 有没有一种聪明的方法来实现目标?

2 个答案:

答案 0 :(得分:1)

匹配并没有像捕获一样,最近在这里:

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

您可以为catch提供部分功能。

catch很简单,因为它必须是PartialFunction[Throwable, ?],但对我而言,模式匹配以相同的方式进行推广并不明显。问题在于详尽的检查,预期的审查者类型,谁知道什么。

答案 1 :(得分: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这样的关键字可以被认为是&#34;&#34;作为right-associative function表示a match pfa match pfpf.apply( a )非常相同(不完全相同...... pf( a )不起作用)。< / p>

此外,orElse用于functional-composition,所以基本上,你通过orElse两个partitial函数组成一个新的部分函数。然后你调用这个新的parital-function,就像你使用任何部分函数一样。

我想,如果你理解orElse做了什么......你会理解第二点的答案。好吧,它失败了,因为您将partial-function common应用于参数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)