欢迎来到第 124 期 Swift Weekly Brief!这是我作为撰稿人身份的第一期。我一直对 Swift 社区及开源保持好奇。

三年前的今天,Swift 宣布开源。回过头看,这是一段多么美妙的过程。

最近 Swift 团队似乎想赶在即将到来的新年前把所有的任务完成,他们接受了 Result 提案以及发布了 Swift 5.0 nightly builds 版本。

入门任务

  • SR-8728 [Compiler] Add note about conditional conformance to RandomAccessCollection docs
  • SR-8513 [Compiler] Confusing error messages for interactions between same-name types from different modules

Swift Unwrapped

Jesse 和 JP 在最新一期 Swift Unwrapped 中一起探讨了最近热议的 Result 提案,分享他们认为的优点和缺点。

社区新闻

Swift Server 工作组召开了一次会议。他们不仅添加了一些新成员,而且还讨论了一些重要的话题,如 Docker 包的更新,加密方案,HTTP 端的优化等等。

Yasuhiro Inami 开源了 SwiftRewriter,一个依赖于 SwiftSyntax 的 Swift 代码格式化工具。

Bruno Rocha 写了篇文章介绍 Swift 中 @dynamicMemberLookup 修饰符的工作原理

Ole Begemann 写了篇文章介绍将 Swift 4.2 中的 Sequence 对象分开头部和尾部,由于 SE-0234 这种方法会在 Swift 5 中失效。

亚马逊开源了 smoke-framework,一个使用 Swift 语言编写的,搭建于 Apple 的 SwiftNIO 之上的开源轻量级服务器端框架。

合并请求

Michael Ilseman 合并了一个 pull request,从而允许访问 String 底层的原生 UTF-8 码元,这要归功于 Sequence 协议中定义的 String.UTF8View.withContiguousStorageIfAvailable 方法。

Slava Pestov 合并了一个 pull request,关于在元类型(metatype)用于具有单个元组类型参数的函数时,使元类型的打印结果更容易理解。这个问题源自 SR-8235

Joe Groff 合并了一个 pull request 关于为运行时错误添加额外的源位置信息。

Harlan Haskins 合并了一个 pull request 用于加固用于检查访问器与其他声明的函数,确保我们正确地检查 setter 的访问以及常规声明的访问。修复 SR-8969

新晋提案

SE-0235: Add Result to the Standard Library 经过修改后被接受

核心团队认可了某几位审核成员关于 Result 的正确使用方式的观点。我们绝对同意将 Result 添加到语言中是重要的一部分,我们也打算在发布时一并提供此使用方式的指南。

虽然我们再次修改该提案,但核心小组认为这些问题已经得到了充分的审查,并且没有必要进行第三轮审查。因此,SE-0235 经修改后被接受。

SE-0236: Package Manager Platform Deployment Settings 被接受

现在有很多针对提案的平台限制部分的负面反馈,SwiftPM 团队决定接受只处理部署目标可定制化提案的修订版本。平台限制那部分提案会在以后的时间再重新提出。

为了指定自定义部署版本,原始提案里提及到的初始化方法将会一并提供。但是,由于这将过于冗长,将使用字符串重载来代替。这种情况下,API 会变成 .macOS("10.13") 而不再是 .macOS(MacOSVersion("10.13"))

SE-0238: Package Manager Target Specific Build Settings 被接受

这个提议用于在 Package.swift 清单文件中声明一些常用的,特定于构建目标的构建设置。顾名思义,特定于目标的构建设置仅适用于特定目标。 SwiftPM 还旨在支持跨目标边界的跨目标构建设置,并为构建目标的依赖提供某些设置,但此提议仅关注前一种构建设置,后者将在未来的提案中进行探索。

SE-0237 Introduce withContiguous{Mutable}StorageIfAvailable methods 被退回修改在经过修改后被接受

The Core Team felt that the use of inout for the closure parameter of withUnsafeMutableBufferPointer(IfSupported) was the best available option, and noted that the library could verify that the UnsafeMutableBufferPointer itself wasn’t directly modified by checking for the expected base address / count after the call. This limits the chance of confusion without resorting to shadowing or excessive overloading of mutating operations.

The two proposed protocols (ContiguousCollection and MutableContiguousCollection) aren’t used in any algorithms within the library. It is not clear that they are important enough to introduce as protocols into the Standard Library at this time. The Core Team would like to consider a revised proposal that does not introduce these protocols.

There are use cases for a Sequence equivalent to the proposed withUnsafeMutableBufferPointerIfSupported, such as initializing a String from a Sequence of UTF-8 code points that are (e.g.) stored in a Data. The Core Team would like to see this addition to the Sequence protocol, which would allow Sequence clients to optimize for the contiguously-stored case without requiring a new protocol, much as the proposal already allows MutableCollection clients to optimize for the contiguously-stored mutable case.


The revised proposal shows the changes, which are:

  • Sequence will have a new (defaulted) requirement withContiguousStorageIfAvailable, and
  • MutableCollection will have a new (defaulted) requirement withContiguousMutableStorageIfAvailable.

论坛动向

亚马逊最近推出了 Lambda Runtime API,可与任何编程语言配合使用。Ted Kremenek 认为这对于 Swift 服务器端生态系统是重要的一步

Swift 中的 Async/Await 特性尚未有实现方案,但社区有个帖子介绍通过添加取消功能来改进它

写这篇帖子是为了讨论出一致且简单的 API 来取消异步任务。我认为,支持取消异步任务的功能,对于许多程序员来说会很麻烦,因为它有点复杂并且应用程序其实没有它也可以运行,只是性能可能会受到影响。有了这个提议,取消功能变成更简单,因而更有可能被程序员实现。

SwiftNIO 团队正打算swift-nio-ssl 的 TLS 实现从原来的 libssl 替换为 BoringSSL

我们建议停止 swift-nio-ssllibssl 的依赖,并切换使用 BoringSSL。此更改将可能导致许多微妙不稳定的运行时行为,以及一些应用程序分发和操作系统的不确定行为。

提议将放弃对 OpenSSLLibreSSL 的支持。这样做的原因将在后面的提案中讨论,并且不一定是强制性的。

请注意,对于 Apple 平台,推荐的 TLS 方案仍然是使用 swift-nio-transport-services

上个星期,JP Simard 写了篇文章说 SwiftSyntax 性能很差,然后 Swift 团队开了个帖子讨论优化方案

对解析器的直接访问可以将 SwiftSyntax 的速度提高 8 倍,它比传统的 sourcekitd 语法快 2 倍。

大家都看过 Matttobsession of Strings 演讲吧,他最近起草了 Unicode Named Character Escape Sequence

此提议为 Swift 字符串字面量(string literal)添加了一个新的 \ N {name} 转义序列(escape sequence),其中 name 是 Unicode 字符的名称。

每个 Unicode 字符都分配了一个唯一的码位(code point),一个介于 U+0000U+10FFFF 之间的数字,以及一个由大写字母(A-Z),数字(0-9),连字符和空格组成的名字。例如,英语中使用的字母 “A” 的 Unicode 字符的码位为 U+0041,名称为 LATIN CAPITAL LETTER A。术语标量值定义的是那些不构成代理对(surrogate pair)的 Unicode 码位子集。

在 Swift 中,字符串字面量可以直接包含一个字符(“A”)或使用 \u{n} 转义序列,其中 n 是对应于标量值的 1-8 位十六进制数字("\u{0041}")。字符串字面量也可以通过插值的方式包含字符(let letterA = "\u{0041}"; "\(letterA)")。

这里有一个帖子讨论 Swift 5 中元组的 KeyPaths

.. 我发现 \SomeType.aTuple.0 这种语法会报错 ..

我认为对于想贡献代码的开发者来说,这是一个很好的新手入门任务。keypath 的运行时 ABI 不需要额外的修改来进一步处理元组。这里有一个 ABI 文档描述 keypath 对象的细节,有些地方可能过时了,但是高层的结构大体是一致的。

有个网友在论坛询问,在 ABI 稳定后,是否会投入更多的资源改进 Swift 糟糕的诊断和类型推断

有两样东西我非常希望可以有所改进:诊断和类型推断,特别是当碰到闭包和范型的时候。(我也开始认识到带有关联类型协议(protocols with associated types, PATs)的局限性了。)

  1. 将来会有哪些方案解决这些烦恼?
  2. 关注 ABI 稳定性是导致这些问题仍然存在的主要原因吗?
  3. ABI 稳定后的 Swift evolution 会着重改进哪些方面?

尾声

你可以写出关于 Swift 的诗歌和俳句吗?是的,我们可以