Created
September 15, 2014 19:20
-
-
Save colindean/ef062db69915b49d44b9 to your computer and use it in GitHub Desktop.
Trying to improve compareTo to be more idiomatic in Scala pattern matching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This sucks | |
3.compareTo(4) match { | |
case x if x > 0 => | |
case x if x < 0 => | |
case x if x == 0 => | |
} | |
/* | |
I want something like this: | |
3.compareTo(4) match { | |
case GreaterThan => | |
case LessThan => | |
case EqualTo => | |
} | |
This would also be acceptable: | |
3.compareTo(4) match { | |
case GreaterThan(_) => | |
case LessThan(_) => | |
case EqualTo(_) => | |
} | |
*/ | |
// But this doesn't seem to work as I'd expect | |
case class GreaterThan(implicit x: Int) { | |
def apply(implicit x: Int):Boolean = x > 0 | |
} | |
case class LessThan(implicit x: Int) { | |
def apply(implicit x: Int) = x < 0 | |
} | |
case class EqualTo(implicit x: Int) { | |
def apply(implicit x: Int) = x == 0 | |
} | |
3.compareTo(4) match { | |
case GreaterThan => | |
case LessThan => | |
case EqualTo => | |
} | |
// I also tried with object apply(). This is something close, but not quite what I want. | |
object Compare { | |
def apply(x: Int) = { | |
x match { | |
case _ if x > 0 => GreaterThan | |
case _ if x < 0 => LessThan | |
case _ if x == 0 => EqualTo | |
} | |
} | |
case class GreaterThan() | |
case class LessThan() | |
case class EqualTo() | |
Compare(3.compareTo(4)) match { | |
case GreaterThan => | |
case LessThan => | |
case EqualTo => | |
} | |
// I tried to implement something like this: | |
Compare(3).to(4) match { | |
case GreaterThan => | |
case LessThan => | |
case EqualTo => | |
} | |
// but got caught up on the types: | |
case class GreaterThan() | |
case class LessThan() | |
case class EqualTo() | |
object Compare { | |
def apply(x: Ordered) = new Compare(x) | |
class Compare(original: Ordered) { | |
def to[T](y: T <: Ordered){ // can't seem to get this right | |
original.compareTo(y) match { // so that compareTo() gets the correctly typed `y` | |
case _ if x > 0 => GreaterThan | |
case _ if x < 0 => LessThan | |
case _ if x == 0 => EqualTo | |
} | |
}} | |
} | |
} |
👍 I like that a lot.
@colindean - The failure here is not immediately trying to make "compareTo" a macro (especially after the talk), like:
compare(x,y, {
case GreaterThan => ...
case LessThan => ...
case EqualTo =>...
})
AND THEN going for gold by using symbol instead of named objects, like:
compare(x,y, {
case > =>
case < =>
case _ =>
})
FYI -
> toolBox.parse("""{
| case < => 1
| case == => 2
| case > => 3
| }""")
res8: res6.u.Tree =
<empty> match {
case $less => 1
case $eq$eq => 2
case $greater => 3
}
In a more serious note, @Sciss suggestion is great.
Should not something like this work?
object Greater {
def unapply(x: Int) = x > 0
}
object Equal {
def unapply(x: Int) = x == 0
}
object Lesser {
def unapply(x: Int) = x < 0
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Something like this. I would use
[T: Ordering]
instead of[T <% Ordered[T]]
, though.