Swift 周报 第二十七期( 二 )


Swift 周报 第二十七期

文章插图
介绍
之前的 SE-0393 引入了类型参数包和几个相关概念,允许泛型函数声明抽象出可变数量的类型 。该提案将这些想法概括为泛型类型声明 。
动机
当试图在集合上概括通用算法时,自然会出现对可变数量的类型进行抽象的通用类型声明 。例如,惰性可能在两个序列上是通用的 。可以声明一个类型,它将固定序列列表的元素表示为元组序列:
struct ZipSequence: Sequence {typealias Element = (repeat each S.Element)let seq: (repeat each S)func makeIterator() -> Iterator {return Iterator(iter: (repeat (each seq).makeIterator()))}struct Iterator: IteratorProtocol {typealias Element = (repeat each S.Element)var iter: (repeat each S.Iterator)mutating func next() -> Element? {return ...}}}
建议的解决方案
在泛型类型的泛型参数列表中,each 关键字声明了一个泛型参数包,就像它在泛型函数的泛型参数列表中所做的那样 。存储属性的类型可以包含包扩展类型,如上面的 let seq 和 var iter 。
讨论点前缀被认为是丑陋的
虽然我们已经习惯了,但在静态成员和枚举常量前加上点会引入视觉噪音,看起来太聪明了,总是让我的其他语言背景的同事感到惊讶:
func foo(_ v: Color) {...}object.foo(.red) //
在声明中缺少点前缀之间也存在这种令人不安的不对称性:
enum Color {case redcase greenstatic var blue = ...}
并在其他地方使用这些前缀:
switch color {case .red: breakcase .green: break}foo(.red)foo(.blue)
有趣的是,我已经可以在某些上下文中使用“.foo(red)”(例如,在 Color 的静态方法中),但不能在其他上下文中使用 。
我很欣赏这将是一个突破性的变化,我们不可能在现阶段迅速适应这一变化 。暂时忘记这一点,你认为 Swift 通过以下更改会变得更好还是更糟?
func foo(_ v: Color) {...}...object.foo(Color.red) // okobject.foo(.red)//prohibitedobject.foo(red)// ?switch color {case .red: break//prohibitedcase red: break// ?}dispatchPrecondition(condition: .onQueue(.main)) // dispatchPrecondition(condition: onQueue(main))// ?bar(.init()) // bar(init())// ?// While choosing what "red" to use – follow these new resolution rules:// - use local variable if exists// - or use instance variable if exists (in which case self should be captured strongly explicitly or implicitly)// - or use static variable if exists (in case of enum could be an enumeration constant)// - or use global variable if exists// - otherwise emit an error
讨论非类型可以在 Tasks 中捕获吗?
现在,我猜想下面的代码应该会出现任何错误 。
class SomeClass {var count: Intinit(count: Int) {self.count = count}}let someClass = SomeClass(count: 0)//public init(priority: TaskPriority? = nil, operation: @escaping @Sendable () async -> Success)Task {someClass.count += 1}//public init(priority: TaskPriority? = nil, operation: @escaping @Sendable () async -> Success)Task {someClass.count += 1}
但是,在 Swift(5.8 版)中,此代码片段可以编译 。在中,这段代码有没有出现错误?
回答:
在 Swift v. 中,全局必须与全局 actor 隔离,因此行 .count += 1 将需要:
整个 Task 闭包被隔离到同一个 actor,或者您为该操作切换到适当的 actor
(例如:await .run { .count += 1 })很难准确地说出在 Swift 6 中什么会/不会是错误 。您可以使用一些编译器标志来尝试一些事情,但它们是不一致的 。