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)
}
}
大家觉得这种设计是好是坏?
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 1
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
|