Dear Emily,

You know that feeling when it suddenly clicks? Something you never knew or could not understand. And then, boom, this new knowledge is there for the taking. Well, I had this experience some time ago.

Girl, you know, me as a programmer coming from a Java background, methods and operators are a world apart. I never even considered them in the same category. The world was simple: operators for mathematical stuff, methods for interaction with objects. But time came and passed and I learned a lot.

Years ago I stumbled upon Groovy and saw this language had many operators that Java did not. I wondered if Java ever got that exiting stuff like the elvis and safe navigation operator[1]. Something else caught my eye as well, the overloading of operators:

class Person {
    String name

    Person(String name) { this.name = name }

    List<Person> plus(Person other) { [this, other] }
}

def both = new Person("William") + new Person("John")

It all looked cool and shiny, but since I had no choice in the programming language, I kind of forgot about it and moved on with my life.

Flash forward a few years… I joined the TypeDriven focus group, a group within JDriven dedicated to functional programming on the JVM. Some guys did mostly Scala, a language with both functional and object-oriented aspects. So I fiddled with the language a bit myself and soon found out the Groovy example above can be written in Scala as:

case class Person(name: String):
  def +(p: Person): List[Person] = List(this, p)

val both = Person("William") + Person("John")

And then it struck me! Though the code samples above look quite the same, there is a difference. Groovy defines some special function for its supported operators. Every usable operator has a matching method name. For example the plus method for +, the minus method for - and the multiply method for *. Thus, you are limited to the operators Groovy provides.

Scala did not seem to do such thing, as the name of the method is simply called +. If that’s true, I should be able to use any symbol or word I liked. So I put it to the test:

case class Person(name: String):
  def +(p: Person) = List(this, p)
  def combine(p: Person) = List(this, p)
  def @&@*@@(p: Person) = List(this, p)

val both1 = Person("William") + Person("John")
val both2 = Person("William") combine Person("John")
val both3 = Person("William") @&@*@@ Person("John")

And wow, it compiled and ran without any problems[2]. I checked the docs, and it said it all:

In Scala, operators are methods. Any method with a single parameter can be used as an infix[3] operator. For example, + can be called with dot-notation: 10.+(1), however, it’s easier to read as an infix operator: 10 + 1.
— Scala docs

I was flabbergasted when I gave this some real thought! Using a normal method to make operators work seemed like a wonderful trick to me. But there, too, I was wrong 🙈. If I would only have checked the operator page of Wikipedia, I could have read it all along:

In mathematics, an operator is generally a mapping or function that acts on elements of a space to produce elements of another space.
— Wikipedia

Once you know the concepts, you can easily use this knowledge in whatever language that supports 'extended' operator overloading. For example, above example can be kinda translated to F# as well:

type Person = {Name:string} with
  static member (+) (p1: Person,p2: Person) = [p1;p2]
  static member combine (p1: Person)(p2: Person) = [p1;p2]
  static member (@&@*@@) (p1: Person,p2: Person) = [p1;p2]

let both1 = {Name="William"} + {Name="John"}
let both2 = {Name="William"} |> Person.combine <| {Name="John"}
let both3 = {Name="William"} @&@*@@ {Name="John"}

Nice, so in the end an operator is nothing more than a symbol for a mathematical operation!

SU,
Jacob


1. Years later I learnt it could have been in Java 7 with "Project Coin"…​
2. Later I learned creating weird operators is seen in the community as language abuse though, see for example this gist.
3. An operator can be placed before (prefix), between (infix) or after (postfix) its arguments. Read more about it at Infix, Prefix, and Postfix Expressions.
shadow-left