How to check if an object has a certain operator implemented? - kotlin

I am new with Kotlin and I am wondering if there is a method to check if a parameter object has plus operator.
For example I want complete this function:
fun <T: Any> T.plusWithOther(other: T): T {
if(T has plusOperator){
return this + other
}
return this
}

There is no general way to query for a specific operator. However, there are extension functions for the plus and minus operators.
As an example:
infix fun <T> T.add(other: T): T = this + other
So you can use add instead of plus:
fun <T: Any> T.plusWithOther(other: T): T {
if(T has addOperator){
return this add other // or plus, minus, etc. based on what you need from the function
} return this
}

Related

How to overload function with different return types and the same parameters in Kotlin?

I want to overload function with the same parameters (or without parameters at all) and different return types. Correct implementation should be chosen by the type of variable I assign returning value of a function to.
The only way to do this I found is using reified generics and comparing KClass'es:
inline fun <reified T: Any> read(): T {
return read(T::class)
}
#Suppress("UNCHECKED_CAST")
fun <T: Any> read(t: KClass<T>): T {
return when (t) {
Int::class -> readInt() as T
UInt::class -> readUInt() as T
String::class -> readString() as T
// ...
else -> throw Exception("Unsupported type")
}
}
fun readInt(): Int {
// ...
}
fun readUInt(): UInt {
// ...
}
fun readString(): String {
// ...
}
The problem with this approach is that the compiler and IDEA are not smart enough to determine types at compile time for which there is no implementation. The most I can do is throw a runtime exception:
val int: Int = read()
val string: String = read()
val double: Double = read()
// ^^^^ No compile-time error here
Maybe I'm missing something and there is more "correct" way of doing this?
Maybe I'm missing something and there is more "correct" way of doing this?
No. You cannot do this at all. You must name the methods differently.

Is it possible to make safe inline Optional in Kotlin?

In Kotlin sometimes I have to work with double nullability. For example, I need double nullability, when I want to use T? where T may be a nullable type. There are a few approaches for doing this:
Holder<T>? where Holder is data class Holder<out T>(val element: T) - example1
boolean flag variable - example1
containsKey for Map<K, T?> - example1
The special UNINITIALIZED_VALUE for representing the second kind of null - example1
The last approach has the best performance, but it's also the most error-prone. So I've decided to encapsulate it in inline class Optional<T>:
inline class Optional<out T> #Deprecated(
message = "Not type-safe, use factory method",
replaceWith = ReplaceWith("Optional.of(_value)")
) constructor(private val _value: Any?) {
val value: T?
get() =
#Suppress("UNCHECKED_CAST")
if (isPresent) _value as T
else null
val isPresent: Boolean
get() = _value != NULL
companion object {
#Suppress("DEPRECATION")
fun <T> of(value: T) = Optional<T>(value)
fun <T : Any> ofNullable(value: T?): Optional<T> =
if (value == null) EMPTY
else of(value)
#Suppress("DEPRECATION")
val EMPTY = Optional<Nothing>(NULL)
}
private object NULL
}
inline fun <T> Optional<T>.ifPresent(code: (T) -> Unit) {
#Suppress("UNCHECKED_CAST")
if (isPresent) return code(value as T)
}
inline fun <T> Optional<T>.or(code: () -> T): T {
ifPresent { return it }
return code()
}
The first problem with this Optional is public constructor, which allows creating instances with arguments of not matching type.
The second problem was noticed at testing time. Here is the failed test:
emptyOr { Optional.EMPTY }.value assertEql null
fun <T> emptyOr(other: () -> T): T = Optional.EMPTY.or(other)
Exception:
Exception ClassCastException: Optional$NULL cannot be cast to Optional
at (Optional.kt:42) // emptyOr { Optional.EMPTY }.value assertEql null
If I remove inline modifier from Optional, the test will pass.
Q: Is there any way to fix these problems without removing inline modifier from Optional?
1 Examples include some context. Please read them fully before writing that I added incorrect links.
I implemented exactly the same utility in one of my projects: OptionalValue.kt. My implementation is very similar to yours, it is also an inline/value class, so it should be cpu/memory efficient and it passes all tests I throw at it.
Regarding your first question: about a public constructor. There is an annotation specifically for this case: #PublishedApi. I tried to reproduce ClassCastException from your example, but it worked for me without problems, so I believe it was a bug in Kotlin itself (?).
Also, to answer the question why do we need double nullability, I explained my point here

Is there any difference in null checking quality between `?.apply`, `?.run` and `?.let` in Kotlin?

I know the convention is to use ?.let for null checking mutable variables because ?.let will make sure that the variable we're checking doesn't change to null in the middle of the block that's being executed. Will the same hold true for ?.apply and ?.run?
One last thing, if the variable is immutable is it recommended to just use a simple if?
Is there any difference in null checking quality between ?.apply, ?.run and ?.let in Kotlin?
Yes, they're all essentially the same when it comes to null checking quality. In fact, if you open the code for the apply, let, with, also & run. They're 'nearly' identical, they mainly differ on how the block get's executed, what argument is passed to the block and what value is returned.
inline fun <T, R> with(receiver: T, block: T.() -> R): R {
return receiver.block()
}
inline fun <T> T.also(block: (T) -> Unit): T {
block(this)
return this
}
inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
inline fun <T, R> T.let(block: (T) -> R): R {
return block(this)
}
inline fun <T, R> T.run(block: T.() -> R): R {
return block()
}
They're really just syntactic sugar, that said it'd be a good idea for you to follow some basic rules/conventions on when to use what. Take a look at article I & article II, they explain the difference between them in much greater detail than I can elaborate in this answer, along with basic conventions on when to use what.
if the variable is immutable is it recommended to just use a simple if?
Yes, in fact, if you make an if check on a val variable, then the compiler will automatically understand that the variable will never be null inside the if block.
val user: User? = null;
if (user != null) {
// user not null
val name = user.name // won't show any errors
}
var user: User? = null;
if (user != null) {
// user might be null
// Since the value can be changed at any point inside the if block (or from another thread).
val name = user.name // will show an error
}

How can I create a "forEach" that returns an object that is a receiver to the consuming function?

I'm trying to do something like this in a long chain of "stream" operations.
fun main(args: Array<String>) {
"test1, test2, test3".split(", ")
.toCustomString(StringBuilder(), StringBuilder::append)
}
fun <T, R>Iterable<T>.toCustomString(obj: R, thing: R.(T) -> Unit): R {
this.forEach {
obj.thing(it)
}
return obj
}
But this doesn't work it says none of the functions found for StringBuilder::append can't be applied here. Is there a way I can make something like this work?
You are trying to use a method reference with a different signature for a receiver function. You can make it work with supplying a lambda instead. Or as other answers point out, changing the signature of your receiver function.
fun main(args: Array<String>) {
"test1, test2, test3".split(", ")
.toCustomString(StringBuilder(), { item -> append(item) })
}
There's no problem to use a method reference in that case and it should work perfectly.
Just ensure you use kotlin class StringBuilder an change this:
fun <T, R>Iterable<T>.toCustomString(obj: R, thing: R.(T) -> Unit)
by this one:
fun <T, R>Iterable<T>.toCustomString(obj: R, thing: R.(T) -> R)
In order to use StringBuilder::append as a function reference, thing should have type R.(T) -> R instead of R.(T) -> Unit because StringBuilder.append(String) will return StringBuilder. However, since toCustomString does not handle the return value from StringBuilder.append, what #Marko suggested is more appropriate.
FYR, here is an alternative way to do it without an extra extension function:
val customString = StringBuilder().apply {
"test1, test2, test3"
.split(", ")
.forEach { this.append(it) }
}

Is there a built in Kotlin method to apply void function to value?

I wrote this method to apply a void function to a value and return the value.
public inline fun <T> T.apply(f: (T) -> Unit): T {
f(this)
return this
}
This is useful in reducing something like this:
return values.map {
var other = it.toOther()
doStuff(other)
return other
}
To something like this:
return values.map { it.toOther().apply({ doStuff(it) }) }
Is there a language feature or method like this already build in to Kotlin?
Apply is in the Kotlin standard library: See the docs here: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/apply.html
Its method signature:
inline fun <T> T.apply(f: T.() -> Unit): T (source)
Calls the specified function f with this value as its receiver and returns this value.
I ran into the same problem. My solution is basicly the same as yours with a small refinement:
inline fun <T> T.apply(f: T.() -> Any): T {
this.f()
return this
}
Note, that f is an extension function. This way you can invoke methods on your object using the implicit this reference. Here's an example taken from a libGDX project of mine:
val sprite : Sprite = atlas.createSprite("foo") apply {
setSize(SIZE, SIZE)
setOrigin(SIZE / 2, SIZE / 2)
}
Of course you could also call doStuff(this).