使用未应用功能丰富 PartialFunction
enrich PartialFunction with unapply functionality
PartialFunction
是一个天然的提取器,它的 lift
方法提供了精确的提取器功能。所以使用部分函数作为提取器会非常方便。这将允许以比可用于 PartialFunction
的普通 orElse
更复杂的方式组合模式匹配表达式
所以我尝试使用 pimp 我的库方法但失败了
更新:如@Archeg 所示,还有另一种有效的转换方法。所以我将它包含在提供的代码中。
我也尝试了一些更复杂的解决方案,但都失败了
object Test {
class UnapplyPartial[-R, +T](val fun : PartialFunction[R,T]) {
def unapply(source : R) : Option[T] = fun.lift(source)
}
implicit def toUnapply[R,T](fun : PartialFunction[R,T]) : UnapplyPartial[R,T] = new UnapplyPartial(fun)
class PartialFunOps[-R, +T](val fun : PartialFunction[R,T]) {
def u : UnapplyPartial[R, T] = new UnapplyPartial(fun)
}
implicit def toPartFunOps[R,T](fun : PartialFunction[R,T]) : PartialFunOps[R,T] = new PartialFunOps(fun)
val f : PartialFunction[String, Int] = {
case "bingo" => 0
}
val u = toUnapply(f)
def g(compare : String) : PartialFunction[String, Int] = {
case `compare` => 0
}
// error while trying to use implicit conversion
def testF(x : String) : Unit = x match {
case f(i) => println(i)
case _ => println("nothing")
}
// external explicit conversion is Ok
def testU(x : String) : Unit = x match {
case u(i) => println(i)
case _ => println("nothing")
}
// embedded explicit conversion fails
def testA(x : String) : Unit = x match {
case toUnapply(f)(i) => println(i)
case _ => println("nothing")
}
// implicit explicit conversion is Ok
def testI(x : String) : Unit = x match {
case f.u(i) => println(i)
case _ => println("nothing")
}
// nested case sentences fails
def testInplace(x : String) : Unit = x match {
case { case "bingo" => 0 }.u(i) => println(i)
case _ => println("nothing")
}
// build on the fly fails
def testGen(x : String) : Unit = x match {
case g("bingo").u(i) => println(i)
case _ => println("nothing")
}
// implicit conversion without case is also Ok
def testFA(x : String) : Option[Int] =
f.unapply(x)
}
我收到以下错误消息:
UnapplyImplicitly.scala:16: error: value f is not a case class, nor does it have an unapply/unapplySeq member
case f(i) => println(i)
UnapplyImplicitly.scala:28: error: '=>' expected but '(' found.
case toUnapply(f)(i) => println(i)
使用 TestI
所示的假设形式可以避免此错误。但我很好奇是否可以避免 testInplace
错误:
UnapplyImplicitly.scala:46: error: illegal start of simple pattern
case { case "bingo" => 0 }.u(i) => println(i)
^
UnapplyImplicitly.scala:47: error: '=>' expected but ';' found.
case _ => println("nothing")
UnapplyImplicitly.scala:56: error: '=>' expected but '.' found.
case g("bingo").u(i) => println(i)
^
我不确定你最终想要达到什么目的,但据我所知,提取器应该始终是对象,你无法通过 class 获得它。它实际上在文档中被称为 Extractor Object
。考虑一下:
class Wrapper[R, T](fun: PartialFunction[R, T]) {
object PartialExtractor {
def unapply(p: R): Option[T] = fun.lift(p)
}
}
implicit def toWrapper[R,T](fun : PartialFunction[R,T]) : Wrapper[R, T] = new Wrapper(fun)
val f : PartialFunction[String, Int] = {
case "bingo" => 0
}
def testFF(x : String) : Unit = x match {
case f.PartialExtractor(i) => println(i)
case _ => println("nothing")
}
更新
我能想到的最好的:
def testInplace(x : String) : Unit ={
val ff = { case "bingo" => 0 } : PartialFunction[String, Int]
x match {
case ff.PartialExtractor(Test(i)) => println(i)
case "sd" => println("nothing") }
}
PartialFunction
是一个天然的提取器,它的 lift
方法提供了精确的提取器功能。所以使用部分函数作为提取器会非常方便。这将允许以比可用于 PartialFunction
orElse
更复杂的方式组合模式匹配表达式
所以我尝试使用 pimp 我的库方法但失败了
更新:如@Archeg 所示,还有另一种有效的转换方法。所以我将它包含在提供的代码中。
我也尝试了一些更复杂的解决方案,但都失败了
object Test {
class UnapplyPartial[-R, +T](val fun : PartialFunction[R,T]) {
def unapply(source : R) : Option[T] = fun.lift(source)
}
implicit def toUnapply[R,T](fun : PartialFunction[R,T]) : UnapplyPartial[R,T] = new UnapplyPartial(fun)
class PartialFunOps[-R, +T](val fun : PartialFunction[R,T]) {
def u : UnapplyPartial[R, T] = new UnapplyPartial(fun)
}
implicit def toPartFunOps[R,T](fun : PartialFunction[R,T]) : PartialFunOps[R,T] = new PartialFunOps(fun)
val f : PartialFunction[String, Int] = {
case "bingo" => 0
}
val u = toUnapply(f)
def g(compare : String) : PartialFunction[String, Int] = {
case `compare` => 0
}
// error while trying to use implicit conversion
def testF(x : String) : Unit = x match {
case f(i) => println(i)
case _ => println("nothing")
}
// external explicit conversion is Ok
def testU(x : String) : Unit = x match {
case u(i) => println(i)
case _ => println("nothing")
}
// embedded explicit conversion fails
def testA(x : String) : Unit = x match {
case toUnapply(f)(i) => println(i)
case _ => println("nothing")
}
// implicit explicit conversion is Ok
def testI(x : String) : Unit = x match {
case f.u(i) => println(i)
case _ => println("nothing")
}
// nested case sentences fails
def testInplace(x : String) : Unit = x match {
case { case "bingo" => 0 }.u(i) => println(i)
case _ => println("nothing")
}
// build on the fly fails
def testGen(x : String) : Unit = x match {
case g("bingo").u(i) => println(i)
case _ => println("nothing")
}
// implicit conversion without case is also Ok
def testFA(x : String) : Option[Int] =
f.unapply(x)
}
我收到以下错误消息:
UnapplyImplicitly.scala:16: error: value f is not a case class, nor does it have an unapply/unapplySeq member case f(i) => println(i)
UnapplyImplicitly.scala:28: error: '=>' expected but '(' found. case toUnapply(f)(i) => println(i)
使用 TestI
所示的假设形式可以避免此错误。但我很好奇是否可以避免 testInplace
错误:
UnapplyImplicitly.scala:46: error: illegal start of simple pattern case { case "bingo" => 0 }.u(i) => println(i) ^
UnapplyImplicitly.scala:47: error: '=>' expected but ';' found. case _ => println("nothing")
UnapplyImplicitly.scala:56: error: '=>' expected but '.' found. case g("bingo").u(i) => println(i) ^
我不确定你最终想要达到什么目的,但据我所知,提取器应该始终是对象,你无法通过 class 获得它。它实际上在文档中被称为 Extractor Object
。考虑一下:
class Wrapper[R, T](fun: PartialFunction[R, T]) {
object PartialExtractor {
def unapply(p: R): Option[T] = fun.lift(p)
}
}
implicit def toWrapper[R,T](fun : PartialFunction[R,T]) : Wrapper[R, T] = new Wrapper(fun)
val f : PartialFunction[String, Int] = {
case "bingo" => 0
}
def testFF(x : String) : Unit = x match {
case f.PartialExtractor(i) => println(i)
case _ => println("nothing")
}
更新
我能想到的最好的:
def testInplace(x : String) : Unit ={
val ff = { case "bingo" => 0 } : PartialFunction[String, Int]
x match {
case ff.PartialExtractor(Test(i)) => println(i)
case "sd" => println("nothing") }
}