TomTom
TomTom

Reputation: 2930

How to define new operator in Kotlin?

Is it possible to define a generic exponentiation operator that can be interfaced like this:

> 10^3         // 1000
> 2.71^2       // 7.3441
> 3.14^(-3.14) // 0.027..

According to the docs it's possible to extend classes with infix functions:

// Define extension to Int
infix fun Int.exp(exponent: Int): Int {
...
}

But they don't allow symbols like ^

Upvotes: 18

Views: 8362

Answers (3)

Paulo Buchsbaum
Paulo Buchsbaum

Reputation: 2649

I works with Math. Android Studio forbids to use ^ with quotes. So I've defined v operator (^ upside down). Is it ugly? Yes, but it is best than thons of typecasting and pow notation.

inline infix fun Double.v(exponent: Int): Double = this.pow(exponent)
inline infix fun Double.v(exponent: Long): Double = this.pow(exponent.toDouble())
inline infix fun Double.v(exponent: Double): Double = this.pow(exponent)
inline infix fun Int.v(exponent: Int): Double = this.toDouble().pow(exponent)
inline infix fun Int.v(exponent: Long): 
      Double = this.toDouble().pow(exponent.toDouble())
inline infix fun Int.v(exponent: Double): Double = this.toDouble().pow(exponent)
inline infix fun Long.v(exponent: Int): Double = this.toDouble().pow(exponent)
inline infix fun Long.v(exponent: Long): 
      Double = this.toDouble().pow(exponent.toDouble())
inline infix fun Long.v(exponent: Double): 
      Double = this.toDouble().pow(exponent)

inline usage generates no extra load in runtime, even inside heavier loops.

Unfortunately, the damaged operator precedence forces you to surround the power operation with parentheses. And the compiler forces you flank with spaces.

After all, what gives the best look?

This?

var k=2  
...
println((k v 5)+3)

Or this?

var k=2
 ... 
println(k.toDouble().pow(5) + 3)

I vote on the fist option!.

Upvotes: 5

hotkey
hotkey

Reputation: 147901

Unfortunately, you cannot define new operators, there's only a predefined set of those that can be overloaded. Some operators might be added to this set later, there's an open issue for that in the Kotlin issue tracker.

However, you can use backticked names to define infix extension functions which look like operators (much less pretty though):

infix fun Int.`^`(exponent: Int): Int = ... 

Usage:

5 `^` 3

Note that infix functions have precedence lower than that of operators, thus

1 + 1 `^` 3 == 8

Upvotes: 34

JB Nizet
JB Nizet

Reputation: 691645

No. Kotlin only allows overloading a predefined set of operators, as indicated in the documentation. And ^ is not one of them (it's not even an operator AFAIK, so it can't be overloaded).

Upvotes: 0

Related Questions