Search code examples
scalaoperators

How to define my own logical operator on Booleans in Scala


I would like to have a new logical operator. However, when I try to define it as:

def xor (that: Boolean): Boolean = (this || that) && !(this && that)

and then use it, I get following error:

value xor is not a member of Boolean

The xor definition is located in the same class just before the function I'm using it.

What is the right place where the operator definition should be placed?


Solution

  • I'm not sure if you know about it, but there is a bitwise XOR operator in Scala already (^), which you'd probably prefer.

    To add extension methods to booleans, you can't simply define a function that takes 2 parameters. You'll have to wrap the boolean in an implicit class and define a proper method on that.

    implicit class Xorable(private val a: Boolean) extends AnyVal {
      def xor(b: Boolean) = a ^ b
    }
    

    and only then can you use it like true xor false. The method you've defined above can only be used as xor(a, b)

    Edit: As Luis Miguel Mejía Suárez pointed out

    It is usually a good idea to make your implicit classes to be value classes.

    The only thing is that you can't have an implicit value class whose parameter is an instance of another value class. Since Booleans are value classes, you'll have to either not use value classes or make an implicit def in this case, but for AnyRef's descendants, you can just add an extends AnyVal to that first implicit class. Actually -

    The restriction only apply to user-defined value classes, you can make the implicit class of booleans to be a value class

    By the way, you can do this more easily with an extension method in Scala 3:

    extension (a: Boolean) def xor(b: Boolean) = a ^ b