【问题标题】:"If a last argument lambda is passed to a function call outside the parentheses, passing no values for the default parameters is allowed"“如果最后一个参数 lambda 被传递给括号外的函数调用,则不允许为默认参数传递任何值”
【发布时间】:2019-02-23 05:57:35
【问题描述】:

我正在阅读 Kotlin 文档的 Default Arguments 部分,并且遇到了以下信息块:

但是如果最后一个参数 lambda 被传递给外部的函数调用 括号,不允许为默认参数传递任何值:

fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { ... }

foo(1) { println("hello") } // Uses the default value baz = 1 
foo { println("hello") }    // Uses both default values bar = 0 and baz = 1

我试图理解这里所说的内容。

我知道前 2 个参数不需要传递任何值。第三个参数似乎是一个返回Unit类型的函数。

这就是我从他们的解释中得到的全部信息:But if a last argument lambda is passed to a function call outside the parentheses, passing no values for the default parameters is allowed

我猜他们是说第三个参数不需要传入?

【问题讨论】:

    标签: lambda kotlin


    【解决方案1】:

    更新:文档现在是 updated,希望新的措辞更加清晰。

    原始答案如下。


    您需要前一句的上下文和代码块才能理解:

    如果默认参数位于没有默认值的参数之前,则 默认值只能通过调用带有命名的函数来使用 论据:

    fun foo(bar: Int = 0, baz: Int) { ... }
    ​
    foo(baz = 1) // The default value bar = 0 is used
    

    但是如果最后一个参数 lambda 被传递给外部的函数调用 括号,不允许为默认参数传递任何值:

    fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { ... }
    ​
    foo(1) { println("hello") } // Uses the default value baz = 1 
    foo { println("hello") }    // Uses both default values bar = 0 and baz = 1
    

    所以在一般情况下,如果您对除最后一个参数之外的所有参数都有默认值,则在仅使用该参数调用函数时,您必须显式命名最后一个参数,因为没有办法编译器知道您正在尝试传递该特定参数,而不仅仅是参数列表中的第一个参数。

    但是,由于在函数调用的括号外传入 lambda 的语法仅限于作为 very last parameter of the function 的 lambda,因此编译器可以确定您试图在第二个中传入 qux例子。

    【讨论】:

    • 谢谢,这是有道理的 - 我现在明白语法是如何工作的。但我只是没有看到一个可以使用它的可行示例。
    • 在很多情况下,您希望将 lambda 传递给函数,并且 有时 参数化它的使用方式。例如,您可能有一个 execute 函数,您通常只使用 lambda execute { println("foo") } 调用它,但它具有默认参数,您可以在其中调整它如何执行您的 lambda,例如 execute(thread = ..., times = 3) { println("foo") }
    【解决方案2】:

    但是如果最后一个参数 lambda 被传递给外部的函数调用 括号,不允许为默认参数传递任何值。

    这意味着你可以像这样调用foo函数而不带括号:

    foo { println("hello") } 
    or
    foo(1) { println("hello") }
    or
    foo(1, 2) { println("hello") }
    

    加上括号,它看起来像这样(请注意,在前两个示例中,我们需要指定参数名称qux):

    foo(qux = { println("hello") })
    or
    foo(1, qux = { println("hello") })
    or
    foo(1, 2, { println("hello") })
    

    【讨论】:

    • 你的第四个和第五个例子不起作用,你在位置上传递了一个 lambda,用于期望 Int 的参数。
    猜你喜欢
    • 2012-05-22
    • 2018-07-20
    • 1970-01-01
    • 2020-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多