8

Is it possible to pass case patterns as parameters to other functions? Something like this:

def foo(pattern: someMagicType) {
  x match {
    pattern => println("match")
  }
}

def bar() {
  foo(case List(a, b, c))
}
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • I played around with Scala 2.10's `Try`, before you changed your question. Maybe you still find that useful: http://stackoverflow.com/questions/11990017/threading-trys-through-for-comprehension – 0__ Aug 16 '12 at 15:57

3 Answers3

4

So you want to pass a pattern matching block to another function? That can be done with PartialFunctions, as the following example shows:

def foo(f:PartialFunction[String, Int]) = {
  f("")
}

foo {
  case "" => 0
  case s => s.toInt
}
Kim Stebel
  • 41,826
  • 12
  • 125
  • 142
3

I think Kim Stebel's first answer is close to what you want. A 'pattern match as such' is no isolated entity in Scala. A match can be defined as a Function1 or PartialFunction.

def foo[A, B](x: A)(pattern: PartialFunction[A, B]): Unit =
  if(pattern.isDefinedAt(x)) println("match")

def bar(list: List[String]): Unit =
  foo(list){ case List("a", "b", "c") => }

Test:

bar(Nil)
bar(List("a", "b", "c"))

Alternatively use composition:

def foo[A, B](x: A)(pattern: PartialFunction[A, B]): Unit = {
  val y = pattern andThen { _ => println("match")}
  if (y.isDefinedAt(x)) y(x)
}
0__
  • 66,707
  • 21
  • 171
  • 266
0

Your magic type can be written as a structural type that has an unapply method. Depending on what kind of extractor you need, you will need different kinds of unapply or unapplySeq. Below is a simple example.

def foo(x:Int, Pattern: { def unapply(x:Int):Boolean }) {
  x match {
    case Pattern => println("match")
  }
}

foo(1, new { def unapply(x:Int) = x > 0 })

And this is how it's done for lists:

foo(List(1,2,3), new { def unapplySeq(x:List[Int]):Option[List[Int]] = if (x.size >= 3) Some(x) else None })

def foo(x:List[Int], Pattern: { def unapplySeq(x:List[Int]):Option[List[Int]] }) {
  x match {
    case Pattern(a,b,c) => println("match: " + a + b + c)
  }
}
Kim Stebel
  • 41,826
  • 12
  • 125
  • 142
  • The ```foo(1,...``` bit doesn't work in the REPL (I use 2.9.2). It led me to this interesting discussion: http://www.scala-lang.org/node/10730 – opyate Aug 17 '12 at 07:34
  • Actually, nor does it work compiled. Which version of Scala did you use, @Kim? – opyate Aug 17 '12 at 07:47