I've noticed in Kotlin that there are already defined unaryPlus
and unaryMinus
operators on all of the number types.
What's the purpose of these operators? Are they in some way connected to the prefix forms of inc
and dec
?
Others have defined the basic meaning of unaryMinus
and unaryPlus
, and in reality on numeric types they may not actually even be called as functions. For example, coding +x
or x.unaryPlus()
generates the same bytecode (where x
is type Int
):
ILOAD 1
ISTORE 2
And the code -x
or x.unaryMinus()
generates the identical bytecode:
ILOAD 1
INEG
ISTORE 2
But there is more going on that this...
So why does the compiler even generate anything for +x
? Some people will say that +x
and x.unaryPlus()
doesn't do anything, and that -x
and x.unaryMinus()
only reverses the sign. That isn't correct. In Java it is more complicated because it can involve widening and unboxing, see Unary Numeric Promotion which explains the full consequences of these operators. This has consequences for boxed values and types smaller than Int
. For value of type Short
and Byte
these operators will return a new unboxed value widened of type Int
. And since both operators have this more hidden functionality then both must generate bytecode even if you don't think +x
does anything. By the way, this is similar to what C language does and it is called Usual Arithmetic Conversions.
Therefore this code is invalid:
val x: Short = 1
val y1: Short = +x // incompatible types
val y2: Short = x.unaryPlus() // incompatible types
val z1: Short = -x // incompatible types
val z2: Short = x.unaryMinus() // incompatible types
In these numeric cases on the base numeric types they are just compiler magic to allow for the idea of these operators to be equated to operator functions that you might want to overload in other classes.
For other uses such as Operator Overloading...
But they are there for more than just mathematical use and can be used on any class as an operator. Kotlin exposes operators as functions so that you can apply operator overloading on a specific set of operators which include unaryMinus
and unaryPlus
.
I could use these to define operators for my own or existing classes. For example I have a Set<Things>
where Things
is an enum class along with an unaryMinus()
operator to negate the contents of the finite set of options:
enum class Things {
ONE, TWO, THREE, FOUR, FIVE
}
operator fun Set<Things>.unaryMinus() = Things.values().toSet().minus(this)
And then I can negate my enum set whenever I want:
val current = setOf(Things.THREE, Things.FIVE)
println(-current) // [ONE, TWO, FOUR]
println(-(-current)) // [THREE, FIVE]
Notice that I had to declare my extension function with the modifier operator
or this will not work. The compiler will remind you if you forget this when you try to use the operator:
Error:(y, x) Kotlin: 'operator' modifier is required on 'unaryMinus' in 'com.my.favorite.package.SomeClass'
These operators are the signs of the integers. Here are some examples:
+5
calls 5.unaryPlus()
and returns 5.
-5
calls 5.unaryMinus()
and returns -5.
-(-5)
calls 5.unaryMinus().unaryMinus()
and returns 5.
The purpose of those operators is to be able to write:
val a = System.nanoTime()
val b = -a // a.unaryMinus()
val c = +b // b.unaryPlus()
They are not directly related to ++
/inc
and --
/dec
operators however they can be used in conjunction.
Notice that the following expressions are different:
--a // a = a.dec()
-(-a) // a.unaryMinus().unaryMinus()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With