Kotlin 编译器如何判断在嵌套 Lambda 中应该取哪个默认参数 it? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
twoyuan
V2EX    Kotlin

Kotlin 编译器如何判断在嵌套 Lambda 中应该取哪个默认参数 it?

  •  
  •   twoyuan 2017-11-24 17:55:52 +08:00 8917 次点击
    这是一个创建于 2939 天前的主题,其中的信息可能已经有所发展或是发生改变。

    code

    例如上述代码中,第一个 it 去了 async 的默认参数,而 第二个 it 使用了 forEach 的默认参数

    14 条回复    2017-11-29 14:09:44 +08:00
    sorra
        1
    sorra  
       2017-11-24 18:19:26 +08:00
    当然是取最近的。
    你这个奇怪,可能是根据用法自动匹配了不同类型的 it,但这不合理,应该报编译错误才是编译器的合理设计。
    对开发者来说,这里要给参数命名,不应该使用 it。
    yufz
        2
    yufz  
       2017-11-24 19:06:06 +08:00
    这编译器不报错咩,神奇
    DeweyReed
        3
    DeweyReed  
       2017-11-24 19:26:43 +08:00
    一般为了可读性都会重命名
    list.forEach{ item -> ... }
    twoyuan
        4
    twoyuan  
    OP
       2017-11-24 21:28:08 +08:00
    @sorra #1 确实是应该有 warning 才合理一些,第一个 it 匹配到了带有 invoke 的 async 默认参数可以理解,第二个在两个 it 都有 toString 的情况下却匹配了正确的,让人觉得可怕……
    sagaxu
        5
    sagaxu  
       2017-11-24 21:39:25 +08:00
    sagaxu
        6
    sagaxu  
       2017-11-24 21:40:20 +08:00
    Expression 'it' of type 'Int' cannot be invoked as a function. The function 'invoke()' is not found
    SoloCompany
        7
    SoloCompany  
       2017-11-24 22:28:38 +08:00 via iPhone
    async block 哪来的输入参数,明明是 ()->?
    twoyuan
        8
    twoyuan  
    OP
       2017-11-24 23:13:23 +08:00
    @sagaxu #6
    @SoloCompany #7

    抱歉,async 是我自己随便封装的一个函数,忘了协程好像也有这个
    sorra
        9
    sorra  
       2017-11-25 10:37:45 +08:00
    属实,测试代码如下,可怕。谁去给官方报个 issue 啊
    ```

    fun sync(f: ((() -> Unit) -> Unit) -> Unit) {
    f {
    it()
    }
    }

    fun main(args: Array<String>) {
    sync {
    it {}
    (1..10).forEach {
    it {
    println(it)
    }
    }
    }
    }

    ```
    SoloCompany
        10
    SoloCompany  
       2017-11-25 19:49:43 +08:00
    @twoyuan 很正常, type inference 有时候因为过于智能会显得比较魔幻

    执行一下
    fun main(args: Array<String>) = run { val run = 1; run { print("run: $run") } }

    或者甚至 (后面这个会有个编译警告, 但警告的也仅仅是变量重名而不是 type inference 混淆)
    fun main(args: Array<String>) {
    val x: (() -> Any) -> Any = ::run;
    x { val x = 1; x { print("x: $x") } }
    }
    sorra
        11
    sorra  
       2017-11-26 11:37:02 +08:00
    @jinyang656 @SoloCompany @sagaxu
    https://discuss.kotlinlang.org/t/will-it-variable-stay-or-go/522/8
    2014 年有讨论,但直到 1.0 发布都没结论,于是为了兼容性搁置了问题。
    大概只能用 Lint 工具来解决了。
    SoloCompany
        12
    SoloCompany  
       2017-11-26 15:18:09 +08:00 via iPhone
    @sorra 这根本是两个问题好吗,请看我给出的例子,这个问题和 it 变量没有关系,只是类型推断系统过于智能是否合适的问题而已
    sorra
        13
    sorra  
       2017-11-26 16:30:59 +08:00
    帖子里讨论了嵌套 Lambda 的问题,对于重定义的 it 不报任何警告是危险的。显式的参数没那么危险。
    Java 的做法是禁止 Lambda 重定义局部变量。用匿名内部类就没有这个限制。

    题外话,Java 只允许 final 变量提升到闭包作用域,而 Scala/Kotlin 允许 var。

    这方面个人认为还是 Java 更严谨。
    SoloCompany
        14
    SoloCompany  
       2017-11-29 14:09:44 +08:00
    @sorra #13 重名的问题的确 error 比 warning 更合适, 不过有 lint 工具的话这个也不是什么大问题; 反而 mutable 变量不能在闭包中使用这一点我绝对认为 kotlin 的做法(当然只是 sugar) 更合理, 在没有更好选择的前提下为此写一个 wrapper 的做法简直就像破补丁一样太不优雅了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5064 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 08:02 PVG 16:02 LAX 00:02 JFK 03:02
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86