How to (force) overloading of plus for integers in Kotlin? - kotlin

I would like to make plus mean something else, than addition. For example, creation of lazy expressions for computational graph. Unfortunately, class extensions cant override member functions. The following code will print 3:
operator fun Int.plus(other: Int) = listOf(this, other)
fun main() {
println( 1 + 2 )
}
Is is possible to force overriding?

No it is not possible. 1 + 2 is lowered into 1.plus(2), and there is a well defined order in how the compiler finds an appropriate plus method. Specification:
If a call is correct, for a callable f with an explicit receiver e
of type T the following sets are analyzed (in the given order):
Non-extension member callables named f of type T;
Extension callables named f, whose receiver type U conforms to type T, in the current scope and its upwards-linked scopes, ordered
by the size of the scope (smallest first), excluding the package
scope;
[...]
[...]
When analyzing these sets, the first set which contains any
applicable callable is picked for c-level partition, which gives us
the resulting overload candidate set.
So the plus method that is declared in Int is always found first, and the search stops there. Any extension you define will be ignored.
Hypothetically, if the built-in Int.plus is an implicitly imported extension function, then your code would have worked! Implicitly imported extensions are #6 on that list :)
My workaround for this situation is to use the "declare functions with almost any name by adding backticks" feature:
infix fun Int.`+`(other: Int) = listOf(this, other)
fun main() {
println( 1 `+` 2 )
}
This wouldn't work for some names that have reserved characters like square brackets, angle brackets, slashes, and dot (not an exhaustive list).

Related

Why functions have priority over the Property-like callables in the same scope?

I just noticed something interesting when testing a code and I would like more explanation.
Why functions have the priority over lambdas when they are in the same scope ?
For example :
fun sum(x: Int, y:Int) = x + y
val sum = { x: Int, y: Int -> x + y }
// here, the compiler use the fonction (first line) and not the lambda
println(sum(1, 2))
In this case, I use invoke() to call the lambda instead of the function.
The Overload resolution section of kotlin language specification does touch on this, it states
When calculating overload candidate sets, member callables produce the
following separate sets (ordered by higher priority first):
Member function-like callables;
Member property-like callables.
but the specification still seems to be a work in progress as it contains a lot of TODO's, one specific TODO that would be relevant to your question is in the Callable references section
TODO(We might get new ambiguity between props and funs with the same
name)
So it seems to get a definite answer, you will have to wait until the language specification matures.

Kotlin: what does annotation (acc: S, T) -> S mean?

I'm very new to Kotlin. I looked at Kotlin's source code and I saw this prototype:
public inline fun <S, T : S> Iterable<T>.reduce(operation: (acc: S, T) -> S): S
I understand that operation is a method, 'acc' is one its arguments, 'acc' is of type S and the return value of operation is of type S. However, what does the T inside list of arguments mean?
Where is its arguments?
Naming the function parameters in a function type is optional. The names are only significant for documentation purposes.
What the above says is that reduce expects a function taking an S (the accumulated value) and a T (the current element). They gave the S the name acc, but didn't give the T any name.
(acc: S, T) -> S is a type.
In Kotlin, functions are first-class types.  Some types have a simple name, such as String or Int.  Others need parameters, such as List<URL> or Map<Int, String>.  Function types have even more complicated names, of the form:
        (params) -> returnType
So a function which takes a single Int parameter and returns a String would have the type (Int) -> String.
You can also give names to the parameters if you want, e.g. (count: Int) -> String, though the name is ignored.
So in your example, the reduce() method takes a single parameter, called operation.  That parameter is a function which itself takes two parameters (the first called acc of type S, and the second of type T with no name), and returns a value of type S.
What's particular confusing in your case is that S and T are type parameters: they refer to types that aren't known yet.  When the reduce() method is called, the caller will specify them (or the compiler will infer them).  That's what the <S, T : S> after the fun means: the method needs two type parameters: S, and T (which must be S or a subtype).

How do I read / interpret this Kotlin code effectively?

I know how to read/interpret Java code and I can write it. However being new to kotlin I find code like below hard to read. Perhaps I am missing key concepts in the language.
But, how would you go about interpreting this code? Where do you propose one to start reading it in order to understand this piece of code quickly and efficiently? Left to right? Right to left? Break down parameters first? Look at return values?
inline fun <T : Any, R> ifNotNull(input: T?, callback: (T) -> R): R? {
return input?.let(callback)
}
So, like Java this is a generic function. It has two type parameters T which is of type 'Any' ('Any' is like 'Object' in Java) and R. The input parameter is a nullable T, as denoted by the question mark. Nullable types mean that the value can be null. The other function parameter is a function that takes in a T (non nullable type) and returns R. The return type of the function is a nullable R. The body of the function says that if input is not null, call and pass that to the callback and return that value. If input is null, then null is what gets returned.
Let's dissect the function definition piece by piece:
inline: Indicates that the code of the function will be copied directly to the call site, rather than being called like a normal function.
fun: We're defining a function.
<T : Any, R>: The function takes two generic type parameters, T and R. The T type is restricted to the Any type (which is Kotlin's Object-type). That might seem redundant, but what it actually says is that T cannot be a nullable type (Any?).
ifNotNull: The name of the function.
input: T?: The first parameter of type T?. We can put the ? on the T type here because we restricted it to non-nullable types in the type declaration.
callback: (T) -> R: The second parameter is of type (T) -> R, which is a function type. It's the type of a function that takes a T as input and returns an R.
: R?: The function returns a value of type R or null.
return input?.let(callback): The function body. The let function takes a function parameter, calls it with its receiver (input), and then returns the result of the function. The ? after input says that let will be called only if input is not null. If input is null, then the expression will return null.
The function is equivalent to this Java method (except for the inlining and nullable types):
public <T, R> R ifNotNull(final T input, final Function<T, R> callback) {
if (input == null) {
return null;
}
return callback.apply(input);
}
Matt's answer explains everything well in one go; I'll try to look at how you might go about reading such code.
Skipping over the first word for now, the most important thing is the second word: fun.  So the whole thing is defining a function.  That tells you what to expect from the rest.
The braces tell you that it's a block function, not a one-liner, so the basic structure you're expecting is: fun name(params): returnType { code }.  The rest is filling in the blanks!  (This fits the general pattern of Kotlin declarations, where the type comes second, after a colon.  The Java equivalent would of course be more like returnType name(params) { code }.)
As with Java, the stuff in angle brackets is giving generic parameters, so we can skip that for now and go straight to the next most important bit, which is the name of the function being defined: ifNotNull.
Armed with those, we can read the rest.  inline is a simple modifier, telling you that the function will be inlined by the compiler.  (That enables a few things and restricts a few others, but I wouldn't worry about that now.)
The <T : Any, R> gives the generic parameter types that the function uses.  The first is T, which must be Any or a subtype; the second is R, which is unrestricted.
(Any is like Java's Object, but can't be null; the topmost type is the related Any?, which also allows null.  So except for the nullability, that's equivalent to the Java <T extends Object, R>.)
Going on, we have the function parameters in parentheses.  Again, there are two: the first is called input, and it's of type T?, which means it accepts any value of type T, and also accepts null.  The second parameter is called callback, and has a more complicated type, (T) -> R: it's a function which takes a T as its parameter, and returns an R.  (Java doesn't have function types as such, so that probably looks strangest.  Java's nearest equivalent is Function<R, T>.)
After the parentheses comes the return type of this function itself, R?, which means it can return either an R or null.
Finally, in braces is the actual code of the function.  That has one line, which returns the value of an expression.  (Its effect is to check whether the value of input is null: if so, it returns the null directly.  Otherwise, it calls the callback function given in the parameter, passing input as its parameter, and returns its result.)
Although that's a short declaration, it's quite abstract and packs a lot in, so it's no wonder you're finding it hard going!  (The format is similar to a Java method declaration — but Kotlin's quite expressive, so equivalent code tends to be quite a bit shorter than Java.  And the generics make it more complex.)  If you're just starting to learn Kotlin, I'd suggest something a bit easier :-)
(The good news is that, as in Java, you don't often need to read the stdlib code.  Although Kotlin's doc comments are rarely up to the exemplary level of Java's, they're still usually enough.)

When exactly is the operator keyword required in Kotlin?

In the 14th Kotlin Koan on operator overloading, I was suprised when after solving I viewed the answer and saw that the operator modifier was not required on the compareTo method:
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
override fun compareTo(other: MyDate) = when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}
}
The operator overloading docs linked to from the exercise explicitly says:
Functions that overload operators need to be marked with the operator
modifier.
So what's going on here? Why does this code compile? When exactly is operator required?
Why does this code compile?
This compiles because the overridden interface method, Comparable<T>.compareTo, is itself an operator fun.
/**
* Compares this object with the specified object for order. Returns zero if this object is equal
* to the specified [other] object, a negative number if it's less than [other], or a positive number
* if it's greater than [other].
*/
public operator fun compareTo(other: T): Int
As the function overrides this, it is also an operator function.
When exactly is operator required?
operator in general is required whenever you wish to be able to use a function as if it were an operator, since operator usages are simply compiled to function calls (except on primitive types, etc.)
That is, foo += bar, for example, is equivalent to foo.plusAssign(bar), foo[bar] = baz is equivalent to foo.set(bar, baz), etc.
Personally I prefer specifying operator wherever possible even if it is not required, for readability reasons.
If MyDate were not a Comparable, and you omitted the operator modifier, comparing two dates via <, >, <=, or >= would not compile.
I couldn't find anything in the specification on this, though. However in a polymorphic sense it makes sense - why should you be able to write a < b where the type of a and b are Comparables, but not when they are a MyDate? Since you wouldn't be able to remove the "operator-ness" of this function, it makes sense that operator should be inheritable from the superclass method.
Kotlin has many features that are enabled via particular conventions. Those can be identified by the use of an operator keyword. Examples are ranges, operator overloads, index operators, destructuring declarations and more.
If we want to compare two objects in Java, for sorting e.g., we implement the Comparable interface with its compareTo method. This is also done in Kotlin, but with much better support and a shorthand syntax. If you implement this method in a class, you can use all the nice operators like <, <=, >, >= with that class out of the box. These operators are translated to appropriate calls of compareTo by the compiler:
obj1 > obj2 ⇒ obj1.compareTo(obj2) > 0
The interface method compareTo in Comparable already defines the operator keyword, which makes it redundant to add the keyword in your own implementation.
In your example, the operator keyword is not mandatory since the overridden method already defines it.
In Java, operators are tied to specific Java types. For example, String and numeric types in Java can use the + operator for concatenation and addition, respectively. No other Java type can reuse this operator for its own benefit. Kotlin, on the contrary, provides a set of conventions to support limited Operator Overloading.
Let’s start with a simple data class:
data class Point(val x: Int, val y: Int)
We’re going to enhance this data class with a few operators.
In order to turn a Kotlin function with a pre-defined name into an operator, we should mark the function with the operator modifier. For example, we can overload the “+” operator:
operator fun Point.plus(other: Point) = Point(x + other.x, y + other.y)
This way we can add two Points with “+”:
val p1 = Point(0, 1)
val p2 = Point(1, 2)
println(p1 + p2)
Point(x=1, y=3)

Kotlin: What do the unary plus/minus operators do on numbers?

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()
fun main(){
var a = 34
var b = 56
println("Orignal value:"+ a)
println("Orignal value:"+ b
//The value will not change using .unaryPlus() will generate bytecode
println("After unary plus:" + a.unaryPlus())
//The value will invert the sign using .unaryMinus() will generate bytecode
println("After unary minus:" + b.unaryMinus())
}
Solution:
Orignal value:34
Orignal value:56
After unary plus:35
After unary minus:-55