fun add ( value : A, compare : (A, A) -> Int ) : Tree <A> =
when (this) {
is Empty -> treeNode(value)
is Node -> if (compare(value,this.value) < 1) {
treeNode(this.value,left.add(value,compare),right)
} else{
treeNode(this.value,left,right.add(value,compare))
}
}
I dont understand what the funtion wants when I call it
tree.add(5,?)
The second argument of tree.add() should be a function that takes 2 objects of type A and returns an integer.
To pass such a function, one option is to use a lambda expression (with braces):
tree.add(5, { a, b -> ... })
In Kotlin, we usually pass such lambdas outside the parenthesis of the function call, though. Like this:
tree.add(5) { a, b -> ... }
Now let's check the content of the function. In your case, the semantic of the expected function seems to be the same as the Comparator.compare or Comparable.compareTo functions:
Compares its two arguments for order. Returns zero if the arguments are equal, a negative number if the first argument is less than the second, or a positive number if the first argument is greater than the second
When A is Int like in your example, the implementation of the comparison function could simply call Int.compareTo(Int):
tree.add(5) { a, b -> a.compareTo(b) }
Another way is to pass a method reference directly instead of a lambda:
tree.add(5, Int::compareTo)
Note: passing the comparator function as argument to add is rather bad design (especially because this function is public), because the comparator can be different for each call adding elements to the tree. It should instead be a property of the tree itself, otherwise the tree could become inconsistent.
Related
Edited: What and how it work? This is a kotlin dsl language.
fun ClassName.funcName(): (Type ) -> Type = {func body}
um this is one of the implementation I found, and also see the concrete syntax to this link: https://dzone.com/articles/the-complete-custom-gradle-plugin-building-tutoria
private fun CodeLinesExtension.buildFileFilter():
(File) ->
Boolean =
if (fileExtensions.isEmpty()) {
{ true }
} else {
{ fileExtensions.contains(it.extension) } // filter by extension
}
if you CALL this one as a arguments in ".filter(...)", what would happed in the "(File)" syntax, is it automatically receive an arguments?
someFiles.filter(CodeLinesExtension.buildFileFilter()).forEach{...}
There are many things at play here.
fun SomeClass.funcName() is the syntax for declaring extension functions. These are used just like regular methods of the class SomeClass, but can be defined outside of the class, and it's especially useful on classes that you don't control.
The return type of the function you mention is (File) -> Boolean. This expression describes a function type. In this specific case, it is the type of all functions that take a File as single argument, and return a Boolean.
This means that your buildFileFilter() function is an extension function that itself returns a function (File) -> Boolean.
As you can see in the function's body, inside the if statement, there are braces to define the blocks of the if-else ({ ... }), but also braces inside those blocks. This is because Kotlin uses braces for lambda expressions (literals for anonymous functions).
{ true } is a lambda expression that represents a function that may or may not take arguments, but returns true every time.
So this code:
if (fileExtensions.isEmpty()) {
{ true }
} else {
{ fileExtensions.contains(it.extension) } // filter by extension
}
returns either:
{ true } - a function that takes a File as argument and always returns true, or
{ fileExtensions.contains(it.extension) } - a function that takes a File as argument and returns whether fileExtensions contains the extension of the File that it receives (it is the implicit name for the File argument)
Note: the fact that these functions take a File as argument is inferred by the compiler based on the return type of buildFileFilter().
if you CALL this one as a arguments in ".filter(...)", what would happed in the "(File)" syntax, is it automatically receive an arguments?
filter() itself actually expects a function as argument. The function you pass to filter() is called a predicate, because it takes one element of the list as argument and returns a Boolean that says whether this element should be included in the resulting list.
So if you apply filter to a List<File>, the predicate expected by filter is exactly of type (File) -> Boolean (it says whether we should put this File item in the resulting collection).
Calling buildFileFilter() returns a function as we have seen, and the function is perfectly of the right type to use it in filter. The File argument of the function returned by buildFileFilter() will be given by the filter function itself when it calls your filter function.
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.)
This question is about fun() vs a lambda block definitions and scopes.
i have tried define the expressions in two ways. Here is what i have tried:
val myFunction = fun(){
println("i am in a function")
}
//but i also tried doing this:
val myFunction = {
println("i am in a lambda")
}
my problem is i do not know if they are equivalent and same thing ?
The differences are best described in https://kotlinlang.org/docs/reference/lambdas.html#anonymous-functions:
Anonymous functions allow you to specify return type, lambdas don't.
If you don't, return type inference works like for normal functions, and not like for lambdas.
As #dyukha said, the meaning of return is different:
A return statement without a label always returns from the function declared with the fun keyword. This means that a return inside a lambda expression will return from the enclosing function, whereas a return inside an anonymous function will return from the anonymous function itself.
There is no implicit it parameter, or destructuring.
Your specific cases will be equivalent, yes.
See the reference: https://kotlinlang.org/docs/reference/lambdas.html
There are several ways to obtain an instance of a function type:
Using a code block within a function literal, in one of the forms:
a lambda expression: { a, b -> a + b },
an anonymous function: fun(s: String): Int { return s.toIntOrNull() ?: 0 }
Both give you a function object which can be used interchangeably
I am learning the new and very beautiful language Kotlin and everything seems to be very logical and consistent. I only found one thing which seems like an arbitrary exception to the rule than a solid rule. But maybe I lack enough understanding some deeper reasons behind the rule.
I know that in if-else and when statements there are blocks of code, then the last expression is returned. In the next example 1 or 2 are returned depending on the condition - in our case it returns 1.
val x = if (1 < 2) {println("something"); 1} else {println("something else"); 2}
On the other hand this does not hold for any code block. The next line assigns y not to 1 but to the whole block of code as a lambda.
val y = {println("something"); 1}
Similarly in function body, the last expression is not returned. This does not even compile.
fun z() : Int {
println("something")
1
}
So what exactly is the rule? Is it really so arbitrary like: if in if-else or when statement which is used as expression there is a block of code, then the last expression in the block is returned. Otherwise the last expression is not returned to outer scope. Or am I missing something?
you misunderstand the curly brackets {}, when around with all flow-control statement it is just a block, for example:
if (condition) { //block here
}
WHEN the {} is declared separately it is a lambda expression, for example:
val lambda: () -> Int = { 1 }; // lambda
WHEN you want to return a lambda in if-else expression, you must double the curly brackets {} or using parentheses () to distinguish between the block and the lambda expression or make the {} as lambda explicitly, for example:
val lambda1: () -> Int = if (condition) { { 1 } } else { { 2 } };
val lambda2: () -> Int = if (condition) ({ 1 }) else ({ 2 });
val lambda3: () -> Int = if (condition) { -> 1 } else { -> 2 };
If a function does not return any useful value, its return type is Unit. Unit is a type with only one value - Unit. This value does not have to be returned explicitly.
On the other hand, a common function must have a explicit return statement if its return type if not a Unit:
fun z(): Int { return 1; }
Another case is a function return Nothing, the return statement don't allowed at all, because you can't create a Nothing instance, for example:
fun nothing(): Nothing {
return ?;// a compile error raising
}
WHEN a function has only one expression then you can using single-expression function instead, for example:
fun z() = 1;
There is a difference between a lambda block and just a 'normal' block, in your case the "y" is just a lambda that needs to be executed to get the returned value:
val block: () -> Int = { 5 }
val five: Int = { 5 }()
val anotherFive = block()
So if you want a block that acts as a lambda, you can create a lambda and execute it right away with "()". This way, your "z" function would compile like so:
fun z() : Int = {
println("something")
1
}()
(Which, of course, does not make much sense and is not very efficient)
You are absolutely right, V.K. The choice is completely arbitrary. Well, probably not completely arbitrary but related to parsing complexities arising from curly braces being chosen to denote both blocks and lambdas.
Actually, besides the case you make for block expressions, there also is the situation of (simple) blocks: just group of statements enclosed in braces. For example, Java supports (simple) blocks and you can write:
String toBeComputed ; {
// Relatively long sequence of operations here
toBeComputed= resultingValue ;
}
I use this idiom quite frequently because:
It's not always convenient to extract the code into a function.
Like a function, it delimits the code and documents its nature without introducing additional names or comments.
Sometimes it's preferable to initialize two or more variables in tandem and introducing a result-value class with this specific purpose feels like an overkill.
Also like a function it doesn't pollute the outer namespace with temporary variables only used internally.
Anecdotally, as Java does not support block expressions I would write the example as
int y ; {
println("something");
y= 1 ;
}
Other languages (ALGOL and Scala come to my mind) do support block expressions (and in the case of Scala also lambdas, but with a different syntax). In these languages what you proposed (in Scala syntax)
val y= { println("something"); 1 }
is completely valid and does not require () to force a lambda to evaluate (because there is no lambda!).
In conclusion, Kotlin designers did choose to make the language less consistent than ALGOL and Scala in terms of blocks and block expression, probably in favor of convenience.
I hope my long response shows that what you expected from Kotlin was not illogical, just not the case because of some language design choice. The principle of less surprise did not work this time.