Suffix notation


#1

I think it would be really useful if Kotlin supported suffix/postfix operators.

Given a Degree class:
data class Degree(val value: Double)

one could define a suffix function like so:
suffix fun Double.deg() = Degree(this)

which could be use as follows:
val angle = 90.0 deg

which would get compiled down the equivlant code:
val angle = Degree(90.0)

This is similar to the user-defined literals in C++11.


#2

I doubt the use case warrants a new language feature, considering that extension properties come very close already:

data class Degree(val value: Double)

val Double.deg: Degree 
  get() = Degree(this)

val angle = 90.0.deg

#3

True, but you could say the same for infix functions.

val flag = 1 shl 4

Could just as easily be expressed with

val flag = 1.shl(4)

The best argument I can muster in support, I suppose, is that infix and suffix functions open up the potential to write more elegant and readable code, which naturally fits in with many DSLs.

Isn’t that one of the major selling points of Kotlin?


#4

Point taken. I guess I’m not a big fan of this kind of opt-in alternative syntax in general, as it puts more burden on users (“Did this method support infix syntax?”, “Should I be using infix syntax here?”) and leads to less uniform code. Perhaps either-or would be better, i.e. infix/suffix functions are considered operators and can’t use normal function syntax.


#5

My understanding is that Scala has these and is removing them, because it causes weird side effects and problems.


#6

True, but I believe Scala’s suffix notation suffers because, like their infix notation, it’s something implicitly available to all unary and nullary methods. This causes issues because it can be difficult and non-intuitive to predict how Scala will parse the statement, especially if could have also been an infix notation.
E.g. The statement foo bar baz could be foo.bar().baz() or foo.bar(baz) or who knows what else.

I don’t believe Kotlin would have this issue to the same degree, if even at all, because it sensibly requires a function to state whether its an infix or not. This gives us more control of the DSL, as we can predict and design how it will be used.

It was also a wise choice to make the infix an operator, so it has an explicit precedence.


#7

Just thought about another alternative would be to define a singleton object degrees that had plus and minus operator functions so you could instead say something like this:

  val angle1 = degrees +90
  val angle2 = degrees -90

but I would not be opposed to postfix functions.


#8

I agree, units of measure are a very valid use case!
Because some functionality is already available for infix calls, it’s is already possible to write this:

val date = 15 april 2017

That is valid Kotlin code given the function:

infix fun Int.april(year: Int): Calendar {
    val out = Calendar.getInstance(TimeZone.getTimeZone("Europe/Zurich"))
    out.set(year, Calendar.APRIL, this)
    return out
}

Of course, a small dot does not look like a huge problem:

discountAfter[3.days] = 10.percent

But the code would look better without it.