Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala pattern matching against something of multiple types

Tags:

scala

Suppose c can be Updatable or Drawable or both. If it's both, I want to handle Updatable first.

Given this code:

case c: Updatable => c.update()
case c: Drawable => c.draw()

Has one problem: it only evaluates one of the choices. Sometimes, c can be both so I need to run both of these.

I know there's | mechanism that looks like this:

case c @ (_: Updatable | _: Drawable) => c.update(); c.draw()

The problem here is that I can't call both update and draw because it's an |.

I think I'm looking for something like this, but doesn't compile:

case c @ (_: Updatable & _: Drawable) => c.update(); c.draw()
case c: Updatable => c.update()
case c: Drawable => c.draw()

Is there such a thing? I know I could open it up and write isInstacenOf, but I'd prefer a pattern match if it's even possible.

like image 878
Kai Sellgren Avatar asked Dec 19 '22 16:12

Kai Sellgren


2 Answers

def f(c:Any) = c match {
  case d:Drawable with Updatable => println("both")
  case d:Drawable => println("drawable")
  case u:Updatable => println("updatable")
}
like image 82
Landei Avatar answered Feb 23 '23 02:02

Landei


How about this?

trait Foo
trait Bar
class FooBarImpl extends Foo with Bar
type FooBar = Foo with Bar


def matching(x: Any) = x match {
    case _: FooBar  => "i'm both of them"
    case _: Foo    => "i'm foo"
    case _: Bar    => "i'm bar"
}

val x = new FooBarImpl

matching(x) 
// res0: String = i'm both of them
matching(new Foo{})
// res1: String = i'm foo

Although I'm not quite sure whether reflection kicks in or not.

like image 41
om-nom-nom Avatar answered Feb 23 '23 01:02

om-nom-nom