Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List elements matching on their type

I've got a code similar to one below:

def walkTree(list:List[Command]) {
    list match {
        case Command1::rest => doSomething(); walkTree(rest)
        case Command2::rest => doSomethingElse(); walkTree(rest)
        case Nil => ;
    }
}

I also know that you can pattern match on specific type and assign a variable at the same time:

try {
    ...
}
catch {
    case ioExc:IOException => ioExc.printStackTrace()
    case exc:Exception => throw new RuntimeException("Oh Noes", e);
}

Is there a way to combine both in something like below:

def walkTree(list:List[Command]) {
    list match {
        case cmd1:Command1::rest => doSomething(); walkTree(rest)
        case cmd2:Command2::rest => doSomethingElse(); walkTree(rest)
        case Nil => ;
    }
}

Or do I need to extract each list element before matching?

like image 313
pafcio00 Avatar asked Jun 09 '11 08:06

pafcio00


People also ask

What is pattern matching in Haskell?

Pattern matching consists of specifying patterns to which some data should conform and then checking to see if it does and deconstructing the data according to those patterns. When defining functions, you can define separate function bodies for different patterns.

What is pattern matching in OCaml?

Pattern matching comes up in several places in OCaml: as a powerful control structure combining a multi-armed conditional, unification, data destructuring and variable binding; as a shortcut way of defining functions by case analysis; and as a way of handling exceptions.


2 Answers

Yes, just use parentheses like this (see example below):

def walkTree(list:List[Command]) {
    list match {
        case (cmd1:Command1)::rest => doSomething(); walkTree(rest)
        case (cmd2:Command2)::rest => doSomethingElse(); walkTree(rest)
        case Nil => ;
    }
}

However, can't you use foreach for this:

scala> List(A(1), B(2), A(3), B(4), A(5)).foreach(_ match {
     |     case (a:A) => println("a:" + a)
     |     case (b:B) => println("b:" + b)
     | })
a:A(1)
b:B(2)
a:A(3)
b:B(4)
a:A(5)

Example:

scala> case class A(val i: Int);
defined class A

scala> case class B(val i: Int);
defined class B

scala> def walkTree(list: List[ScalaObject]) {
     |     list match {
     |         case (a:A)::rest => println("a:" + a); walkTree(rest);
     |         case (b:B)::rest => println("b:" + b); walkTree(rest);
     |         case Nil => ;
     |     }
     | }
walkTree: (list: List[ScalaObject])Unit

scala> walkTree(List(A(1), B(2), A(3), B(4), A(5)))
a:A(1)
b:B(2)
a:A(3)
b:B(4)
a:A(5)
like image 81
dacwe Avatar answered Nov 15 '22 23:11

dacwe


Using foreach and then pattern match on each element seems to be clearer for me:

def walkTree(list:List[Command]) {
  list foreach {
    _ match {
      case cmd1:Command1 => doSomething()
      case cmd2:Command2 => doSomethingElse()
      case _ =>
    }
  }
}
like image 27
Frank S. Thomas Avatar answered Nov 15 '22 23:11

Frank S. Thomas