V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Newyorkcity
V2EX  ›  问与答

kotlin:如何解释这两种写法的输出结果的不同?

  •  
  •   Newyorkcity · 2020-11-02 23:49:05 +08:00 · 1217 次点击
    这是一个创建于 1241 天前的主题,其中的信息可能已经有所发展或是发生改变。
    fun main(args: Array<String>) {
        val list = 1..5;
        println("1:-------------")
        list.forEach(fun(a: Int) {
            if (a == 3) return;
            println(a);
        });
        println("2:-------------")
        list.forEach {
            if (it == 3) return;
            println(it)
        }
    }
    

    感兴趣的 V 友可以先自己推断一下输出结果各自是什么..

    我说不清楚为什么,有懂的老哥还请赐教。谢谢~!

    第 1 条附言  ·  2020-11-03 10:56:40 +08:00
    我的困惑:

    第二个为什么会影响到外面的 forEach 呢?我个人了解这种写法是一个语法糖,当被调用的函数甲所需要的入参为一个函数类型时,可以直接将被调用的函数甲不接(),而接{}并在其中完成入参函数的函数体。。。但语法糖背后的逻辑不应该仍然是函数甲(先具体到 forEach )把每个元素都调用一次函数乙吗?

    莫非此时传入函数乙的变成了 list ?
    10 条回复    2020-11-03 16:40:39 +08:00
    ysc3839
        1
    ysc3839  
       2020-11-02 23:54:05 +08:00
    目测前面那个输出了 1 2 4 5,后面那个输出了 1 2 。大概是因为前者是从 fun return 了,而后者是从 main return 了。
    hoichallenger
        2
    hoichallenger  
       2020-11-03 00:02:22 +08:00   ❤️ 2
    上面是匿名函数,下面是 Lambda 表达式,return 的含义当然不一样。只要在下面的 forEach 里使用 Qualified returns ( return@forEach )就可能保证两者结果一致了。
    Jirajine
        3
    Jirajine  
       2020-11-03 00:49:09 +08:00 via Android
    @hoichallenger 这种行为很奇怪,lambda 也是函数,return 应该从最内层函数返回。
    不过这种 labeled return 倒是很有用,可惜其他语言没有类似的机制。
    bkmi
        4
    bkmi  
       2020-11-03 01:40:05 +08:00 via Android
    @Jirajine 这里 lambda 是 inline 的,不是函数。
    Newyorkcity
        6
    Newyorkcity  
    OP
       2020-11-03 07:12:55 +08:00 via Android
    @hoichallenger return 的含义的不一祥具体是指?
    starerlloll
        7
    starerlloll  
       2020-11-03 07:38:28 +08:00
    第一个是在 fun(a: Int) { } 里 return, 所以在 prinln 之前结束了该 fun,但这并不影响 list.forEach 继续
    第二个是在 list.forEach 里 return, 所以到 3 了就停了
    Newyorkcity
        8
    Newyorkcity  
    OP
       2020-11-03 10:56:22 +08:00
    @starerlloll
    第二个为什么会影响到外面的 forEach 呢?我个人了解这种写法是一个语法糖,当被调用的函数甲所需要的入参为一个函数类型时,可以直接将被调用的函数甲不接(),而接{}并在其中完成入参函数的函数体。。。但语法糖背后的逻辑不应该仍然是函数甲(先具体到 forEach )把每个元素都调用一次函数乙吗?

    莫非此时传入函数乙的变成了 list ?
    zhtf
        9
    zhtf  
       2020-11-03 12:16:01 +08:00   ❤️ 1
    hoichallenger
        10
    hoichallenger  
       2020-11-03 16:40:39 +08:00   ❤️ 1
    @Newyorkcity Kotlin 的文档里关于 return 是这么说的:By default returns from the nearest enclosing function or anonymous function. 因为 Lambda 是表达式( Expression )不是函数( Function ),所以第二个 forEach 里的 return 最近的函数是 main 函数,而第一个 forEach 里的 return 最近的函数是那个匿名函数。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3138 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 14:29 · PVG 22:29 · LAX 07:29 · JFK 10:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.