views:

145

answers:

2

I am trying to emulate != with <> in Scala.

implicit def conditional[A](left : A) = new {
 |   def<>[A](right : A) = (left != right)
 | }

What are the case in which this emulation won't work

+7  A: 

This ought to always work, but perhaps not in the way you're envisioning. Do you expect the two types to be the same? If so, it should be

class Conditionalize[A](left: A) { def <>(right: A) = left != right }
implicit def conditional[A](left: A) = new Conditionalize(left)

if not, it's clearer to use a separate type parameter:

implicit def notequality[A](a: A) = new { def <>[B](b: B) = a != b }

The former will only work if the LHS does not need to be implicitly converted to be of the same type as the RHS. With conditional but not notequality defined:

implicit def int_to_string(i: Int) = i.toString
scala> "5" <> 5
res0: Boolean = false

scala> 5 <> "5"
<console>:9: error: type mismatch;
 found   : java.lang.String("5")
 required: Int
       5 <> "5"

because you can't chain implicits.

The latter case will will work just like !=. (Edit: with one special case regarding the null value, due to its type Null.)

Both of these will wrap primitives, which will make it slower for heavy-duty work. But Scala avoids the weirdnesses of Java where 0.0 == -0.0 but (new java.lang.Double(0.0)).equals(new java.lang.Double(-0.0)) is false, so you shouldn't notice the difference in outcome.

And if you wanted to, you could add @specialized to make the comparators avoid boxing primitives at the cost of additional code size.

Rex Kerr
+4  A: 

One thing to take notice of is that <> has a different precedence than ==, so some thing will not work without parenthesis. For example:

a <> b >> 2  // (a <> b) >> 2
a != b >> 2  // a != (b >> 2)
Daniel
True, but not a serious problem since you have the same issues with precedence of `<` and `>`.
Rex Kerr
@Rex I beg to disagree. Equality, to me, is on a level different than ordering.
Daniel