
kotlin 中 return 语句会从最近的函数或匿名函数中返回,这意味着下面两个函数是不同的:
fun foo(ints: IntArray) { ints.forEach { if (it == 0) return print(it) } } fun bar(ints: IntArray) { ints.forEac(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) } } 大家觉得这种设计是好是坏?
1 jarlyyn 2017-05-26 03:19:36 +08:00 …… 我接触过的大部分语言都是这样啊。 |
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)" |
3 geelaw 2017-05-26 04:29:43 +08:00 问题……为什么不把 return@forEach 语法糖成 continue ? |
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 没有意义。 |
5 wweir 2017-05-26 08:20:51 +08:00 via Android lambda 表达式没有做任何显示的标记,直接把后续代码做隐式替换,导致代码逻辑和直观存在偏差 感觉这种语法糖不要也罢 |
6 wotemelon 2017-05-26 08:27:10 +08:00 via Android js 就是这样的 |
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 } |
8 araraloren 2017-05-26 08:34:41 +08:00 补充楼上: sub ($para) { -> { return ; # 从 sub 中返回 } } 设计正好相反。。 :) |
9 laxenade 2017-05-26 08:53:53 +08:00 感觉叫 yield 更贴切 |
10 SoloCompany 2017-05-26 09:21:29 +08:00 via iPhone 这要看定义,inline function 和普通 function 毕竟还是有很大不同的,如果没有这个特性,很多封装控制流的的库函数比如 use run let 等的使用就体验大打折扣了 |
12 bombless 2017-05-26 10:16:04 +08:00 via Android 有点把问题复杂化了。感觉最好是只要有歧义就强制加 label |