Scala 3: Infix Operator Notation

Dean Wampler
Mar 28 · 3 min read

For a long time, Scala has supported a useful “trick” called infix operator notation. If a method takes a single argument, you can call it without the period after the instance and without parentheses around the argument. This post describes changes in Scala 3.

Spring Equinox Sunset, Ohio St. Chicago, ©2021, Dean Wampler, All Rights Reserved

For example, if I have a Matrix class and a + method to add matrices, element by element, I can write matrix1.+(matrix2) or use the less cluttered and more intuitive syntax, matrix1 + matrix2. The intention was to support true operators, like + in intuitive contexts like this. However, there was no restriction on what methods applied in Scala 2, so if I also had a plus method, then matrix1 plus matrix2 was allowed.

Used judiciously, this is fine, but dropping the punctuation occasionally makes the expressions ambiguous for the compiler or worse, for the reader. Hence Scala 3 is tightening the rules a bit to encourage more limited use.

Let’s revisit an example I discussed in Scala 3: Contextual Abstractions, Part II:

In Scala 3, the <+> method can be used as is as an infix operator, because its name uses just operator characters instead of alphanumeric and _ characters. However, combine can’t be used as an operator in the old way, unless I use back ticks or wrap the the argument in {}:

The {} option supports common usage where a function literal is passed to a method. Also, for backwards compatibility, all the standard collection operations are allowed to be used in infix notation without back ticks or {}.

If I really want combine to be used with infix notation, I declare it infix:

I’ll explain @targetName in a moment. The new infix keyword tells the compiler to allow infix notation for combine in user code without restriction. Note that it is necessary to use infix in NumericMonoid's definition, too, even though the abstract declaration in Semigroup is declared infix.

The @targetName annotation is a new feature for specifying the alphanumeric name the compiler should use for the generated byte code for the <+> method. If I wanted to call this method from Java code, I would use plus. This name is not visible in Scala code. Also, I can’t use "combine" as the argument for the annotation, as that name would collide with the actual combine method name.

When I compile these definitions, then use javap to analyze the class file, I see that <+> has the full byte code signature public default T plus(T, T);. The default keyword comes from the fact that the Semigroup trait is implemented in byte code as a Java interface and the implementation of <+> is a default method implementation for <+>.

If I remove the @targetName annotation, recompile, and then run javap, then <+> has the signature, public default T $less$plus$greater(T, T);, using Scala’s default encoding for non-alphanumeric characters.

As for many breaking changes, these restrictions on infix notation will start with Scala 3.1 or when the -source:future compilation flag is used with Scala 3.0.

For methods that take no arguments and they are not defined with empty parentheses, (), it’s been a common trick for DSLs to use postfix notation. For example, suppose I have an extension method to convert Double literals to some Dollars type in a financial application, 100.0 dollars.

Postfix expressions are even more ambiguous than infix expressions. They are not technically deprecated, but for a while it’s been necessary to enable the language feature for them, such as import scala.language.postfixOps. That remains true in Scala 3.0, but I’ve been told that a subsequent release of Scala 3 may finally, officially deprecate postfix expressions and remove them in a later release.

You can start reading the rough draft of Programming Scala, Third Edition on the O’Reilly Learning Platform. Most of the chapters are now available and the final release of the book will be coming soon!

Scala 3

What’s new in Scala version 3

Scala 3

A series of posts on Scala version 3, what’s new and why, and how to use its new features effectively. For more details, visit http://programming-scala.org/.

Dean Wampler

Written by

The person who’s wrong on the Internet. ML, AI, & FP supplicant at Domino Data Lab. Formerly at Anyscale and Lightbend. Speaker, Lover, O’Reilly author.

Scala 3

A series of posts on Scala version 3, what’s new and why, and how to use its new features effectively. For more details, visit http://programming-scala.org/.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store