V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
CYKun
V2EX  ›  Kotlin

Kotlin 中 return 语句的设计是基于怎样的考虑?

  •  2
     
  •   CYKun · 2017-05-26 00:20:05 +08:00 · 6976 次点击
    这是一个创建于 2773 天前的主题,其中的信息可能已经有所发展或是发生改变。

    kotlin 中 return 语句会从最近的函数或匿名函数中返回,这意味着下面两个函数是不同的:

    fun foo(ints: IntArray) {
        ints.forEach {
            if (it == 0) return
            print(it)
        }
    }
    
    fun bar(ints: IntArray) {
        ints.forEach(fun(value: Int) {
            if (value == 0) return
            print(value)
        })
    }
    

    foo 在遇到 0 时会直接返回,bar 遇到 0 时会跳过它继续执行。
    foo 的代码看上去很漂亮,forEach 给人一种在用 for 循环的感觉,遇到 return 直接从 foo 中返回,似乎也挺合理的。

    但是 forEach 接收的毕竟是一个 lamda 表达式,这种设计导致匿名函数和 lambda 表达式行为不一致,为此 kotlin 还提供了 @Label 来控制返回语句:

    fun foo(ints: IntArray) {
        ints.forEach {
            if (it == 0) return@forEach
            print(it)
        }
    }
    

    大家觉得这种设计是好是坏?

    12 条回复    2017-05-26 10:16:04 +08:00
    jarlyyn
        1
    jarlyyn  
       2017-05-26 03:19:36 +08:00
    ……

    我接触过的大部分语言都是这样啊。
    disposablexyz
        2
    disposablexyz  
       2017-05-26 04:05:44 +08:00 via iPad
    https://blog.jooq.org/2016/02/22/a-very-peculiar-but-possibly-cunning-kotlin-language-feature/

    "reason is very simple: we want to have lambdas that work exactly like built-in language features (e.g. synchronised)"
    geelaw
        3
    geelaw  
       2017-05-26 04:29:43 +08:00
    问题……为什么不把 return@forEach 语法糖成 continue ?
    imcj
        4
    imcj  
       2017-05-26 07:52:00 +08:00 via iPhone
    Now, it returns only from the lambda expression. Oftentimes it is more convenient to use implicits labels: such a label has the same name as the function to which the lambda is passed.

    在 lambda 里面 continue 没有意义。
    wweir
        5
    wweir  
       2017-05-26 08:20:51 +08:00 via Android   ❤️ 1
    lambda 表达式没有做任何显示的标记,直接把后续代码做隐式替换,导致代码逻辑和直观存在偏差

    感觉这种语法糖不要也罢
    wotemelon
        6
    wotemelon  
       2017-05-26 08:27:10 +08:00 via Android
    js 就是这样的
    araraloren
        7
    araraloren  
       2017-05-26 08:29:15 +08:00
    个人觉得不大好,同样对比 Perl 6 的设计
    不让你在 Block (lambda) 中使用 return 会报错
    Block:
    -> $para {
    return $para; # ERROR !
    }

    而匿名的方法则没问题
    sub ($para) {
    return $para; # OK
    }
    araraloren
        8
    araraloren  
       2017-05-26 08:34:41 +08:00
    补充楼上:
    sub ($para) {
    -> {
    return ; # 从 sub 中返回
    }
    }
    设计正好相反。。 :)
    laxenade
        9
    laxenade  
       2017-05-26 08:53:53 +08:00
    感觉叫 yield 更贴切
    SoloCompany
        10
    SoloCompany  
       2017-05-26 09:21:29 +08:00 via iPhone
    这要看定义,inline function 和普通 function 毕竟还是有很大不同的,如果没有这个特性,很多封装控制流的的库函数比如 use run let 等的使用就体验大打折扣了
    enenaaa
        11
    enenaaa  
       2017-05-26 09:22:23 +08:00
    @wweir 赞同。 函数的形式应该一致, 匿名函数搞得像代码块, 容易混淆。
    bombless
        12
    bombless  
       2017-05-26 10:16:04 +08:00 via Android
    有点把问题复杂化了。感觉最好是只要有歧义就强制加 label
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2624 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 11:42 · PVG 19:42 · LAX 03:42 · JFK 06:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.