scala - How does orElse work on PartialFunctions -
i getting bizarre behavior (at least seems me) orelse method defined on partialfunction
it seem me that:
val = partialfunction[string, unit] { case "hello" => println("bye") } val b: partialfunction[any, unit] = a.orelse(partialfunction.empty[any, unit]) a("hello") // "bye" a("bogus") // matcherror b("bogus") // nothing b(true) // nothing makes sense not how behaving , having lot of trouble understanding why types signatures seem indicate exposed above.
here transcript of observing scala 2.11.2:
welcome scala version 2.11.2 (java hotspot(tm) 64-bit server vm, java 1.8.0_11). type in expressions have them evaluated. type :help more information. scala> val = partialfunction[string, unit] { | case "hello" => println("bye") | } a: partialfunction[string,unit] = <function1> scala> a("hello") bye scala> a("bye") scala.matcherror: bye (of class java.lang.string) @ $anonfun$1.apply(<console>:7) @ $anonfun$1.apply(<console>:7) @ scala.partialfunction$$anonfun$apply$1.applyorelse(partialfunction.scala:242) @ scala.runtime.abstractpartialfunction.apply(abstractpartialfunction.scala:36) ... 33 elided scala> val b = a.orelse(partialfunction.empty[any, unit]) b: partialfunction[string,unit] = <function1> scala> b("sdf") scala.matcherror: sdf (of class java.lang.string) @ $anonfun$1.apply(<console>:7) @ $anonfun$1.apply(<console>:7) @ scala.partialfunction$$anonfun$apply$1.applyorelse(partialfunction.scala:242) @ scala.partialfunction$orelse.apply(partialfunction.scala:162) ... 33 elided note return type of val b has not widen type of partialfunction.
but not work expected:
scala> val c = a.orelse(partialfunction.empty[string, unit]) c: partialfunction[string,unit] = <function1> scala> c("sdfsdf") scala.matcherror: sdfsdf (of class java.lang.string) @ $anonfun$1.apply(<console>:7) @ $anonfun$1.apply(<console>:7) @ scala.partialfunction$$anonfun$apply$1.applyorelse(partialfunction.scala:242) @ scala.partialfunction$orelse.apply(partialfunction.scala:162) ... 33 elided
there's few things wrong attempt, first let's see working implementation:
scala> val a: partialfunction[string, unit] = { case "hello" => println("bye") } a: partialfunction[string,unit] = <function1> scala> val b: partialfunction[any, unit] = { case _ => println("fallback") } b: partialfunction[any,unit] = <function1> scala> val c = a.orelse(b) c: partialfunction[string,unit] = <function1> scala> c("hello") bye scala> c("foo") fallback there's 2 main errors in code:
- the way pf defined
- the (wrong) assumption
empty"catch-all" function returnsnothing
1. how define partialfunction
val right: partialfunction[string, unit] = { case "hello" => println("bye") } how not define it:
val wrong = partialfunction[string, unit] { case "hello" => println("bye") } if @ definition of partialfunction.apply
def apply[a, b](f: => b): partialfunction[a, b] = { case x => f(x) } you'll see defines partial function any x , applies given f function it. { case "hello" => println("bye") } f argument, approximately end following (clearly unexpected) partialfunction:
val wrong: partialfunction[string, unit] = { case x => x match { case "hello" => println("bye") } so when ask whether it's defined return true, since it's defined any string:
wrong.isdefinedat("hello") // true (ok) wrong.isdefinedat("whatever") // true (sure?) but when try apply it
wrong("hello") // bye (ok) wrong("whatever") // matcherror (boom!) you fall short on inner match.
since orelse decides whether call "else" depending on result of isdefined, it's obvious why fails.
2. empty catches nothing!
straight docs:
def empty[a, b]: partialfunction[a, b]the partial function empty domain. attempt invoke empty partial function leads throwing
scala.matcherrorexception.
the partialfunction (well, it's not partial anymore) you're looking is:
val fallback: partialfunction[any, unit] = { case _ => println("fallback") } or - show learn our mistakes -
val fallback = partialfunction[any, unit] { _ => println("fallback") }
Comments
Post a Comment