【问题标题】:Annotating the whole of a function declaration with a typealias使用类型别名注释整个函数声明
【发布时间】:2017-06-16 14:43:03
【问题描述】:

我的目标是使用typealias 作为“附加”到函数声明的一个单词提醒。说,

typealias VoidToVoid = () -> ()

我可以在声明预期的闭包类型时使用类型别名,因此

let f : VoidToVoid = { return }
assert(f is VoidToVoid)

但是,这似乎不是最常用的函数声明方式。我希望有一种方法可以告诉读者,像下面声明的 f′ 函数应该是 VoidToVoid 类型,并使用该名称。

(但是没有读者不得不推断、思考或等待编译器告诉他或她关于类型。更糟糕的是,编译器无法知道类型别名我想要 f′ 并且可能会输出说明裸类型而不是别名的消息。)

func f′() : VoidToVoid {  // tentative syntax
    return
}

我能到那里吗?

编辑:类型别名有两端使用。一方面,这现在是可能的:

func giveMeAClosure(_ f: VoidToVoid) {
    f()
}

另一方面,VoidToVoid 是隐含的:

func canBeGivenAsClosure() {
    // ...
}

即在canBeGivenAsClosure被声明的地方,通过VoidToVoid两端之间确实存在联系,但并不明显。这与let 的情况不同,后者可以将“VoidToVoid”作为其类型注释。

【问题讨论】:

    标签: swift function types


    【解决方案1】:

    闭包是未命名的闭包表达式,这就是为什么我们可以使用函数类型typealias 来指定闭包的类型,即使对于具有非空参数列表的闭包也是如此。

    typealias VoidToVoid = () -> ()
    typealias IntToVoid = (Int) -> ()
    
                      // unnamed closure expressions
    let f: VoidToVoid = { print("foo") }
    let g: IntToVoid  = { print($0) }
    

    请注意,这些示例中的fg 不是函数:它们只是不可变的属性,包含对在他们的声明。

    另一方面,函数是闭包的特例;一个有名字的闭包。此外,任何具有非空参数列表的函数都需要在其声明中提供内部(可选)和外部参数名称​​。但是,函数类型 typealias 可能不包含其参数名称的参数标签:

    typealias IntToVoid = (a: Int) -> ()
    /* Error: function types cannot have argument 
              label 'a'; use '_' instead */
    

    这意味着函数类型 typealias 不能用于替代函数的组合参数和返回类型声明部分(即使在 () -> () 的情况下也不行)。

    详情见例:

    关闭

    ...

    Functions 中介绍的全局和嵌套函数实际上是 闭包的特殊情况。闭包采用以下三种形式之一:

    • 全局函数是具有名称但不捕获任何值的闭包。
    • 嵌套函数是具有名称的闭包,可以从其封闭函数中捕获值。
    • 闭包表达式是用轻量级语法编写的未命名闭包,可以从周围的上下文中捕获值。

    另一方面,您可以自然地测试给定函数的类型到一些现有的函数类型typealias

    typealias VoidToVoid = () -> ()
    typealias IntToVoid = (Int) -> ()
    
    func f() -> () {}
    func g(_ a: Int) -> () { _ = a }
    
    print(f is VoidToVoid) // true
    print(g is IntToVoid)  // true
    

    【讨论】:

    • 然而,从类型的角度来看,将Int 转换为Void 的两个函数可以在它们的function-namefunction-signature 并且仍然作为值传递到期望未命名的IntToVoid 的位置。这就是我想表达的。
    • @B98 首先,请注意闭包是引用类型,因此函数和未命名的闭包都不是通过值传递,而是通过引用传递。据我了解您的问题,您想使用函数类型 typealias 来完全替换函数的 function-signature :这是不可能的。遵循 func 的语法。 decl.,function-signature 包含一个 parameter-clause,而它(对于非 void)又包含一个 parameter-list 和一个parameter:s 的数量和这些需要一个 local-parameter-name 的语法,它可能不存在于 typealias 中; ...
    • ...typealias 简单保存每个参数中的type-annotation(第二个必需部分)的值。跨度>
    • 我只想将函数类型作为一个单词,在不同的情况下可以通过typealias 功能获得。那么参数的名称就无关紧要了。例如,给定func g(f: IntToVoid),我想将“IntToVoid”附加到 func decls,其值,一个函数,可以传递给g
    • ...即,无论函数或闭包是通过复制传递还是通过引用传递。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-05
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 2017-06-17
    • 2019-07-05
    • 1970-01-01
    相关资源
    最近更新 更多