Higher order functions is complex? - kotlin

I have read many articles, but there are still things I am having difficulty understanding. Where's the point I can't understand? My questions are in the code. I hope I asked right.
fun main() {
/*
1- Is it argument or parameter in numbers{} block?
where is it sent to the argument? why do we send "4" if it is parameter?
Are all the functions I will write in (eg println) sent to the numbers function? But this HOF can
only take one parameter.
*/
numbers {
/*
2-How does this know that he will work 3 times?
According to the following 3 functions? Is there a for loop logic??
*/
println(it)
"4" // 3- Which one does this represent? f:(String) or ->String?
}
}
fun numbers(f: (String) -> String) {
f("one")
f("two")
f("three")
println(f(" - "))
}

There is no argument or parameter defined in your lambda block above. It's just the content of your lambda function. You've used the implicit single parameter name of it. "4" is the return value of your lambda.
The lambda itself isn't "aware" of how many times it will be called. In this case, it is called four times, because your numbers function invokes the parameter f four times.
A lambda's return value is whatever its last expression evaluates to. In this case, it returns the String "4".
Maybe this will help. Lambda syntax is a convenience. But we can take away each piece of syntactic sugar one at a time to see what it actually means.
All of the code blocks below have the exact same meaning.
Here is your original statement:
numbers {
println(it)
"4"
}
First, when a lambda omits the single parameter, it gets the implicit parameter name it. If we avoid using this sugar, it would look like this:
numbers { inputString ->
println(inputString)
"4"
}
The evaluated value of the last expression in a lambda is what it returns. You can also explicitly write a return statement, but you must specify that you are returning from the lambda, so you have to put its name. So if we put this in, it looks like this:
numbers { inputString ->
println(inputString)
return#numbers "4"
}
When a lambda is the last argument you pass to a function, you can put it outside the parentheses. This is called "trailing lambda". And if the function is the only argument, you don't need parentheses at all. If we skip this convenience, it looks like this:
numbers({ inputString ->
println(inputString)
return#numbers "4"
})
A lambda is just a very compact way of defining a function. If we define the function directly, it looks like this:
numbers(fun(inputString: String): String {
println(inputString)
return "4"
})
The function you are passing is the argument of the numbers() function. You can also define it separately and then pass the function reference like this:
fun myFunction(inputString: String): String {
println(inputString)
return "4"
}
numbers(::myFunction)

Related

Semantic operator of dot in Kotlin

I'd like to understand a bit better the 2 functions below. I know it is very compact and understand more or less what it does: it converts each characters of a string into string of '0' and '1'. But...
How does the dot(in front of encodeToByteArray) connect the 's' to encodeToByteArray()?
Where can I find more info about what dot represents?
Also, how and why the code { byte -> binaryStringOf(byte) } can do the job in that place?
How does it "know" that there is a byte with which it calls the function binaryStringOf(byte)
Where can I find more info about it, too?
fun binaryStringOf(message: String): String {
var s: String
s = (message)
.encodeToByteArray()
.joinToString("") { byte -> binaryStringOf(byte) }
return s
}
fun binaryStringOf(b: Byte): String {
return b.toString(2).padStart(8, '0')
}
The formatting above makes things a little bit more confusing, but let me try to explain what is going on.
The = is an assignment operator. It says "assign the variable s to the result of the expression on the right side".
Now we see that message is a parameter in the binaryStringOf function of type String. String is a class which contains a function (also called a method when it is a member of a class) called encodeToByteArray which returns a ByteArray.
ByteArray in turn has a function called joinToString which we're giving two parameters: one of type String, and one of type ((Byte) -> CharSequence) (ie, the function is itself being passed in as a variable, using lambda syntax). Kotlin has some syntactic sugar to make this look nicer when the lambda is the last argument.
So, the statement
s = (message)
.encodeToByteArray()
.joinToString("") { byte -> binaryStringOf(byte) }
means "the variable s is assigned the value that results from calling joinToString on the result of calling encodeToByteArray on message.
Then return s says that the return value from the binaryStringOf should be whatever value was assigned to s.
.encodeToByteArray()
works on the incoming string (message in this case). It returns a ByteArray; so something that represents an array of Byte values.
And on that array object, it invokes the joinToString() method. That method receives various arguments, but only the separator string ("") is provided, and the transform parameter.
Now: transform is a function. It is something that can be invoked, with parameters, and that has to return a specific result.
The key part to understand is that { byte -> ... } is that transform function parameter.

Having trouble passing a value in a Kotlin function. The variable being convert:(String)->R

I have some code here that reads a file and converts it to a list of a type depending what is being passed to the function. The code for this function looks like so.
fun <R> readFile(path:String,convert:(String)->R): List<R> {
val reader = BufferedReader(FileReader(File(path)))
var line = reader.readLine()
val result = mutableListOf<R>()
while(line!=null) {
result.add(convert(line))
line = reader.readLine()
}
reader.close()
return result.toList()
}
The problem I have is that I am unsure sure what to pass into the variable convert. I am trying to return back a list of Person objects back. Below is the code I tried myself to hit the function readFile
val listOfPerson = readFile("path/person.txt","Person")
With this I'm getting an error with my Type. Intellij is flagging "Required (String) -> ???"
The type (String) -> R is a function type. It represents a function that takes a String as argument and returns R (which is generic and can be different on every call to readFile()).
In order to call readFile(), you need to pass a String and a function:
readFile("path/person.txt") { line -> /* whatever you need */}
Note that in Kotlin, the { line -> ...} is a lambda expression, i.e. a function literal. This particular lambda expression represents a function that takes the argument line and does whatever is in the body.
Lambda expressions can be passed out of the parentheses of the function call, but it's still an argument to the function. The above code is equivalent to:
readFile("path/person.txt", { line -> /* whatever you need */})
In your specific case, the convert argument is a conversion function, so you need to provide some code that converts the line: String argument into whatever R type you need in the output list.
If you just want a list of the lines as strings (without conversion) you can simply provide the identity function:
readFile("path/person.txt") { line -> line }
Or in short:
readFile("path/person.txt") { it }
it is an implicit argument (a shortcut) for lambda expressions that represent functions with only 1 argument, which is the case here.

Order of execution - Kotlin

I have tried to debug the next program to understand the execution order, however I'm still confused about the execution order
fun foo(): String{
println("Calculating foo...")
return "foo"
}
fun main(args: Array<String>) {
println("First ${foo()}, Second ${foo()}!")
}
// Result:
//
// Calculating foo...
// Calculating foo...
// First foo, Second foo!
// I though the execution would show something like this:
//
// First Calculating foo...foo,
// Second Calculating foo...foo!
Isn't main the initial function to be executed?
If it is, then println would be the 1st sentence, as such (for me) the execution would start from left to right (am I correct?), so... if it is the first word to be displayed would be First ,then it would be called the foo() function and this would return "foo", that would be extrapolated to string again => ${} ... am I right ?
If not, what I'm misunderstanding ?
Thanks for any clarification.
You can think about it like this
Execute main() function.
Evaluate argument to println() function.
"First ${foo()}, Second ${foo()}!" is using string interpolation, so we need to first interpolate the string.
Interpolate first ${foo()}, by calling foo()
First foo() prints "Calculating foo..."
Interpolate second ${foo()}, by calling foo()
First foo() prints "Calculating foo..."
Now we have the interpolated string First foo, Second foo!
Execute println("First foo, Second foo!")
There are two concepts here :
The string interpolation will take the output of your function to build the output text. The println call in foo() is a side-effect, not included in return value. So, it won't be added to generated string.
println in main function will receive the result of String interpolation. Text is interpreted fully before being passed to println. That's why you see the output as is : to create the final text, kt will execute each string expression first, then builing the entire string to display, and finally pass the ready text to println function.
Code execution order is not strongly bound to the natural reading order. There is operator priority concept, also when executing a function, all its arguments must be evaluated before being passed to it (except for closures/lambda, but that's a more complicated subject). And there'smuch more rules. I can only encourage you to take a general programming courses to discover all these, because there's much to say, it would be tough to include all in a single SO answer.
Kotlin's String templates are resolved statically, and are converted to respective variable/function calls in concatenation with Strings.
A literal like "test ${foo()} test2" will be compiled as "test " + foo() + "test2" in the JVM bytecode.
Basically, your function call,
println("First ${foo()}, Second ${foo()}!")
is chopped down like:
println("First " + foo() + ", Second " + foo() + "!")
This will execute as follows:
println( "First ".plus(foo()).plus(", Second ").plus(foo()).plus("!") )
So first of all both the foo calls have been made after concatenation of all the Strings likewise in the above manner, final String is sent as an argument to the println()

When do I use another function without paramters in Kotlin?

I'm a novice of Kotlin.
I found that I can use another function without parameters even if it has.
Let me know when I can use it.
Q1) Why can I use 2 types? (with parameters & without parameters) Is it Kotlin's feature?
Q2) What does it mean? ((Result!) -> Unit)!
It seems you are confused, you can never use a function without arguments. If the function has arguments then you have to fill the slot somehow.
The closest thing that could relate to what you are referring to is default values for arguments.
fun example(boolean: Boolean = true) {}
example()
example(true)
example(false)
You can omit the argument because it has defaulted in the function signature.
The documentation
What you are showing in the image file is a lambda.
In the first example:
signIn(listener: Session...)
That seems to be a callback. So it is gonna be an interface or maybe an abstract class called when some async operation is finished.
The second example, it is the callback implemented as a lambda
signIn() { result ->
//do something
}
In Kotlin the last argument if it is a lambda or something that can be implemented as a lambda can be moved out of the parenthesis for syntactic sugar. A lambda is like an anonymous function, it is a literal of a function.
By example you can declare a lambda:
val lambda = {text: String -> text.lenght % 2 == 0}
fun setRuleForText(rule: (String)-> Boolean) {...}
setRuleForText(lambda)
setRuleForText() { text: String
text.isNotEmpty()
}
In this case, the argument is a kotlin function. The argument rule is a function that receives a String as an argument and returns Boolean. Something to point out is that expressions return the last written value without the need for the reserved return word.
This is the documentation. And here you can see from a good source more about functions (the author is a Kotlin certified trained by Jetbrains)
In your case (Result) -> Unit means the lambda should receive a Result type as argument and then return Unit (unit is like void in Java but is more than that), no explicit return type.
signIn() { result ->
//do something
}
Most of the types, the argument on lambdas is inferred automatically, but if not, then
signIn() { result: Result ->
//do something
}
Both of the listed functions take a parameter.
The first is:
signIn(listener: Session.SignInListener!)
That takes a single parameter, of type Session.SignInListener.  (The ! means that Kotlin doesn't know whether it's nullable or not, because it's from Java and isn't annotated.)
The other is:
signIn {...} (listener: ((Result!) -> Unit)!)
That's the IDE's representation of the function with this signature:
signIn(listener: ((Result!) -> Unit)!)
That takes a single parameter, which is a function type (see below).
The reason the IDE shows it with braces is that in Kotlin, if the last parameter to a function is a lambda, you can move it outside the parentheses.  So a call like this:
signIn({ println(it) })
could equally well be written like this:
signIn() { println(it) }
The two forms mean exactly the same.  And, further, if the lambda is the only parameter, you can omit the parens entirely:
signIn { println(it) }
Again, it means exactly the same thing.
That syntax allows you to write functions that look like new language syntax.  For example:
repeat (10) {
// ...
}
looks like a new form of loop construct, but it's really just a function called repeat, which takes two parameter (an integer, and a lambda).
OK, let's look at that function type: ((Result!) -> Unit)!
That's the type of a function which takes one parameter of type Result, and returns Unit (i.e. nothing useful; think of it as the equivalent of void).  Again, it's complicated because Kotlin doesn't know about the nullability; both the Result parameter and the parameter holding this function have !s to indicate this.  (Without them, it would just be (Result) -> Unit.)

How does Kotlin recognize a lambda receiver in a "use" function

When I look at sample code for the "use" function in Kotlin, I usually see something like this:
private fun readFirstLine(): String {
BufferedReader(FileReader("test.file")).use { return it.readLine() }
}
However, in the following example, I don't understand where "input" comes from, since input -> appears to be a lambda. From my understanding, everything inside of use { } must be an expression:
val streamIn = resources.openRawResource(rawResId)
val streamOut = FileOutputStream(destFilename)
streamIn.use { input ->
streamOut.use { output ->
input.copyTo(output)
}
}
"input" clearly refers to the same object that "streamIn" refers to, but I don't understand how Kotlin knows that.
everything inside of use { } must be an expression
If you looked at the signature, you'll see that use takes a (T) -> R function, so really, any function/lambda that accepts the closable thing as a parameter can be passed to it.
With that misconception cleared up, let's see what the code in question is doing.
streamIn.use { input ->
streamOut.use { output ->
input.copyTo(output)
}
}
First we see streamIn.use {, which means we are going to do something with streamIn and then close it. And from now on streamIn will be called input. Then there is streamOut.use {, which indicates that we are also going to use streamOut to do stuff, and then close it, and we are going to call it output from now on.
I don't understand where "input" comes from
It's basically giving another name to the it as in your first code snippet. Since we have nested lambdas here, we can't use it to refer to the parameters of both lambdas.
"input" clearly refers to the same object that "streamIn" refers to, but I don't understand how Kotlin knows that.
This is because in the implementation of use, there's probably a line like this:
return block(this)
block is the lambda parameter you pass to use, and this is the object on which use is called. Since input is the parameter of the lambda, it refers to this.
Now we have declared that we are going to use two resources, what are going to do with them? input.copyTo(output)! Whatever copyTo returns is going to be returned by streamOut.use, which in turn is going to be returned by streamIn.use. streamOut and streamIn will also be closed one after another.
So overall what have we done? We have basically used 2 resources at the same time and closed them afterwards. This is how you'd compose use to use multiple resources at the same time.
in the lambda, you can define a name for your object so in the following code the input is equivalent to it which is streamIn and output is equivalent to streamOut:
streamIn.use { input ->
streamOut.use { output ->
input.copyTo(output)
}
}
The reason that they define input and output is you cannot use it when you use a lambda block inside another lambda block.
use is an extension function which takes whatever calls it as a parameter.
Assume this example:
file.bufferedReader().use{
println(it.readText()) // it is actually that object that calls `use`
}
According to the API docs of Kotlin, this is the schema of use:
inline fun <T : AutoCloseable?, R> T.use(block: (T) -> R): R
The bufferedReader in my example is a closable class.
When you write somethingClosable.use { }, you are in fact passing a lambda function to it, like:
fun <T, R> function(t: T): R {
// use T and return an R
}
somethingClosable.use(function)
And inside use your function will be called.
More info on extension functions in Kotlin.