-
Kotlin Lambda详解及非局部返回是啥意思?
2020-09-10 16:34:45如果推断出的该 lambda 的返回类型不是Unit,那么该 lambda 主体中的最后一个(或可能是单个) 表达式会视为返回值。 意思就是说lambda表达式一定要放在花括号 { } 中,->前面是参数,后面是方法体就是你要拿这个...Lambda定义
lambda 表达式总是括在花括号中, 完整语法形式的参数声明放在花括号内,并有可选的类型标注, 函数体跟在一个
->
符号之后。如果推断出的该 lambda 的返回类型不是Unit
,那么该 lambda 主体中的最后一个(或可能是单个) 表达式会视为返回值。意思就是说lambda表达式一定要放在花括号 { } 中 ,
->
前面是参数,后面是方法体就是你要拿这个参数进行的操作。如果你的lambda是有返回值的,->
后面最后一个表达式会被视为返回值,代码如下: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 }
lambda 主体中的最后一个(或可能是单个) 表达式会视为返回值。为啥非要这么说呢
var lam1: (Int, Int) -> Int = { x: Int, y: Int -> 1操作 ➺ val sum = x + y 2操作 ➺ println(sum) 3操作 ➺ sum } 注意:Kotlin不像java用 ; 作为结束标志,所以要每行写一个操作,如果放在一行编译就会报错!
->
后面有 1 ,2 , 3 三个操作,最后3处的表达式作为返回值返回。那如果
var lam = { x: Int, y: Int -> x + y }
前面声明不指定有没有返回值,x+y 会不会作为返回值返回呢?
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
结果是会作为返回值,如果不指定,会根据
->
后面返回表达式自动推算返回值,代码如下修改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规则
我们通常看到的lambda印象最深就是,精简,最后简化到只剩一个 { } 都可以,虽然看不懂,就好厉害的感觉
那如何将一个函数方法改成一个lambda表达式呢?这就和下面lambda非常重要的几个规则有关
1 在 Kotlin 中有一个约定:如果函数的最后一个参数是函数,那么作为相应参数传入的 lambda 表达式可以放在圆括号之外 ,这种语法也称为拖尾 lambda 表达式。
fun main() { method3( "hello" , { x -> x + 6 } ) : 正常调用, ↓ ↓ ↓ 根据拖尾原则,如果lambda表达式在参数的最后一个位置 ↓ 可以拿到圆括号外面 ↓ method3("hello") { x -> x + 6 } } fun method3(msg: String, lamParams: (Int) -> Int) { 两个参数:一个String,一个lambda表达式 }
2 如果一个 lambda 表达式只有一个参数,可以省略这个参数并忽略 ->。而这个被省略的参数可以用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表达式 }
这样经过简化的之后,看起来很厉害的样子就出来了: method3("hello") { it + 6 }
3 如果 lambda 表达式的参数未使用,那么可以用下划线取代其名称:
fun main() { method("") { _, str -> str } 分析: 1 lambda表达式位置在method方法中参数最后一个可以拿到括号外面 2 lambda表达式有两个参数,所以不能省略 3 Int参数 在箭头后面的操作中没有用到,可以用 _ 代替 } fun method(msg: String, lam: (Int, String) -> String) { }
这样就可以将函数精简为Lambda表达式了。
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显示声明返回值:
Lambda 禁止直接使用return关键字,我们可以使用限定的返回语法: return@函数名 从Lambda 显式返回一个值。 否则,将隐 式返回最后一个表达式的值。
lambda默认将 -> 最后一个表达式作为返回值返回 method("") { _, str -> str } 也可以显示的 return 返回值 method("") { _, str -> return@method str }
=======================================================================
匿名函数:
当想要显示指定lambda 表达式的返回类型,我们可以使用匿名函数的形式
fun(x: Int, y: Int): Int = x + y
fun关键词后面并没有和普通函数一样有一个函数名,所以叫匿名函数。
而且如果返回值可以推算得出返回值也是可以省略的,即:fun(x: Int, y: Int) = x + y 也是可以的
注意:
1 匿名函数参数必须放在括号里面,不能像lambda表达式一样简化处理。
2 Lambda表达式与匿名函数之间的另一个区别是非局部返回的行为:这是什么意思呢?
官方文档是这样说的:一个不带标签的 return 语句总是在用 fun 关键字声明的函数中返回。这意味着 lambda 表达式中的 return 将从包含它的函数返回,而匿名函数中的 return 将从匿名函数自身返回。
非局部返回,这就牵扯到了 inline 内联函数
说的是 内联函数 如果被处理成了Lambda表达式的时候,return 返回的是外部那个调用内联函数的函数,而不是内联函数本身。(注意:前面说过Lambda是禁止直接使用return关键字,要使用必须是:return@函数名 这种形式。但是内联函数使用Lambda就可以直接使用 return关键字)。看代码:
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 所以报错。
而我们函数调用顺序为
main() -> behavior() -> speak
这样我们在 speak的参数lambda表达式里面 return,结束的是哪个函数呢?
结束的是 behavior 函数。因为 speak 是内联函数。编译的时候就变成下面样子,。
调用处大体示意: 编译时大体示意: fun main() { fun main() { behavior { behavior { speak { println("speak $it") println("speak $it") return return } } } } }
所以 return 的就是 behavior 函数了。
(注:内联函数能不能return还有其他限制,这里就不说了。)
上面说 lambda 表达式中的 return 将从包含它的函数返回,而匿名函数中的 return 将从匿名函数自身返回。说的是Lambda在内联函数的情况下。
-
啥玩意儿是 - 局部变量?
2020-04-11 22:26:43局部变量 概念: 声明在函数内部的变量,必须先赋值再使用。 作用范围: 定义行开始到所在的代码块结束。 注意: 多个变量,在重合的作用范围内,不可出现重名(命名冲突)。 public class TestLocalVariables...局部变量
-
概念: 声明在函数内部的变量,必须先赋值再使用。
-
作用范围: 定义行开始到所在的代码块结束。
-
注意: 多个变量,在重合的作用范围内,不可出现重名(命名冲突)。
public class TestLocalVariables{ public static void main(String[] args){ int a = 10;//局部变量 System.out.println(a);//输出为 10 if (a % 2 == 0){ //int a = 20;//重名的局部变量 //System.out.println(a); int b = 20;//局部变量,这个b仅在此if结构下可用 System.out.println(b);//打印结果为 20 }//代码块结束,b变量回收 int b = 30;//新变量赋值 不建议定义相同名字的变量,重新定义新变量名 System.out.println(b);//输出结果为30 } }
-
-
局部响应归一化LRN(Local Response Normalization)是啥
2019-05-29 10:26:00归一化有很多种方法,第一次遇到LRN是在Alexnet中,用于对卷积层...个人认为是因为每次归一化某个值得时候,要参考某个与该值相关的局部区域内的响应值,那这个局部区域怎么定呢? 这里是使用与该值具有同一位置...归一化有很多种方法,第一次遇到LRN是在Alexnet中,用于对卷积层的输出结果进行归一化。公式如下:
这里的i表示第i个通道,(x,y)为某个像素点位置。这里的意思就是说,我要把卷积层输出的第i个通道的(x,y)位置的值进行归一化。为什么叫局部响应呢?个人认为是因为每次归一化某个值得时候,要参考某个与该值相关的局部区域内的响应值,那这个局部区域怎么定呢?
这里是使用与该值具有同一位置(x,y)且与通道i距离为n/2的那些值。先写这些,以后理解了再说。
参考:https://blog.csdn.net/u014296502/article/details/78839881
-
【六祎】彻底认识什么是成员变量和局部变量是个啥!!!
2019-11-26 22:25:20 -
对于局部变量_【高并发】面试官问我:为啥局部变量是线程安全的?
2021-01-15 12:15:52写在前面 相信很多小伙伴都知道局部变量是线程安全的,那你知道为什么局部变量是线程安全的吗?前言 多个线程同时访问共享变量时,会导致并发问题。那么,如果将变量放在方法内部,是不是还会存在并发问题呢?如果不... -
局部变量的地址为啥是一直在增加的
2019-09-29 01:12:29 -
【高并发】面试官问我:为啥局部变量是线程安全的?
2020-10-27 11:23:00写在前面 相信很多小伙伴都知道局部变量是线程安全的,那你知道为什么局部变量是线程安全的吗?前言 多个线程同时访问共享变量时,会导致并发问题。那么,如果将变量放在方法内部,是不是还会存在并... -
返回局部变量或临时变量的地址_【高并发】面试官问我:为啥局部变量是线程安全的?...
2020-11-24 10:48:31写在前面相信很多小伙伴都知道局部变量是线程安全的,那你知道为什么局部变量是线程安全的吗?前言多个线程同时访问共享变量时,会导致并发问题。那么,如果将变量放在方法内部,是不是还会存在并发问题呢?如果不... -
-
java 对象内存分析,封装是啥?JavaBean规范又是啥?
2020-03-06 18:23:07文章目录对象内存分析演示封装是啥?演示JavaBean规范又是啥?结束语 对象内存分析 成员变量:储存在堆内存中,随着对象的销毁而销毁 局部变量:储存在栈内存中,随着所定义的方法的调用结束而销毁 演示 public ... -
【高并发】面试官问我:为什么局部变量是线程安全的?
2020-10-24 18:24:17终于弄懂为啥局部变量是线程安全的了!! -
为啥被匿名内部类引用的局部变量要用final修饰
2019-06-18 22:15:56我们都知道一个.java文件在编译的时候会生成一个.class文件,匿名内部类也是会生成一个.class文件的, 就像如图: TestDemo$1.class是匿名内部类的名字,TestDemo是匿名内部类所在的运行类的名字, 我们知道要获取... -
JS-闭包是啥
2020-06-07 12:50:501.说明 函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包(closure)。在 JavaScript 中,每当函数被创建,就... // name 是一个被 init 创建的局部变量 function displayName() { // di -
JAVA内部类是个啥?
2020-07-02 10:14:20文章目录内部类分类成员内部类局部内部类匿名内部类简化代码接口静态内部类内部类的部分好处参考资料 内部类分类 广泛意义上的内部类一般来说包括四种:成员内部类,局部内部类,匿名内部类和静态内部类。 成员内部... -
闭包?啥是闭包?
2018-12-13 19:54:00简单的说就是就是外部的也可以访问内部的,函数里面包裹一个函数 ...变量的作用域无非就两种:全局变量和局部变量。 javascript语言的特别之处就在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数... -
HDU - 3746 (kmp)(重点在于string 作为局部变量是错的)
2017-07-22 14:23:18用kmp的next数组求出最小重复 子串的长度然后末尾缺少...但是有个很玄学的问题,string作为局部变量是错的,但是全局就是对的,神奇,难受,不懂为啥 Wa #include #include #include #include using namespac -
第三次学JAVA再学不好就吃翔(part43)--局部内部类访问局部变量
2020-06-02 22:11:22啥叫局部内部类? 局部内部类是指在方法中定义的内部类。 举个例子(访问局部内部类) 局部内部类: class InnerTest1 { public static void main(String[] args) { } } class Outer { public void mehtod() {... -
堆和栈的区别是啥?
2016-04-11 17:40:551、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈; 2、堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,... -
js的变量作用域,局部变量,全局变量,全局和局部变量重名
2018-06-23 12:11:461、局部变量://就是定义在函数内部的变量(内部变量),局部变量起作用的范围是函数内部。//局部变量就是私有的变量2、全局变量://就是定义在函数外部的变量(外部变量),//全局变量起作用的范围是当前文件中的... -
logo是啥_VI设计如何与Logo设计配合
2020-12-09 16:17:31常用套路档常用套路1——截取局部Pablo&Rusty‘s咖啡的图形Logo就是P&R几个字母,在使用上也很简单粗暴的使用了局部裁剪的方式来进行VI设计。这种手法可以说是最简单的Logo在全局VI中的表现,但是请注意你... -
堆和栈的区别是啥
2011-04-25 13:15:001、栈区(stack)― 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区(heap) ― 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意... -
python中ch是啥_Ch13.Python基础语法-函数进阶
2020-12-10 22:16:23本章我们将学习Python的函数高级用法目标变量作用域多函数程序执行流程函数的返回值...局部变量所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效。def testA():a = 100print(a)testA() # 100print(a)... -
聊一聊ThreadLocal是个啥东东
2019-04-30 15:34:37ThreadLocal提供了线程私有的局部变量,可以在整个线程存活的过程中随时取用,从而减少了在同一个线程内多个函数或者组件之间公共变量传递的复杂度。同时,由于ThreadLocal变量的线程私有性,故不存在并发线程安全的...
-
利用坐标变换分析塔差对编码器测角精度测试的影响
-
php底层运行机制与原理
-
项目管理工具与方法
-
小屏幕大世界“Next”背后的秘密
-
2021-02-27
-
app服务端.rar
-
在 Linux 上构建企业级 DNS 域名解析服务
-
jquery使用serialize()出现中文乱码怎么办
-
移动手机用户体验的三个层次
-
PHP SOCKET编程
-
scrapy_settings.py
-
什么是区块链?这是我见过的最通俗易懂的解释
-
ELF视频教程
-
华为1+X——网络系统建设与运维(中级)
-
jquery使用serialize()出现中文乱码怎么办
-
宝塔安装sqlsrv扩展,PHP连接 Sqlserver
-
迪普食品-源码
-
Web前端开发笔记(1)
-
wpf prism View Injection(视图注入)
-
晓看红湿处 ,花重锦官城