Why destructuring declaration cannot be used in when expression? - kotlin

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.

Related

Is it possible to omit a type parameter in Kotlin?

I'm translating a very old and big Java server to Kotlin, and I'm trying to make as few logic changes as possible during the conversion. I'm looking for a way to translate this snippet of Java code without fundamentally changing it.
Consider the following toy code:
interface Pet
class Dog : Pet
class Cat : Pet
class PetSitter<T : Pet> {
fun walk(pet: T) {}
}
fun main() {
val sitters: Array<PetSitter<*>> =
arrayOf(PetSitter<Cat>(), PetSitter<Dog>())
sitters[0].walk(Cat()) // Type mismatch.
// Required: Nothing
// Found: Cat
}
This fails to compile with the message Type mismatch: inferred type is Cat but Nothing was expected.
In Java the following works fine:
PetSitter[] sitters = ... // Note: PetSitter's generic is omitted
sitters[0].walk(new Cat());
Is it possible to similarly define a Array<PetSitter> (with no pet generic) in Kotlin? Or some other way to make the parameter type for PetSitter<*>.walk to be Pet instead of Nothing?
In Java, this is called a raw type. It is only supported by necessity for backward compatibility, and it is discouraged to ever use, because it defeats the purpose of using generics. For the same reason, Kotlin forbids it outright because it doesn't have a pre-generics version of the language it must support.
The equivalent of using a raw type is to cast the types to be permissive. This requirement is to force you to consider if the cast is appropriate.
(sitters[0] as PetSitter<Cat>).walk(Cat())
Update: see https://stackoverflow.com/a/70114733/2875073 which is simpler.
It seems Kotlin doesn't allow raw types, but it looks like a work-around is to cast my instance of Pet to Pet and then make a when case enumerating each subtype and casting sitters[0] for each case:
val myPet: Pet = Cat()
when (myPet) {
is Dog -> (sitters[0] as PetSitter<Dog>).walk(myPet)
is Cat -> (sitters[0] as PetSitter<Cat>).walk(myPet)
}

How to keep use cases and entity layer in Functional Clean Architecture pure when having database read/write interactions?

Intro
I've been diving into functional programming in the last few months, and since I'm really intrigued by the Kotlin language, I've been using the Arrow library to toy around with a few things.
A few weeks ago, I've been researching for a guest lecture at university on Clean Architecture and while doing so, I stumbled upon this great blog Post by Mark Seemann, describing how using functional programming automatically leads to Clean Architecture (or with a language like Haskell may the compiler may even enforce Clean Architecture).
That inspired me to come up with a draft (checkout and build of the repo should be a breeze, if you're interested) of a restaurant reservation Software (staying true to Mark Seemann's domain ;) ). However, I'm not entirely sure if the use case layer in this draft can be called pure, and I wanted some feedback from people with more experience and knowledge with FP than myself.
Entity layer
A basic use case is trying to create a new reservation for a certain number of seats in our restaurant. I've modelled the entity layer for that the following way:
fun reservationPossible(
requestedSeats: Int,
reservedSeats: Int,
capacity: Int
): Either<RequestedTooManySeats, ReservationPossible> =
if (reservedSeats + requestedSeats <= capacity) {
ReservationPossible(requestedSeats + reservedSeats).right()
} else {
RequestedTooManySeats.left()
}
const val CAPACITY = 10
object RequestedTooManySeats : Error()
sealed class Error
data class ReservationPossible(val newNumberOfReservedSeats: Int)
Nothing too fancy going on here, just a function checking if a reservation with a certain number of requested seats would be possible or not. Some Error and Result classes are also down below as well as a (for the sake of simplicity) const val to model the capacity of our restaurant.
Frameworks/Adapters #1
To make sense in a real world application, some data would also need to be stored in and loaded from some sort of persistence layer. So, in the outermost layer of our onion architecture, there would be a Database which I mocked for this example:
suspend fun getCurrentlyReservedSeats(): Either<ReadError, Int> {
delay(1) // ... get stuff from db
return 4.right()
}
suspend fun saveReservation(value: String, reservationPossible: ReservationPossible): Either<WriteError, Long> {
delay(1) // ... writing something to db
return 42L.right() // newRecordId
}
abstract class DbError : Error()
object ReadError : DbError()
object WriteError : DbError()
Again, not too much going on here... Just stubs for Database read/write ops. Note however, that (by convention proposed by Arrow) these functions are marked with the suspend modifier as impure functions.
Use Case
So now for the use case, which basically describes our application flow:
get number of currently reserved seats from DB
check if the requested number of seats is still available
if so, persist the new reservation
and return the newly created reservation id
which is translated to code in the reservationUseCase function:
data class UseCaseData(
val requestedSeats: Int,
val reservationName: String,
val getCurrentlyReservedSeats: suspend () -> Either<ReadError, Int>,
val writeVal: suspend (String, ReservationPossible) -> Either<WriteError, Long>,
)
fun reservationUseCase(data: UseCaseData): suspend () -> Either<Error, UseCaseResultData> = {
data.getCurrentlyReservedSeats()
.flatMap { reservationPossible(data.requestedSeats, it, CAPACITY) }
.flatMap { data.writeVal(data.reservationName, it) }
.flatMap { UseCaseResultData(it).right() }
}
data class UseCaseResultData(val newRecordId: Long)
Here is the point, where it gets interesting: This function takes some UseCaseData as input and returns a suspend function to be executed at the program entry like this:
suspend fun main() {
reservationUseCase(
UseCaseData(
requestedSeats = 5,
reservationName = "John Dorian",
::getCurrentlyReservedSeats,
::saveReservation,
)
).invoke().fold(
ifLeft = { throw Exception(it.toString()) },
ifRight = { println(it.newRecordId) },
)
}
So now my questions are:
Can the reservationUseCase function itself be considered pure? I've read some blog post (taking F# as example language, however) suggesting that pure functions which receive impure functions as parameters could be pure, but cannot be guaranteed to be pure. reservationUseCase in this example clearly does receive impure functions with the UseCaseData.
If it can't be considered pure, how could one write a pure use case like the one described above in Kotlin and Arrow?
As you already assume, strictly speaking, reservationUseCase is not a pure function.
The only way I see how you could make it a pure function is to pass all the needed data directly instead of a function which provides access to that data but I doubt that this makes your code finally more clean or nicer to read.
This would lead to the conclusion that use case functions which orchestrate "workflows" can rarely be pure as almost always some interaction with some kind of repository is needed.
If you want some core logic to be pure you would have to extract those into functions which again only accept and return pure data.

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")

Kotlin benifits of writing helper/util methods without wrapping in class

There are can be two ways of writing helper method in Kotlin
First is
object Helper {
fun doSomething(a: Any, b: Any): Any {
// Do some businesss logic and return result
}
}
Or simply writing this
fun doSomething(a: Any, b: Any): Any {
// Do some businesss logic and return result
}
inside a Helper.kt class.
So my question is in terms of performance and maintainability which is better and why?
In general, your first choice should be top-level functions. If a function has a clear "primary" argument, you can make it even more idiomatic by extracting it as the receiver of an extension function.
The object is nothing more than a holder of the namespace of its member functions. If you find that you have several groups of functions that you want to categorize, you can create several objects for them so you can qualify the calls with the object's name. There's little beyond this going in their favor in this role.
object as a language feature makes a lot more sense when it implements a well-known interface.
There's a third and arguably more idiomatic way: extension functions.
fun Int.add(b: Int): Int = this + b
And to use it:
val x = 1
val y = x.add(3) // 4
val z = 1.add(3) // 4
In terms of maintainability, I find extension functions just as easy to maintain as top-level functions or helper classes. I'm not a big fan of helper classes because they end up acquiring a lot of cruft over time (things people swear we'll reuse but never do, oddball variants of what we already have for special use cases, etc).
In terms of performance, these are all going to resolve more or less the same way - statically. The Kotlin compiler is effectively going to compile all of these down to the same java code - a class with a static method.

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)