Skip to content

Instantly share code, notes, and snippets.

@gseitz
Created July 1, 2011 05:42
Show Gist options
  • Save gseitz/1057935 to your computer and use it in GitHub Desktop.
Save gseitz/1057935 to your computer and use it in GitHub Desktop.
Create 1-line extractors for traits
abstract class Traitor[T:Manifest] {
def unapply(any: AnyRef) ={
if (manifest[T].erasure.isAssignableFrom(any.getClass)) Some(any.asInstanceOf[T])
else None
}
}
// this is especially useful when you want to check whether something has a certain trait mixed in
// and want to combine it with retronym's && pattern matching conjunction combinator.
// see: http://stackoverflow.com/questions/2261358/pattern-matching-with-conjunctions-patterna-and-patternb
//
// The combination of Traitor and &&:
// Splitter to apply two pattern matches on the same scrutinee.
object && {
def unapply[A](a: A) = Some((a, a))
}
trait T1
trait T2
object T1 extends Traitor[T1]
object T2 extends Traitor[T2]
new T1 with T2 {} match {
case T1(t1) && T2(t2) => true // do something with t1 and t2
case _ => false // yawn
}
scala> trait YouCantMatchMe
defined trait YouCantMatchMe
scala> object YesICan extends Traitor[YouCantMatchMe]
defined module YesICan
scala> def uncatchable_?(any: Any) = any match {
| case YesICan(uncatchable) => Some(uncatchable)
| case _ => None
| }
uncatchable_$qmark: (any: Any)Option[YouCantMatchMe]
scala> uncatchable_?(new YouCantMatchMe{}) // Some(...)
res0: Option[YouCantMatchMe] = Some($anon$1@c678c7)
scala> uncatchable_?(4) // None
res1: Option[YouCantMatchMe] = None
@quelgar
Copy link

quelgar commented Jul 1, 2011

That is very cool. The && trick also.

@gseitz
Copy link
Author

gseitz commented Jul 1, 2011

Thanks. The kudos for && go to @retronym.

@retronym
Copy link

retronym commented Jul 1, 2011

Little known fact: you can pattern match on intersection types.

scala> trait A; trait B; class C extends A with B
defined trait A
defined trait B
defined class C

scala> new C match { case ab: A with B => true; case _ => false }
res3: Boolean = true

@gseitz
Copy link
Author

gseitz commented Jul 1, 2011

Thanks, but I could swear I tried it and I got different results depending on whether I used "A with B" or "B with A", which didn't seem too practical in the end. Can't remember though.

@retronym
Copy link

retronym commented Jul 1, 2011

I can't repro that. If you can, let me know, it's a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment