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()
Related
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.
What is this code line doing?
fun<T:x>a.b(y: Int)=lazy{u.v<T>(y)}
I do not know what is 'lazy' doing or is 'lazy' something special in Kotlin.
fun<T:x>a.b(y: Int)=lazy{u.v(y)}
Let's break this down. First, let's reformat for readability :)
fun <T: x> a.b(y: Int) = lazy { u.v<T>(y) }
Now, let's go piece by piece.
fun means we're declaring a new method.
<T:x> means this is a generic method operating on type T where T is constrained to be of type x.
a.b means this is an extension function named b on type a.
(y: Int) means that the defined function b takes a single argument named y of type Int.
= is expression body syntax - shorthand for returning a short line of code. This means that a.b will return the value that is the result of evaluating lazy { }
lazy is a Kotlin standard library function that delays the evaluation of the function provided to it until it's needed and then caches the result. The return value of this function is actually a type Lazy that wraps the provided function.
{ u.v<T>(y) } is the function that will be executed by the Lazy object when it's value is obtained the first time and the return value of u.v<T>(y) will be saved as the lazy object's value.
Phew! So what does that mean? Let's look at an example. Suppose we add a print statement to the function to see when it's called.
fun <T: x> a.b(y: Int) = lazy {
println("Executing 'b'")
u.v<T>(y)
}
Now if you tried to use it:
fun main() {
val a = A<T>() // Assume some type T
val lazyObject = a.b<T>(42) // Call the extension method that returns a `Lazy`
// Get the value from the lazy object - prints "Executing 'b'",
// executes `u.v<T>(y)`, caches the result, returns it - then print it
println(lazyObject.value)
// Get the value from the lazy object again. This time, DOES NOT print
// "Executing 'b'", DOES NOT execute `u.v<T>(y)`, and just returns the
// result that was already computed and cached, then print it
println(lazyObject.value)
}
So, in summary, the code you posted is creating an extension method that returns a Lazy object that, when queried for its value, executes the lambda it's initialized with and caches that result for later use.
Hope that helps!
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)
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.)
In Kotlin, I understand that a string can be assigned to a function directly, such as:
fun foo(): String = "Hello World"
But you can also assign a String to a variable directly as well:
var foobar: String = "Hello Word"
My question is, why would you ever create a function when you could just create a variable? I can't see the point in the existence of this functionality.
The interesting thing about
fun foo(): String = "Hello World"
is that it is using the expression syntax, and is equivalent to:
fun foo(): String {
return "Hello World"
}
While just returning a constant isn't very useful, using the expression syntax, avoiding the {block} and return statements allows much more concise function definitions in the case where the entire function can be expressed in one expression.
For example, if foo() was a method on a class, you could say hello with a property of that class:
class Hello(var what : String = "World") {
fun foo(): String = "Hello, $what!"
}
fun main() {
val hello = Hello()
println(hello.foo())
hello.what = "Universe"
println(hello.foo())
}
This prints:
Hello, World!
Hello, Universe!
This is more about when to prefer a function v/s a property.
Kotlin coding conventions has a section that describes this.
A property should be preferred over a function when-
the underlying algorithm does not throw
value is cheap to calculate (or caсhed on the first run)
returns the same result over invocations if the object state hasn't changed
In terms of an API use-case, in some cases exposing a function instead of a property might be a good idea as that gives you the scope to change the implementation of this API in future. What might be a hardcoded value today, could be replaced by code that computes the value in future.
It's simple, think about what the word coding means. Coding rules. Rules that are complicated get broken down in rules that are exactly one level below in abstraction, so that the program is as intelligible as possible.
Well, the function name is just one level above the expression. This is even more true in a language as expressive as kotlin where one line can easily be equivalent to several lines of Java.
If you are talking about strings or primitives exclusively then, yes, an attribute is a more natural choice than a function.