【问题标题】:Uncertain of this Swift struct syntax with closure不确定这种带有闭包的 Swift 结构语法
【发布时间】:2021-12-30 11:31:50
【问题描述】:

我被一些 Swift 结构语法难住了。

对于常规结构,我了解如何定义和初始化它。

struct Thing {
    let name: String
}

let aThing = Thing(name: "The Name")

但我在阅读一些有关函数式编程的内容时遇到了这种语法,最让我难过的是初始化。

struct Effect<T> {
    let run: (@escaping (T) -> Void) -> Void
}

// What is "callback" here? How does this work?
let anIntInTwoSeconds = Effect<Int> { callback in
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
        callback(42)
    }
}

anIntInTwoSeconds.run { theInt in
    print(theInt)
}

如果我用“普通”初始化程序看到它,我会理解的,但是这条线上发生了什么?这个语法叫什么,所以我可以进一步研究它?

let anIntInTwoSeconds = Effect<Int> { callback in

【问题讨论】:

  • 你知道trailing closures吗?
  • 它的语法与anIntInTwoSeconds.run { theInt in 行完全相同。你明白那句台词吗?
  • 让我确认我确实理解 .run 行... run 是一个返回 Void 的函数。它接受一个函数。该函数接受一个 Int 并返回 Void。所以那行说,嘿,运行,执行这个函数。如果那是正确的,我在另一行仍然很模糊。
  • 我会换一种说法。 Run 是一个持有闭包的属性。 (一个匿名函数。)run 闭包的参数是 Generic,这意味着传递给闭包的参数取决于用于创建 Effect 结构的类型。
  • (因此Effect&lt;Int&gt; 结构的运行参数是(Int) -&gt; Void 类型的闭包。Effect&lt;String&gt; 结构的运行参数将是(String) -&gt; Void 类型。)

标签: swift functional-programming


【解决方案1】:

Effect type的声明

struct Effect<T> {

将 Effect 定义为使用 Generic 类型 T。因此您可以创建适用于不同类型的 Effect 对象。

线

let anIntInTwoSeconds = Effect<Int> { callback in

创建一个对 Ints 进行操作的 Effect 对象,并将其分配给变量 anIntInTwoSeconds

{ callback in 部分定义了 Effect 对象的闭包。该声明可以这样重写:

let anIntInTwoSeconds = Effect<Int>(run: { callback in
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
        callback(42)
    }
}
)

你可以解释为:

'创建一个 Effect 结构的实例,其 run 属性包含以“{ callback in”开头的闭包...'

(这很令人困惑,因为 run 属性本身就是一个闭包。所以我们创建了一个 Effect 实例,并传递给它一个作为闭包的“运行”值。)

具体来说,“callback in”部分告诉编译器,在闭包内,闭包的参数应该命名为“callback”。

【讨论】:

  • 这把我的面条弄弯了。 ;-)
  • let anIntInTwoSeconds = Effect&lt;Int&gt; { callback in 语法是否有效,因为 run 属性是结构上唯一定义的属性?
  • 我不确定,TBH。那是我以前从未见过的变体。还有另一种情况称为“尾随闭包语法”,当您调用函数时,如果最后一个参数是闭包,您可以在括号外提供闭包。这看起来与那个相似,但我不确定是什么使它合法。
  • “这把我的面条弄弯了。”听起来很痛苦。
  • @DuncanC 我相信它是尾随闭包语法,就在init 上。成员初始化将类似于init(run: @escaping ((T) -&gt; Void) -&gt; Void),类似于在没有() 的情况下初始化VStack 之类的东西。我不知道如果您手动创建了init,嵌套的@escaping 是否有任何影响。
猜你喜欢
  • 2021-02-07
  • 1970-01-01
  • 1970-01-01
  • 2016-08-20
  • 2018-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-19
相关资源
最近更新 更多