if i do in Kotlin:
val newInstant = Instant.now() - Duration.ofMinutes(10)
it seems to work as expected, ie 10 mins are subtracted from the current time.
However, I want to know how is this possible since Instant is a java class and doesnt implement the operator overloading functions of Kotlin. So what Kotlin mechanism is being used to implement the minus operator in the expression?
Instant has public Instant minus(TemporalAmount amountToSubtract) method, which is used as binary operator -.
Since Java has no way of marking methods for which it makes sense to use the operator syntax, Kotlin allows using any Java methods with the right name and signature as operator overloads and other conventions (invoke() etc.) Calling Java methods using the infix call syntax is not allowed.
https://kotlinlang.org/docs/reference/java-interop.html#operators,
https://kotlinlang.org/docs/reference/operator-overloading.html
Related
I am learning about higher order functions[HOF] and lambda in Kotlin.
I checked the Kotlin docs but didn't understand it, I found one benefit of HOF:
You can perform any operations on functions that are possible for other non-function values.
so, What are 'non-functional values'?
and What are those 'operations'?
In a higher order function if a lambda is taking two parameters and returning a value, then can't we just use a function for it?
and what is the real scenario when we have return a function?
I have seen real programs in Kotlin, but I haven't seen any use of lambda or HOF in them.
I want to understand why, else many of the features would just go unused.
It's just a part of the Kotlin syntax that makes it more concise and understandable.
For example, try to imagine this code without using lambdas and HOF like map, filter etc:
val sum = listOfInts.filter{it % 2 == 0}.map{it*it}.sumOf{it % 10}
Type-safe builders is a cool thing too.
These functions are widely used in many libraries and frameworks, like Compose by Google. The first thing I remembered - State hoisting pattern.
I am reading Kotlin in Action 2nd edition.
Chapter 3 says:
If the class has a member function with the same signature as an extension function, the member function always takes precedence
At the same the book demonstrates the CharSequence.split Kotlin's stdlib extension function (which API is less confusing than an API of Java's String#split).
The thing I do not understand is how this split extension functions takes precedence on the following call:
"12.345-6.A".split(".") // <-- Kotlin's extension function gets invoked here even though there is a member function on String class in Java with matching signature
The book also leaves the following comment on this case:
Kotlin hides the confusing method and provides as replacements several overloaded extensions named split that have different arguments
How does Kotlin hide a member function? Can I also shadow some member function which I do not like with my custom extension function? Or it is a trick which is only available to Kotlin language developers?
Actually Kotlin has a separate implementation of CharSequence and String.
These kotlin String/Charsequence does not have its split function. Kotlin team has made all those string implementation functions separately with help of extension functions.Your string will be referring to kotlin String instead of Java String.
If you need to create java String, you need to refer String with package like below.
var str : java.lang.String = java.lang.String("a b c")
str.split("")
Here it will always call Java split function.
Even if you create split function for java.lang.String , it will call only member function as you have read.
member function always takes precedence
What would be the best way to convert Java Optional to Arrows Option? I was expected to have something out-of-box, but it's not there. Something like:
fun <T> Optional<T>.toOption(): Option<T> = if (this.isPresent) Some(this.get()) else none()
There is no such function at the moment, but such a contribution would be welcomed!
Arrow however does not recommend using Option unless absolutely necessary. The only use-case being nested nulls, which is the limitation for ReactiveX implementation of RxJava & Project Reactor. Both libraries don't allow null being used for their generic value A in Flowable, Flux, Mono, etc.
Analogue, you cannot use null as an empty signal for generic code in Kotlin. Unless A is constraint to be non-null by using A : Any.
Only in both cases should you use Arrow's Option, otherwise using Kotlin's nullable type is recommended by the Arrow maintainers.
Kotlin is one of the languages that allow us to easily define behavior for various predefined operators, operation named operator overloading - https://kotlinlang.org/docs/reference/operator-overloading.html
My question is regarding the overloading part of the operation.
From what I see default the language only declares operators for the basic types - https://github.com/JetBrains/kotlin/blob/01a613dca4042dde8d2374ff0e6610cb9eddc415/core/builtins/native/kotlin/Primitives.kt
If I'm reading this correctly our custom types would not have any of this special methods - operators available by default. And indeed if we're to try
class A { }
val a = A()
System.out.println(a + a)
the compiler would try to find a suitable operator plus method to call but ultimately give a compilation error.
But if we do declare our own operator plus method
class A {
operator fun plus(other: A) = "Hello!"
}
val a = A()
System.out.println(a + a)
we would indeed have "Hello!" printed.
The above mechanism is called "operator overloading" but without a previous method with the same name we do not in fact use the OOP method overloading we all are accustomed to - https://en.wikipedia.org/wiki/Function_overloading.
So between the two mechanisms - operator overloading and method overloading there is really no connection, other than an unfortunate name clash?
Looks like you are confused about operators in general.
The thing about operators is that they are just inline functions and the operator keyword is just a language construct to give you the ability to group operators with classes.
Where you can find answers about this is definitely the source code. If we take a look at the tests, we can find the following:
// "Create local variable '-'" "false"
// ACTION: Create extension function 'A.minus'
// ACTION: Create member function 'A.minus'
// ACTION: Replace overloaded operator with function call
Sadly, I cannot find the source code where operator is transformed, but most certainly this must be the procedure where the operator overload is replaced with function call.
I try to write a type-safe wrapper for a JavaScript library.
I need to call a method from JavaScript with variable arguments
(e.g. method(args...)).
The Kotlin fun for this should work with variable arguments, too.
Because Kotlin supports a spread operator, I tried to use it, but Kotlin do not want this.
Example code:
val jsLibrary: dynamic = require("library") // library given by node's require here
fun method(vararg args: String) = jsLibrary.method(*args)
Edit: Forgot to write spread operator '*' in code already. Compiler returns error because of the spread operator.
The Kotlin compiler returns the error "Can't apply spread operator in dynamic call".
Any ideas how to implement a wrapper like this, or do I need any workaround?
Thanks for your help!
Use external fun with #JsModule annotation
#JsModule("library")
external fun method(vararg args: String): LibraryMethodReturnType
This will do require("library") for you under the hood. You'll have proper Kotlin types instead of dynamic right away. You'll have no "wrappers", meaning no extra JavaScript call at runtime.
There is a hacky solution if for you want to manually use require and dynamic types: use apply method to pass all the arguments as an array.
val jsLibrary: dynamic = require("library")
fun method(vararg args: String) = jsLibrary.method.apply(null, args)