What does Kotlin Lambda explain and non-local return mean?

Lambda definition

Lambda expressions are always enclosed in curly braces, parameter declarations in the complete syntax form are placed in curly braces, with optional type annotations, and the function body follows a  -> symbol. If the inferred return type of the lambda is not  Unit, then the last (or possibly a single) expression in the body of the lambda will be regarded as the return value.

This means that the lambda expression must be placed in curly braces {}, the  -> front is the parameter, and the back is the method body that is the operation you want to perform with this parameter. If your lambda has a return value, the -> last expression will be regarded as the return value. The code is as follows:

Lambda就像一个简化的函数,如下:

lam1 对应的就是method1 ,两个参数,返回一个Int值。x+y 作为 -> 后面最后一个表达式返回
var lam1: (Int, Int) -> Int = { x: Int, y: Int -> x + y }

fun method1(x: Int, y: Int): Int {
    return x + y
}


lam2 对应的就是method2,如果表达式不需要返回值,x+y  只是做了一次运算,并没有返回 
var lam2: (Int, Int) -> Unit = { x: Int, y: Int -> x + y }

fun method2(x: Int, y: Int): Unit {
    x + y
}

The last (or possibly a single) expression in the body of the lambda is treated as the return value. Why do you have to say that?

var lam1: (Int, Int) -> Int = { x: Int, y: Int ->
 1操作 ➺  val sum = x + y
 2操作 ➺  println(sum)
 3操作 ➺  sum
}
注意:Kotlin不像java用 ; 作为结束标志,所以要每行写一个操作,如果放在一行编译就会报错!

 -> There are three operations 1, 2, and 3, and the last 3 expressions are returned as the return value.

Then if  

var lam  = { x: Int, y: Int -> x + y }

The previous statement does not specify whether there is a return value, will x+y be returned as a return value?

var lam = { x: Int, y: Int -> x + y }
fun main() {

    println(lam(2, 3))

}

打印结果:

D:\AndroidStudio\android-studio\jre\bin\java.exe -
5

Process finished with exit code 0

The result will be used as the return value, if not specified, the return value will be -> automatically calculated according to the return expression, the code is as follows

修改1:
var lam = { x: Int, y: Int -> x > y }
打印结果
D:\AndroidStudio\android-studio\jre\bin\java.exe -
false

Process finished with exit code 0

修改2:
var lam = { x: Int, y: Int -> "Result $x $y" }
打印结果
D:\AndroidStudio\android-studio\jre\bin\java.exe -
Result 2 3

Process finished with exit code 0

=======================================================================

Lambda rules

The deepest impression of the lambda we usually see is that it is simplified, and finally simplified to only one {}, although I don’t understand it, it’s amazing.

How to change a function method into a lambda expression? This is related to the following very important rules of lambda

1 There is a convention in Kotlin: If the last parameter of a function is a function, then the lambda expression passed in as the corresponding parameter can be placed outside the parentheses. This syntax is also called trailing lambda expression .

fun main() {
 
    method3( "hello" ,  { x -> x + 6 } ) : 正常调用,
    ↓
    ↓
    ↓ 根据拖尾原则,如果lambda表达式在参数的最后一个位置
    ↓ 可以拿到圆括号外面
    ↓
    method3("hello") { x -> x + 6 }
   
}

fun method3(msg: String, lamParams: (Int) -> Int) {
                         
     两个参数:一个String,一个lambda表达式
}

2 If a lambda expression has only one parameter, you can omit this parameter and ignore ->. And this omitted parameter can be replaced with it

还是接着上面的代码继续修改
fun main() {
 
    method3( "hello" ,  { x -> x + 6 } ) : 正常调用,
    ↓
    ↓
    ↓ 根据拖尾原则,如果lambda表达式在参数的最后一个位置
    ↓ 可以拿到圆括号外面
    ↓
    method3("hello") { x -> x + 6 }
    ↓
    ↓ 根据单参数省略原则:
    ↓ 参数 x 省略,
    ↓ -> 省略
    ↓ x可用 it 代替   
    ↓
    method3("hello") {  it + 6 }
}

fun method3(msg: String, lamParams: (Int) -> Int) {
                         
     两个参数:一个String,一个lambda表达式
}

After this simplification, it looks very powerful: method3("hello") {it + 6}
 

3 If the parameter of the lambda expression is not used, you can replace its name with an underscore:

fun main() {
 
    method("") { _, str -> str }
    分析:
     1 lambda表达式位置在method方法中参数最后一个可以拿到括号外面
     2 lambda表达式有两个参数,所以不能省略
     3 Int参数 在箭头后面的操作中没有用到,可以用 _ 代替
    
               
}

fun method(msg: String, lam: (Int, String) -> String) {

} 

In this way, the function can be reduced to a Lambda expression.


fun method5(str: String, x: Int, bool: Boolean) {
    str + x + bool
}
    ↓
    ↓ 精简
    ↓
{ str: String, x: Int, bool: Boolean -> str + x + bool }

然后将这个Lambda表达式赋值给lam5
var lam5  = { str: String, x: Int, bool: Boolean -> str + x + bool }
 


main(){
    method6是用method5 的函数形式作为参数
    我们分别传递 method5 和 lambda5 到method6中,完全没有问题,说明精简是对的
    method6(lam5)
    method6(::method5)
 
}
fun method6(m: (String, Int, Boolean) -> Unit) {
                 
       参数是(String, Int, Boolean) -> Unit这么一个表达式
 
}

=======================================================================

Lambda display statement return value:

  Lambda prohibits the use of the return keyword directly, we can use the limited return syntax: return@function name Explicitly return a value from Lambda. Otherwise, the value of the last expression will be implicitly returned.

lambda默认将 -> 最后一个表达式作为返回值返回
method("") { _, str ->  str }

也可以显示的 return 返回值
method("") { _, str -> return@method str }

 =======================================================================

Anonymous function:

   When we want to display the return type of a specified lambda expression, we can use the form of an anonymous function

fun(x: Int, y: Int): Int = x + y

The fun keyword does not have a function name like a normal function, so it is called an anonymous function.

And if the return value can be calculated, the return value can also be omitted, that is: fun(x: Int, y: Int) = x + y is also possible

note:

1 Anonymous function parameters must be placed in parentheses, and cannot be simplified like lambda expressions.

2 Another difference between lambda expressions and anonymous functions is the behavior of non-local returns: what does this mean?

The official document says this: an unlabeled return statement is always returned in a function declared with the fun keyword. This means that the return in the lambda expression will return from the function containing it, and the return in the anonymous function will return from the anonymous function itself.

Non-local return, which involves inline inline function

It is said that if an inline function is processed into a Lambda expression, return returns the external function that calls the inline function, not the inline function itself. ( Note: As mentioned earlier, Lambda prohibits the direct use of the return keyword. To use it, it must be in the form: return@function name. But inline functions using Lambda can directly use the return keyword ). Look at the code:

fun song(f: (String) -> Unit) {

}

inline fun speak(f: (String) -> Unit) {

}
fun behavior() {
    
    song {
        println("song $it")
        return //此处报错: 'return' is not allowed here
    }

    speak {
        println("speak $it")
        return  //此处没问题
    }
    
}

fun main() {

    behavior()

}
song() 方法没有内联不允许在 Lambda 中直接 return 所以报错。

And our function call sequence is  

main() -> behavior() -> speak

In this way, we return in the parameter lambda expression of speak, which function does the end end?

The end is the behavior function. Because speak is an inline function. It will look like the following when compiling.

调用处大体示意:                                 编译时大体示意:
fun main() {                                    fun main() {

    behavior {                                     behavior {
       
         speak {                            
            println("speak $it")                         println("speak $it")
             return                                      return  
            }

      }                                                   }

}                                                   }

So the return is the behavior function.

(Note: There are other restrictions on whether inline functions can return, so I won’t talk about them here.)

As mentioned above  , the return in the lambda expression will return from the function containing it, and the return in the anonymous function will return from the anonymous function itself. Talking about the case of Lambda inline function.

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/u011288271/article/details/108385586