Explanation on Function literal with receiver in Kotlin - kotlin

I was following this link https://kotlin.link/articles/DSL-builder-in-Kotlin.html to understand the builder implementation in Kotlin. I didn't understand the methods inside Builder class. Method name() receives Extension Function as an argument which receives nothing and returns String. And the caller calls name { "ABC" }. If the caller is passing String to name method, how does it translate to an Extension method which returns String ?
I tried following Kotlin documentation for Function literals with receivers but all had samples which returns Unit or refers to DSL Builders. Tried googling it as well to understand but no luck in grasping the concept.

The call to name { "ABC" } is a combination of two Kotlin conventions.
There is a convention that if the last parameter to a function is a function you can omit the parenthesis. Also since there are no parameters to the lambda, "ABC" is what is returned by it.
So the caller is actually passing a lambda in the form name ({() -> "ABC"}), rather than a String.
Looking at the example in the link, it doesn't look like the receiver is necessary for name(), which is why it could be misleading.

Related

How to shadow member function with a custom Kotlin extension function? (like Kotlin stdlib does)

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

Kotlin construction: function call with additional body - what such construction means or how it is called (if I want to look it up in the docs)?

I am seeing the Kotlin code:
navController.navigate("sales_order/" + it.toString()) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
which I can describe as "function call" (navController.navigate) "with additional body" ({...}). How such construction is called (if I want to look it up in the docs) and what does it mean?
When I checked the type of navController.navigate(...) args, then there are 2 arguments. The first argument - string - is provided in () and I am trying to guess, that everything inside {...} is the content for the second argument which has type NavOptionsBuilder in this case. So, I can guess that NavOptionsBuilder has 3 arguments: 1 function call popUpTo that returns some object and 2 named arguments (launchSingleTop, restoreState) which are Boolean type.
Am I deciphering this construction right - just another way of passing arguments - or is there something deeper?
Am I deciphering this construction right
Almost. You got the beginning right, but the end is not exactly correct.
Let's start with what you got right, and throw in some vocabulary here for posterity. Indeed, you seem to be using the overload of navigate that takes 2 arguments: a string route and a builder function.
Functions in kotlin can be passed in multiple ways, but the most common (and the one used here) is passing a lambda expression. Because the syntax for lambda expressions is based on braces ({ ... }), it makes it look like blocks of code, so the Kotlin language went one step further and allowed to pass lambda expressions outside of the parentheses of the function call when the lambda is the last argument. The reason for this is exactly to allow this kind of constructions which look like their own configuration language. This is what is usually referred to as DSLs (Domain Specific Languages).
Now about what you got wrong:
So, I can guess that NavOptionsBuilder has 3 arguments
Not really. NavOptionsBuilder is the receiver of the function that is passed as the second argument of navigate. This means that, within the lambda that you pass, a NavOptionsBuilder instance is implicitly available as this.
This, in turn, means that you can access methods and properties of NavOptionsBuilder within that lambda block. This is what popUpTo, launchSingleTop, and restoreState are: methods and properties of NavOptionsBuilder - not "arguments".
You can find more general info about this here.

Could someone, please, explain me the implementation of the following "Kotlin Literal high order function"?

I am a newbie in Kotlin, I just started to learn it,
I get the following code example about literal/high order function:
fun myHigherOrderFun(functionArg: (Int)->String) = functionArg(5)
println ( myHigherOrderFun { "The Number is $it" })
prints "The Number is 5"
Which I have difficulty to understand: the function myHigherOrderFun get a lambda function as parameter but i can't understand, where is the (Int) input parameter? I see is passed in functionArg(5)... but i can't realize how is possible that?
Thanks in advance.
To start from the beginning, in Kotlin functions are first-class types, just like numbers and Strings and stuff.  So a function can take another function as a parameter, and/or return a function as its result.  A function which does this is called a ‘higher-order function’.
And that's what you have in your example!  The line:
fun myHigherOrderFun(functionArg: (Int)->String) = functionArg(5)
defines myHigherOrderFun() as a function which takes one parameter, which is itself a function taking a single Int parameter and returning a String.  (myHigherOrderFun() doesn't specify an explicit return type, so it's inferred to be a String too.)
The next line is probably where things are less clear:
println(myHigherOrderFun{ "The Number is $it" })
The first non-obvious thing is that it's calling myHigherOrderFun() with a parameter.  Because that parameter is a lambda, Kotlin lets you omit the usual (…), and use only the braces.
The other non-obvious thing is the lambda itself: { "The Number is $it" }. This is a literal function taking one parameter (of unspecified type).
Normally, you'd have to specify any parameters explicitly, e.g.: { a: Char, b: Int -> /* … */ }.  But if there's exactly one parameter, and you aren't specifying its type, then you can skip that and just refer to the parameter as it.  That's what's happening here.
(If the lambda didn't reference it, then it would be a function taking no parameters at all.)
And because the lambda is being passed to something expecting a function taking an Int parameter, Kotlin knows that it must be an Int, which is why we can get away without specifying that.
So, Kotlin passes that lambda to the myHigherOrderFun(), which executes the lambda, passing 5 as it.  That interpolates it into a string, which it returns as the argument to println().
Many lambdas take a single parameter, so it gets used quite a lot in Kotlin; it's more concise (and usually more readable) than the alternative.  See the docs for more info.

Extension function on a generic type

I am new in Kotlin and I am trying to understand type alias and functions.
I have the following example:
interface EmptyInterface
typealias GenericCase<T> = T.(EmptyInterface) -> T
val myFunctionVariable: GenericCase<String> = {
_ -> "Hello world!"
}
So far what I understand is that I extend what ever T is defined with a function that accepts as argument an EmptyInterface and returns a T.
So the myFunctionVariable is a function that should be called passing an EmptyInterface
But the following code does not compile
class a: EmptyInterface
println("${myFunctionVariable(a())}")
I need to pass a String as the first parameter:
class a: EmptyInterface
println("${myFunctionVariable("",a())}")
Why is the string needed as the first parameter? T.(EmptyInterface) -> T which in this case is String.(EmptyInterface) -> String has only 1 parameter.
Could someone please explain this?
The T. in the type T.(EmptyInterface) -> T means that this function is an extension function on T. So the regular way to call this function is to acquire a T instance, and call it on that instance, as if it was a member function. In the case of your example, where you chose T to be a String, you have to call the function on a String instance:
"foo".myFunctionVariable(a())
The syntax you've used is an alternative way to call this extension, passing in the receiver as if it was the first parameter of the function (which, at the bytecode level, it actually is):
myFunctionVariable("foo", a())
If you wish to use your function with this syntax, however, it's better to declare it to take two parameters, as this invocation of an extension function can be quite unexpected.
(There's some more info about how you can go back and forth between a function that's an extension on a type and one that takes it as a first parameter in this answer.
In the type T.(EmptyInterface) -> T, the first T is the receiver: an instance that the function is called upon, and which becomes this within the function definition.  (Similar to an extension function.)
Effectively, the receiver becomes a hidden first parameter to the function; as you discovered, if you try to call the function directly, you'll need to give it explicitly.
The language spec for it is here; some other answers may also help.

Initializing a field member in Kotlin that is a function

New to Kotlin, I have seen this code:
val myModule : Module = module {
viewModel { MyViewModel(get()) }
single { MyRepository() }
}
Looking at the Kotlin docs, it isn't clear to me what the braces mean after "module". Is module a function and the braces are used to initialize the function? If this is true, can you point me to the part in the Kotlin documentation that indicates this? I can't find anything in the docs that shows an example of this. Here is the link:
https://kotlinlang.org/docs/reference/properties.html
Note that your example seems like Koin code.
In a more general sense:
In kotlin when the last parameter of a function is another function ( see Higher order functions) you can put it outside the parenthesis, and if it is the only (non optional) parameter you can omit the parenthesis enterily.
In your example module viewModel and single are functions that take another function as their only parameter, this way you can pass the lambda defining this paramter directly without any parenthesis.
The braces mean that the module function receives a lambda as a parameter. http://kotlinlang.org/docs/reference/lambdas.html#passing-a-lambda-to-the-last-parameter