Properly Reading and Understanding Documentation - kotlin

While looking at examples of Kotlin code I cam across this:
fun main(args: Array<String>) {
val myList = List(3) {it + 1}
println(myList)
}
I understand what it does, but I didn't know a List could be constructed this way. When I reference the documentation (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html) to see other possible ways to construct a List, I don't see any constructors at all. I can only assume I'm not looking in the right spot.
How do I go about properly reading documentation for Kotlin? Shouldn't everything pertaining to a List be contained in one place?

Since List is only an interface, it cannot have any constructors - it's a global function.
Most IDEs (like IntelliJ) should let you "ctrl+left click" or otherwise navigate to the source.
This is the related package: kotlin.collections.
And function you refer to: List.

Related

Kotlin data class equality when one of the properties is a function

I wonder if a data class with one of the properties being a function, such as:
data class Holder(val x: Data, val f: () -> Unit)
can work at all, since the following test fails.
val a = {}
val b = {}
Assert.assertEquals(a, b)
Update: Use case for this could be to have a
data class ButtonDescriptor(val text: String, val onClick: () -> Unit)
and then flow it to UI whilst doing distinctUntilChanged()
I don't think this is possible, I'm afraid.
You can of course check reference equality (===, or == in this case because functions don't generally override equals()).  That would give you a definite answer where you have references to the same function instance.  But that doesn't check structural equality, and so reports the two lambdas in the question as different.
You can check whether the two functions are instances of the same class by checking their .javaClass property.  If the same, that would imply that they do the same processing — though I think they could still have different variables/captures.  However, if different, that wouldn't tell you anything.  Even the simple examples in the question are different classes…
And of course, you can't check them as ‘black boxes’ — it's not feasible to try every possible input and check their outputs.  (Even assuming they were pure functions with no side effects, which in general isn't true!)
You might be able to get their bytecode from a classloader, and compare that, but I really wouldn't recommend it — it'd be a lot of unnecessary work, you'd have to allow for the difference in class names etc., it would probably have a lot of false negatives, and again I think it could return the same code for two functions which behaved differently due to different parameters/captures.
So no, I don't think this is possible in JVM languages.
What are you trying to achieve with this, and could there be another way?  (For example, if these functions are under your control, can you arrange for reference equality to do what you need?  Or could you use function objects with an extra property giving an ID or something else you could compare?)
When you create your data class, if you pass the function by reference it will work with DiffUtils and distinctUntilChanged(). Function references do not break the isEquals() method of data classes in the same way that a lambda does.
For example, you create a function for your onClick:
private fun onClick() { // handle click }
and create your data class like
BottomDescriptor("some text", ::onClick)

Create an object of random class in kotlin

I learned java and python in high school and I became very comfortable with python. I have recently started to learn kotlin, mainly for fun (the keyword for defining a function is fun so it has to be a fun language, right), but I have a little problem.
Let's suppose I have a hierarchy of classes for Chess pieces:
abstract class Piece {
...
}
class Rook : Piece() {
...
}
class Bishop : Piece() {
...
}
.
.
.
I am taking input from the user to generate the board, so if the user types r, I need to create a Rook object, if he types b, I need to create a Bishop etc.
In python, I'd probably use a dictionary that maps the input string to the corresponding class, so I can create an object of the correct type:
class Piece:
...
class Rook(Piece):
...
class Bishop(Piece):
...
.
.
.
input_map = {
'r': Rook,
'b': Bishop,
...
}
s = input_map[input()]() # use user input as key and create a piece of the correct type
I was really amazed by this pattern when I discovered it. In java, I had to use a switch case or a bunch of if else if to achieve the same result, which is not the end of the world, especially if I abstract it into a separate function, but it's not as nice as the python approach.
I want to do the same thing in kotlin, and I was wondering if there is a similar pattern for kotlin since it's a modern language like python (I know, I know, python isn't new, but I think it's very modern). I tried to look online, but it seems like I can't store a class (class, not an object) in a variable or a map like I can in python.
Am I wrong about it? Can I use a similar pattern in kotlin or do I have to fall back to the when statement (or expression)?
If I am not mistaken, a similar pattern could be achieved in java using reflection. I never got to learn reflection in java deeply, but I know it's a way to use classes dynamically, what I can do for free in python. I also heard that in java, reflection should be used as a last resort because it's inefficient and it's considered "black magic" if you understand my meaning. Does it mean that I need to use reflection to achieve that result in kotlin? And if so, is it recommended to use reflection in kotlin, and is it efficient?
I'd like to know how I can approach this problem, and I accept multiple answers and additional solutions I didn't come up with. Thanks in advance.
This can be done without reflection.
You can map the input characters to the constructors:
val pieceConstructorsByKeyChar = mapOf(
'r' to ::Rook,
'b' to ::Bishop,
// etc.
)
Getting values from a map gives you a nullable, since it's possible the key you supply isn't in the map. Maybe this is fine, if when you use this you might be passing a character the player typed that might not be supported. Then you would probably handle null by telling the player to try again:
val piece: Piece? = pieceConstructorsByKeyChar[keyPressed]?.invoke()
Or if you do the look-up after you've already checked that it's a valid key-stroke, you can use !! safely:
val piece: Piece = pieceConstructorsByKeyChar[keyPressed]!!()
Yes you can use similiar approach with Kotlin. Kotlin has many features and supports reflection. Let me write an example about your problem.
Firstly create your classes that will be generate by user input.
abstract class Piece
class Rook : Piece()
class Bishop : Piece()
Create your class map
val inputMap = mapOf(
"r" to Rook::class.java,
"b" to Bishop::class.java
)
Create an instance what you want using newInstance function. If your input map doesn't contains key you gave then it will return null.
val rook = inputMap["r"]?.newInstance()
val bishop = inputMap["b"]?.newInstance()
// null
val king = inputMap["k"]?.newInstance()
Also you can write your custom extensions to create new objects.
fun <T> Map<String, Class<out T>>.newInstance(key: String) = this[key]?.newInstance()
// Create an instance with extension function
inputMap.newInstance("r")

A shorter way to transform enumValues to a multi-value map

New to Kotlin. I was thinking if there is a shorter way to write the following piece of code. It means to categorize enum values into a multi-value map.
fun androidPermissionsByCategory(): Map<String, List<String>> {
val result = hashMapOf<String, MutableList<String>>()
enumValues<AndroidPermission>().onEach {
result.getOrPut(it.permissionGroup, { mutableListOf() }).add(it.value())
}
return result
}
Suggestions?
That's good, solid code (especially if you're not experienced in Kotlin): good use of types, and the getOrPut() function.  (The only tweak I'd suggest would be to change hashMapOf() to mutableMapOf(), since you don't care about the exact type of map.  You could also replace the add() call with += operator, though that's more disputable.)
However, there's a shorter alternative in a more functional style:
fun androidPermissionsByCategory(): Map<String, List<String>>
= enumValues<AndroidPermission>()
.groupBy({ it.permissionGroup }, { it.value() })
(Disclaimer: I don't have Android libs, so I can't test this exactly.)
This uses the standard library's groupBy() function, which does exactly what you want: it compares items (using a key-selector lambda you provide), and uses it to create a multimap from them.
Here we're using the enum's permissionGroup field as the key.
We're also using the optional second parameter to transform the values in the multimap, in this case getting their value().
You'll find that Kotlin has functional alternatives to many of the common imperative patterns for constructing and transforming maps, lists, and similar structures; these are often more concise, more declarative, and easier to read.  Any time you find yourself looping over a list or similar, it's worth asking whether there's a better way.  (As you have here!  Your intuition is clearly working well :-)

Why does the expert change MutableList to List?

I asked a question at How to design a complex class which incude some classes to make expansion easily in future in Kotlin? about how to design a complex class which incude some classes to make expansion easily in future in Kotlin.
A expert named s1m0nw1 give me a great answer as the following code.
But I don't know why he want to change MutableList to List at https://stackoverflow.com/posts/47960036/revisions , I can get the correct result when I use MutableList. Could you tell me?
The code
interface DeviceDef
data class BluetoothDef(val Status: Boolean = false) : DeviceDef
data class WiFiDef(val Name: String, val Status: Boolean = false) : DeviceDef
data class ScreenDef(val Name: String, val size: Long) : DeviceDef
class MDetail(val _id: Long, val devices: List<DeviceDef>) {
inline fun <reified T> getDevice(): T {
return devices.filterIsInstance(T::class.java).first()
}
}
Added
I think that mutableListOf<DeviceDef> is better than ListOf<DeviceDef> in order to extend in future.
I can use aMutableList.add() function to extend when I append new element of mutableListOf<DeviceDef>.
If I use ListOf<DeviceDef>, I have to construct it with listOf(mBluetoothDef1, mWiFiDef1, //mOther), it's not good. Right?
var aMutableList= mutableListOf<DeviceDef>()
var mBluetoothDef1= BluetoothDef(true)
var mWiFiDef1= WiFiHelper(this).getWiFiDefFromSystem()
aMutableList.add(mBluetoothDef1)
aMutableList.add(mWiFiDef1)
// aMutableList.add(mOther) //This is extension
var aMDetail1= MDetail(myID, aMutableList)
Sorry for not giving an explanation in the first place. The differences are explained in the docs.:
Unlike many languages, Kotlin distinguishes between mutable and immutable collections (lists, sets, maps, etc). Precise control over exactly when collections can be edited is useful for eliminating bugs, and for designing good APIs.
It is important to understand up front the difference between a read-only view of a mutable collection, and an actually immutable collection. Both are easy to create, but the type system doesn't express the difference, so keeping track of that (if it's relevant) is up to you.
The Kotlin List<out T> type is an interface that provides read-only operations like size, get and so on. Like in Java, it inherits from Collection<T> and that in turn inherits from Iterable<T>. Methods that change the list are added by the MutableList<T> interface. [...]
The List interface provides a read-only view so that you cannot e.g add new elements to the list which has many advantages for instance in multithreaded environments. There may be situations in which you will use MutableList instead.
I also recommend the following discussion:
Kotlin and Immutable Collections?
EDIT (added content):
You can do this is a one-liner without any add invocation:
val list = listOf(mBluetoothDef1, mWiFiDef1)

Why destructuring declaration cannot be used in when expression?

Probably this question should go the authors of Kotlin, but I'm sure that on SO there are many Kotlin users with deep knowledge of its architecture.
So my question is: why the language doesn't support destructuring in when expressions?
For example I would like to have the following code:
data class Person(val name: String, val age: Int)
when (person) {
("John", _) -> print("It is John") //it won't compile
else -> print("It's not John")
}
As destructuring uses the component1, component2, etc. methods I'm curious why this simple value comparison can't be used as shown above. Is the problem in modification of when mechanism or the destructing itself?
There's an open feature ticket for that:
KT-20004: Scala-like constructor pattern matching in when statement
Also, Java is going to support data classes and pattern matching in the near future, which might have an impact on the implementation of the Kotlin version.