Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chained comparisons in Scala

Tags:

scala

Python supports an elegant syntax for "chained comparisons", for example:

0 <= n < 256

meaning,

0 <= n and n < 256

Knowing that it's a fairly flexible language syntactically, is it possible to emulate this feature in Scala?

like image 658
Matt R Avatar asked Jul 22 '09 11:07

Matt R


1 Answers

Daniel's answer is comprehensive, it's actually hard to add anything to it. As his answer presents one of the choices he mentioned, I'd like just to add my 2 cents and present a very short solution to the problem in the other way. The Daniel's description:

You could, theoretically, feed the result of the one of the methods to another method. I can think of two ways of doing that:

  • Having <= return an object that has both the parameter it received and the result of the comparision, and having < use both these values as appropriate.

CmpChain will serve as an accumulator of comparisions already made along with a free rightmost object, so that we can compare it to the next:

class CmpChain[T <% Ordered[T]](val left: Boolean, x: T) {
  def <(y: T) = new CmpChain(left && x < y, y)
  def <=(y: T) = new CmpChain(left && x <= y, y)
  // > and >= are analogous

  def asBoolean = left
}

implicit def ordToCmpChain[T <% Ordered[T]](x: T) = new AnyRef {
  def cmp = new CmpChain(true, x)
}
implicit def rToBoolean[T](cc: CmpChain[T]): Boolean = cc.asBoolean

You can use it for any ordered types, like Ints or Doubles:

scala> (1.cmp < 2 < 3 <= 3 < 5).asBoolean                          
res0: Boolean = true

scala> (1.0.cmp < 2).asBoolean
res1: Boolean = true

scala> (2.0.cmp < 2).asBoolean
res2: Boolean = false

Implicit conversion will produce Boolean where it is supposed to be:

scala> val b: Boolean = 1.cmp < 2 < 3 < 3 <= 10  
b: Boolean = false
like image 122
Alexander Azarov Avatar answered Sep 30 '22 22:09

Alexander Azarov