Monday, February 22, 2010

Methods of PartialFunction object

This topic looks at the functionality provide in the object PartialFunction.

This example uses Scala 2.8 which I believe is required.

Only two methods are focused on. PartialFunction.cond and PartialFunction.condOpt.
As per request the signature for said methods are:
  1. def cond[T](x: T)(pf: PartialFunction[T, Boolean]): Boolean
  2. def condOpt[T, U](x: T)(pf: PartialFunction[T, U]): Option[U]

Now for some examples:
  1. scala>  import PartialFunction._
  2. import PartialFunction._
  3. scala> def strangeConditional(other: Any): Boolean = cond(other) {
  4.      |  case x: String if x == "abc" || x == "def"  => true
  5.      |  case x: Int => true
  6.      | }
  7. strangeConditional: (other: Any)Boolean
  8. scala> strangeConditional("abc")
  9. res0: Boolean = true
  10. scala> strangeConditional("hello")
  11. res1: Boolean = false
  12. scala> strangeConditional(3)      
  13. res2: Boolean = true
  14. scala> def onlyInt(v: Any): Option[Int] = condOpt(v) { case x: Int => x }
  15. onlyInt: (v: Any)Option[Int]
  16. scala> onlyInt("hi")
  17. res3: Option[Int] = None
  18. scala> onlyInt(3)
  19. res4: Option[Int] = Some(3)
  20. scala> import util.control.Exception.catching
  21. import util.control.Exception.catching
  22. scala> object IntNum { 
  23.      |  val number = catching(classOf[NumberFormatException])
  24.      |  def unapply(x : Any) = condOpt(x) {
  25.      |      case x : Int => x
  26.      |      case y : String if number.opt(y.toInt).isDefined => y.toInt
  27.      |    }
  28.      | }
  29. defined module IntNum
  30. scala> 1 match { case IntNum(x) => println(x+" i win!")}   
  31. 1 i win!
  32. scala> 3 match { case IntNum(x) => println(x+" i win!")}
  33. 3 i win!

3 comments:

  1. It would be somewhat more useful to supply the type signatures of cond and condOpt, I think. It's not necessarily obvious what the utility of these are, particularly when using Any for your examples; or rather, it's not clear what advantage is gained over using a simple match expression.

    ReplyDelete
  2. object IntNum {
    ..val number = catching(classOf[NumberFormatException])
    ..def unapply(x: Any) = x match {
    ....case x: Int => Some(x)
    ....case x: String => number.opt(x.toInt)
    ...._ => None
    ..}
    }

    is easier to read IMHO and does not call y.toInt twice (using opt together with condOpt seems contraproductive to me)

    (sorry for the dots -- I was not able to figure out how to indent as tags are not allowed and whitespace is removed or compressed)

    Nice blog, btw. Keep up the good work!

    ReplyDelete
  3. Wasn't it meant to be
    scala> "3" match { case IntNum(x) => println(x+" i win!")}
    3 i win!
    ?

    ReplyDelete