讨论在 Swift 中引入函数体宏

前言

文章内容精选

提案:函数体 Macros 提案正在审查中

Swift 论坛:Swift 中引入函数体宏

话题讨论:

你是更能接受同性上司还是更能接受异性上司?

上期话题结果

投票结果反映,大多数开发者还是比较担心自己的头发,另外就是身体变胖。久坐缺乏运动会导致一系列的身体健康问题。建议大家抽时间多运动,避免久坐。

提案

通过的提案

SE-0411 隔离的默认值表达式 提案通过审查。该提案已在 四十期周报 正在审查的提案模块做了详细介绍。

正在审查的提案

SE-0414 基于区域的隔离 提案正在审查。

Swift Concurrency 将值分配给由 actor 和任务边界确定的隔离域。在不同隔离域中运行的代码可以并发执行,并且通过 Sendable 检查,防止非 Sendable 值跨越隔离边界传递,从而彻底消除对共享可变状态的并发访问。在实践中,这是一个重要的语义限制,因为它禁止了无数据竞争的自然编程模式。

在本文档中,我们提出通过引入一种新的控制流敏感的诊断来放宽这些规则,该诊断确定非 Sendable 值是否可以安全地在隔离边界上传递。通过引入隔离区域的概念,编译器可以保守地推断两个值是否可能相互影响。通过使用隔离区域,语言可以证明在将非 Sendable 值传递过隔离边界后,该值(以及可能引用它的任何其他值)在调用者中不会被使用,从而防止竞争的发生。

SE-0415 函数体 Macros 提案正在审查。

宏通过附加代码来增强 Swift 程序,其中包括新的声明、表达式和语句。目前,宏系统不支持可能希望增强代码的关键方式之一,即合成或更新函数的主体。可以创建具有自己函数主体的新函数,但不能为用户声明的函数提供、增强或替换函数主体。

该提案引入了函数体宏,确切地说:允许根据声明全面合成函数主体,以及通过更多功能增强现有函数主体。这为宏提供了许多新的用例,包括:

  • 根据函数声明和一些元数据(例如自动合成传递提供的参数的远程过程调用)全面合成函数主体。
  • 通过执行日志/跟踪、检查前置条件或建立不变量来增强函数主体。
  • 根据提供的实现替换函数主体。例如,将主体移入在其他地方执行的闭包中,或将主体视为宏"降低"为可执行代码的特定领域语言。

Swift论坛

  1. 提议SE-0415:函数体宏

内容概括

SE-0415 提议在 Swift 中引入函数体宏。 该提案的审核期截至 2023 年 12 月 20 日。该提案建议启用一项可通过带有 -enable-experimental-feature BodyMacros 标志的主干开发快照访问的功能。

审核过程鼓励反馈以改进提案。 它要求审阅者评估所解决问题的重要性、提案是否符合 Swift 的方向,并将其与其他语言或库中的类似功能(如果适用)进行比较。 Tony Allevato 作为审核经理负责监督此审核流程。

讨论的序言中提出的一个具体问题提到,所提议的宏可能无法有效地处理从函数体抛出的错误。 有人建议使用一种新的延迟块来捕获抛出的错误,从而允许访问块内的这些错误以进行处理。

所提出的语法示例演示了一个概念,其中 defer 块可能会捕获从函数体抛出的错误并执行报告错误和重新抛出错误等操作。

  1. 讨论枚举案例类型签名/插值

内容概括

讨论围绕获取具有关联值的枚举情况的字符串表示,特别是寻求一种为每种情况生成类型化签名或插值的方法。 一个示例枚举了具有关联值及其预期输出签名的各种情况。

当前的方法涉及使用反射,但由于反射元数据对应用程序二进制大小的影响,因此存在可能删除反射元数据的担忧。 另一种考虑的方法是使用宏,但这些可能不适用于较旧的操作系统版本,从而带来兼容性挑战。

该对话强调了与处理重复的枚举案例名称相关的编译器错误,该错误使枚举实例的唯一性变得复杂。

核心需求是为某些枚举案例的所有实例导出一个稳定的 hashValue,无论它们的关联值如何,旨在将具有相同案例名称但不同关联值的实例视为相同的存储目的。 然而,传统的 Hashable 实现不足以实现此目的。

一个探索的想法涉及利用 String(describing:) 生成枚举案例的字符串表示形式,但如果客户端为枚举实现 CustomStringConvertible,则这种方法可能会失败。 人们有兴趣了解如何调用枚举描述的默认 Swift 标准库实现,以解决 CustomStringConvertible 的客户端实现所产生的问题。

  1. 讨论~Copyable 类型中不可用的 deinit

内容概括

讨论围绕着 ~Copyable 类型中不存在不可用的 deinit 以及它对程序员构建代码以与本地数据流分析保持一致的依赖展开。

不可破坏类型的概念旨在增强本地数据流分析并提供编译时保证。 它类似于函数的想法,从技术上讲,函数承诺返回一些东西,但实际上却没有,而编译器静态地证明了理论上的不可能。

该提案引入了不可破坏类型(Destructible)作为取代Copyable 的新根类型。 它设想了类型不需要显式反初始化的场景,依赖编译器的静态分析来强制执行预期的清理例程。

讨论对比了使用和不使用此功能时 API 使用的难度,强调了需要显式清理时面临的潜在挑战。 对 API 文档、运行时检查和潜在风险的仔细研究与用于防止错误使用的编译时诊断进行了比较。

对话承认实现此功能的潜在复杂性以及收益是否值得付出努力的不确定性。 它引用了 Scott Meyers 关于使接口易于正确使用且难以错误使用的名言,强调了编程接口简单性和清晰性的重要性。

  1. 展示Advent of Code 2023

内容概括

Swift 社区受邀参加"Advent of Code",这是一项从 12 月 1 日到 12 月 25 日举办的年度编码挑战赛。 这项挑战由 Eric Wastl 组织,涉及日常编码练习,开始时很简单,逐渐变得更具挑战性。

参与者可以使用任何编程语言,但有一个 Swift 团队模板可供那些喜欢 Swift 的人使用。 该模板提供了解决挑战的起点。

加入:

  1. 克隆 Swift 团队的入门模板(可选)。
  2. 在 Advent of Code 网站上创建一个帐户(参与排行榜所需)。
  3. 使用ID 3315857-f51d8ce5加入Swift社区排行榜。

我们鼓励参与者每天使用 Swift 尝试挑战。 排行榜跟踪完成时间,但分数只是为了好玩,可以忽略。

排行榜允许那些想要分享解决方案的人链接到 GitHub 帐户,为参与者提供了互相学习方法的机会。

这是一个社区活动,并不正式隶属于 Swift 项目,旨在整个 12 月享受乐趣、提高 Swift 技能并享受一些编码挑战。 参与者被警告,随着挑战变得更加严峻,挫败感可能会出现!

  1. 讨论Swift OpenAPI Generator 1.0.0-alpha.1(候选发布版)已发布(Multipart、base64、过滤、递归类型等)

内容概括

Swift OpenAPI Generator 团队已发布版本 1.0.0-alpha.1,该版本作为即将发布的 1.0 版本的候选版本,预计将在大约两周内发布。 1.0 的主要重点是增强文档和示例,没有计划更改代码。

自 2023 年 5 月以 0.1.0 版本首次开源以来,Swift OpenAPI Generator 已经取得了实质性进展。 合并了 200 多个拉取请求,产生了 24 项更新并引入了重要的新功能。

主要亮点:

  • 新功能包括对 Base64 编码数据的支持、文档过滤、递归类型支持、服务器 URL 模板变量支持以及具有类型安全和流式传输的多部分内容类型支持。
  • 此外,生成代码的可自定义访问修饰符允许在公共、包(默认)和内部可见性之间进行选择。
  • 该版本还包含各种改进和错误修复,例如将 Swift 5.9 更新为最低支持版本、错误处理增强以及生成的代码注释的细化。

重大变更和迁移:

  • 该版本包括 API 反馈所必需的重大更改。 提供了将代码从版本 0.3.x 迁移到 1.0.0-alpha.1 的指南,详细说明了潜在的构建错误及其解决方案。

下一步是什么:

  • 版本 1.0.0-alpha.1 作为候选版本,邀请反馈意见被考虑用于计划在两周内发布的最终 1.0.0 版本。 鼓励用户测试 alpha 版本以确保与其项目的兼容性。

该团队对贡献者表示感谢,并邀请通过 Swift OpenAPI Generator GitHub 存储库进一步参与。

  1. 讨论可编码不正确的 Json 字符串,包含 URL 和十进制存在值

内容概括

该对话探讨了 Swift Codable 协议在处理存在类型时的细微差别,特别是涉及 URL、Decimal 和 AnyEncodable 的可编码行为。

讨论解决了使用存在类型时期望与实际行为之间的差异。 值得注意的是,当抽象具有预期行为(例如,meow())的 Cat 等类型的实例时,预期 Cat 的所有实例都将统一表现出该行为。 当使用encode()时,内部表示(例如Decimal类型)会出现在最终的JSON字符串中,这会让人感到惊讶,从而导致方法分派和类型编码的混乱。

该演讲深入探讨了 Codable 的基础知识以及存储类型信息以进行解码的必要性。 出于安全性和互操作性原因,可编码省略了编码数据中的类型信息,因此需要在代码中预定义以进行解码。 这种方法允许解码不明确的值,但对类型擦除的值(如 AnyEncodable)带来了挑战,使得在解码期间难以对类型进行逆向工程。 如果解码时不知道类型,则不可能重建原始数据。

所讨论的警告方面围绕着未来可能需要解码的场景。 如果在不考虑未来解码要求的情况下做出编码决策,则可能会使数据检索变得复杂。

最后,讨论暗示了从枚举案例数组中收集枚举时的挑战���注意事项,强调了编码和解码策略的复杂性以及在设计导出或序列化工具时深思熟虑的重要性。

  1. 讨论是否可以自动验证值更改并抛出错误?

内容概括

本讨论围绕自动验证值更改的概念展开,旨在消除 CRUD 方法中出现的显式验证调用。 对话的重点是在 Swift 构造中实现自动验证的挑战。

该示例使用 Name 结构来探索拦截值访问以进行实时验证的潜在方法。 然而,诸如计算属性或属性观察器之类的现有机制缺乏对在验证过程中抛出错误的直接支持。 这一限制对在 Swift 结构中无缝实现自动验证造成了重大障碍。

这次对话强调了手动验证的必要性,即使是基本类型,因为从这些基本类型构建的复杂类型会产生复杂性。 例如,讨论介绍了 Employee 结构体,并说明了对其 addr1 和 addr2 属性的手动验证规则的需求,强调尽管基本类型具有验证机制,但手动验证在复杂类型级别至关重要。

尽管函数体宏被认为是另一种潜在的方法,但讨论主要集中在计算变量或动态查找功能是否可以支持自动验证,最终表达了对在 Swift 现有机制中实现它的可行性的怀疑。

提出了两种建议的"手动"方法:

  1. 使用 let 代替 var 字段,并在构造函数中加入验证逻辑,使其失败。
  2. 在外部执行验证,如果验证失败,则利用 didSet 恢复到之前的值。

这些手动方法旨在在更改期间同步强制验证,确保值保持一致。 但是,后一种方法可能会暂时使不变量无效,但可能适用于可接受同步验证的场景,例如避免由于暂时不正确的值导致的 UI 闪烁。

话题讨论

你是更能接受同性上司还是更能接受异性上司?

能 不能

欢迎在文末留言参与讨论。

关于我们

Swift社区 是由 Swift 爱好者共同维护的公益组织,我们在国内以微信公众号的运营为主,我们会分享以 Swift实战SwiftUlSwift基础为核心的技术内容,也整理收集优秀的学习资料。

特别感谢 Swift社区 编辑部的每一位编辑,感谢大家的辛苦付出,为 Swift社区 提供优质内容,为 Swift 语言的发展贡献自己的力量。

相关推荐
Magnetic_h6 小时前
【iOS】单例模式
笔记·学习·ui·ios·单例模式·objective-c
归辞...7 小时前
「iOS」——单例模式
ios·单例模式·cocoa
humiaor8 小时前
Xcode报错:No exact matches in reference to static method ‘buildExpression‘
swiftui·xcode
yanling20239 小时前
黑神话悟空mac可以玩吗
macos·ios·crossove·crossove24
归辞...11 小时前
「iOS」viewController的生命周期
ios·cocoa·xcode
crasowas15 小时前
Flutter问题记录 - 适配Xcode 16和iOS 18
flutter·ios·xcode
2401_8524035515 小时前
Mac导入iPhone的照片怎么删除?快速方法讲解
macos·ios·iphone
SchneeDuan15 小时前
iOS六大设计原则&&设计模式
ios·设计模式·cocoa·设计原则
JohnsonXin1 天前
【兼容性记录】video标签在 IOS 和 安卓中的问题
android·前端·css·ios·h5·兼容性
蒙娜丽宁1 天前
Go语言错误处理详解
ios·golang·go·xcode·go1.19