I currently have an element
val test: map <int, List <string>
I have a question which is the best way to obtain an element if
test.get (100) or test [100]
What is the difference, which has the best performance?
It is the exact same thing. In Kotlin, you can override operators. [] is the get operator, so the resulting jvm byte code will be exactly alike.
You can do the same thing with other operators, e.g. plus:
val x = 3 + 2
is the same thing as
val x = 3.plus(2)
If you are using an IDE like IntelliJ, you can CTRL-click on the [] or the + operator and on the get() and plus() function respectively and you will see that you end up at the same place.
Related
I gave Kotlin a try, because it's supposed to be a java without certain limitations like checked exceptions or no support for operator overriding (of course these limitations got their right to exists, like reduction of abusing or forced verbosity, but this question isn't why they should (not) exist). So I wrote a simple Vector2 class, which should support basic operators like +-*/.
There isn't a problem when your first and second operand both are from the type Vector2, but there is a problem when the first operand isn't from type Vector2. Take this example:
fun main(args: Array<String>) {
val vector = Vector2(2.0, 3.0) * 2.0
}
This works flawless because of this method in Vector2:
operator fun times(d: Double) = Vector2(x * d, y * d)
But what am I supposed to do if the two operands change place like this:
fun main(args: Array<String>) {
val vector = 2.0 * Vector2(2.0, 3.0)
}
I though of an operator overload of times() for the type Double:
// In 'Vector2.kt'
operator fun Double.times(vector: Vector2) = ...
but I don't know how to retrieve the double value to multiply it with the vector.
Could anybody help? Thanks in advance!
When you define an extension function, the receiver (the object the function is called on) is always available as this, in the body of your implementation.
operator fun Double.times(vector: Vector2): Vector2 = vector * this
You could implement that any way you'd like, I just reversed the operands to shorten the example.
Recently I was working with lists in kotlin and had the following snippet:
a = listOf(1, 2, 3, 4)
println(a[-2])
Of course this causes an IndexOutOfBoundsException so I thought it would be nice to extend this functionality. So I thought one could override the get operator in the List class:
operator fun <T> List<T>.get(index: Int): T =
// Here this should call the non-overridden version of
// get.
get(index % size)
I understand that extensions are just static methods and therefore cannot be overridden, but is there a way one can achieve something like this?
Of course you could just create another function
fun <T> List<T>.safeGet(index: Int): T = get(index % size)
but I'd like to know if there are other ways.
(I understand that index % size is a very naive way of doing what I want, but it's not the focus of my question and makes the code smaller.)
EDIT
When I wrote this question I thought the % operator would return always positive numbers when the right hand side is positive - like in python. I'm keeping the original question here just for consistency.
Since get operator is already defined in List, you cannot redefine get (with one Int parameter).
However, you can override invoke operator, which is not defined in List.
fun main(args: Array<String>) {
val a = listOf(1, 2, 3, 4)
println(a(-2))
}
// If `index` is negative, `index % size` will be non-positive by the definition of `rem` operator.
operator fun <T> List<T>.invoke(index: Int): T = if (index >= 0) get(index % size) else get((-index) % (-size))
although I think that creating a new extension method to List with an appropriate name will be more preferable option.
As a sidenote, (positive value) % (negative value) is non-negative, and (negative value) % (positive value) is non-positive.
% in Kotlin corresponds to rem in Haskell in the following example: https://stackoverflow.com/a/28027235/869330
You're trying something impossible, because extensions are always shadowed by members, even #JvmName cannot save you.
Workaround: use your second solution, or add a Unit parameter which is ugly (looks like a[x, Unit]) but can exist with its own get method together.
Another solution: create your own List implementation (recommended).
I'm trying to write a fast json parser for JVM in kotlin.
And I found this issue, I'm not sure this is a bug or any good reason behind this.
val x: Long = -9223372036854775808L // compile error
this is marked as a bug in kotlin KT-17172.
as you can see the stdlib using the code as below:
public const val MIN_VALUE: Long = -9223372036854775807L - 1L
are you remember unary operator - in kotlin? if you divide the MIN_VALUE into special parts you may see it clearly. for example:
val x: Long = -(9223372036854775808L);
// ^--- the value overflow since the MAX_VALUE is 9223372036854775807L
Let's imagine something like this:
var num: Float = 0.0f
num = 2.4 * 3.5 / 3.8
num has several decimals, but I want only 2.
In JS I would use num.toFixed(2).
Other answers here suggest to use "%.2f".format(num) or num.format(2). The latter needs a custom extension fun:
fun Double.format(digits: Int) = java.lang.String.format("%.${digits}f", this)
However, any of these options leads to a compiler error of "unresolved reference". I don't think is a question of imports cause the compiler would suggest it.
Is there an easy way to do this?
Kotlin standard library for JS doesn't have anything like Double.format yet, but you can implement it easily with aforementioned toFixed function available in javascript:
fun Double.format(digits: Int): String = this.asDynamic().toFixed(digits)
fun Float.format(digits: Int): String = this.asDynamic().toFixed(digits)
This works because Double and Float in Kotlin are represented with Number data type in JS, so you can call toFixed() function on instances of those types.
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