val squareRoot = new PartialFunction[Double, Double] {
def isDefinedAt(x: Double) = x >= 0
def apply(x: Double) = scala.math.sqrt(x)
}
val f1= squareRoot andThen sqr
> f1: PartialFunction[Double,Double] = <function1>
val f3= sqr compose squareRoot
> f3: (Double) => Double = <function1>
/** Composes this partial function with a transformation function that
* gets applied to results of this partial function.
* @param k the transformation function
* @tparam C the result type of the transformation function.
* @return a partial function with the same domain as this partial function, which maps
* arguments `x` to `k(this(x))`.
*/
override def andThen[C](k: B => C): PartialFunction[A, C] =
new AndThen[A, B, C] (this, k)
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
The 'bug' is that PartialFunction extends Function1 and thus it
is possible to write
sqr compose squareRoot
Function `compose` takes as argument a `Function1` and returns
a new `Function1`. It should not be possible to pass a `PartialFunction`
as an argument to `compose` but - alas! - here the designers of
Scala opted for convenience and sacrificed correctness.
> Note that Function1
does not define a total function, as might be suggested by the existence of scala.PartialFunction. The only distinction between Function1
andPartialFunction
is that the latter can specify inputs which it will not handle.
isDefinedAt
returns true for an a: A
, calling apply(a)
may still throw an exceptionPartialFunction[A, B]
is a unary function where the domain does not necessarily include all values of type A
.My advice: Define your own wrapper
final class PFunction[A,B](val v: A => Option[B]) extends AnyVal
as a sound and correct alternative to `PartialFunction`.
Thanks for the clarifications, Paolo. I understand now that the goal of
PartialFunction is to allow one to check whether a value is in its
domain without evaluating the - possibly lengthy - calculation;
something that would not be possible with A => Option[B].
Am I right in assuming that the same thing would be possible by using
a lazy implementation of `Option` (for instance scalaz.LazyOption,
which als defines a function `isDefined` that does not evaluate the
wrapped value), in which case we could use A => LazyOption[B] instead of
PartialFunction?