14

Is it possible to call a method using infix notation?

For example, in Haskell, I could write the following function:

x `isAFactorOf` y = x % y == 0

and then use it like:

if 2 `isAFactorOf` 10 ...

Which in some cases allows for very readable code. Is anything similar to this possible in Scala? I searched for "Scala infix notation", but that term seems to mean something different in Scala.

2 Answers2

17

Starting with version 2.10, Scala introduced implicit Classes to handle precisely this issue.

This will perform an implicit conversion on a given type to a wrapped class, which can contain your own methods and values.

In your specific case, you'd use something like this:

implicit class RichInt(x: Int) {
  def isAFactorOf(y: Int) = x % y == 0
}

2.isAFactorOf(10)
// or, without dot-syntax
2 isAFactorOf 10

Note that when compiled, this will end up boxing our raw value into a RichInt(2). You can get around this by declaring your RichInt as a subclass of AnyVal:

implicit class RichInt(val x: Int) extends AnyVal { ... }

This won't cause boxing, but it's more restrictive than a typical implicit class. It can only contain methods, not values or state.

Robert Harvey
  • 199,517
KChaloux
  • 5,803
  • 4
  • 35
  • 34
  • 2
    You should probably mention that implicit classes can't be top-level, so the implicit class will need to be defined locally. – Carcigenicate Dec 20 '14 at 15:54
3

Essentially, in Scala you can't call a function in an infix manner, but you can define a method on a type, which the left argument can be converted to implicitly. So for your example, you can define a class which has a method isAFactorOf (taking an Int) and indicate that an Int can be implicitly converted to an instance of this class.

If you look at this answer https://stackoverflow.com/a/3119671 to another question, you will see the syntax in Scala which works equivalently.

eques
  • 244
  • It's worth pointing out that new versions of Scala have a construct explicitly for this, which the answer linked does not address: implicit class RichInt(i: Int) { def square() = i * i }. – KChaloux Dec 05 '14 at 13:58