Combine a PartialFunction with a regular function

孤街醉人 提交于 2020-01-14 13:56:09

问题


So, suppose, I want to provide a "catch all" fall back for a PartialFunction:

 val foo: PartialFunction[Int, String] = { case 1 => "foo" }
 val withDefault = foo orElse { _.toString }

This does not compile: missing parameter type for expanded function ((x$1) => x$1.toString). This:

  val withDefault = foo orElse { case x: Int => x.toString }

Does not compile either (same error).

This:

val withDefault = foo orElse { (x: Int) => x.toString }

fails with type mismatch; found : Int => String; required: PartialFunction[?,?]

The only way I could find to make it work is to spell out the whole thing:

val withDefault = foo orElse PartialFunction[Int, String] { _.toString }

Is there any better syntax for this? I mean, one without having to tell it that I am passing a partial function from int to string to where it expects to receive a partial function from in to string. This is not ambiguous at all, why do I have to do this?


回答1:


Maybe you need applyOrElse:

val withDefault = foo.applyOrElse(_: Int, (_: Int).toString)

Or maybe you would like something like this:

implicit class PartialFunToFun[A,B](val f: PartialFunction[A,B]) extends AnyVal {
  def withDefault(bar: A => B) = f.applyOrElse[A,B](_: A, bar)
}

and use it: foo.withDefault(_.toString)(1)

Also if you want to get just another PartialFunction you can use the next syntax:

val withDefault = foo.orElse[Int, String]{case x => x.toString}



回答2:


The errors you encountered for the first two are not specific to orElse. They also occur when you attempt to define the same functions separately.

scala> { _.toString }
<console>:12: error: missing parameter type for expanded function ((x$1: <error>) => x$1.toString)
       { _.toString }


scala> { case x: Int => x.toString }
<console>:12: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?
       { case x: Int => x.toString }
       ^

For the last one, you are defining a function rather than a PartialFunction, thus leading to the "type mismatch" since orElse expects a PartialFunction to be passed.

scala> { (x: Int) => x.toString }
res3: Int => String = $$Lambda$1127/2044272973@3d5790ea

The final thing I'll add is that orElse is meant as a way to union two PartialFunctions. _.toString in itself is not a PartialFunction, though you could create a PartialFunction that uses it. To me it sounds like you want to have a "default" result for all the values that foo is not defined for, so I think you actually want applyOrElse instead since that is its use case. See the API to learn more.



来源:https://stackoverflow.com/questions/38357710/combine-a-partialfunction-with-a-regular-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!