Tag: 泛型编程

开始Swift编程第15部分-具有泛型和闭包的枚举

在上一篇文章中,我们讨论了错误处理。 开始进行Swift编程第14部分-错误处理 在上一篇文章中,我们讨论了泛型。 medium.com 我们介绍了有关如何创建自己的错误并在代码中使用它们而不只是崩溃的基础知识。 如果您有兴趣知道,我只剩下5个主题,然后向您指出一些我最喜欢的资源,这些资源可以帮助我编写程序。 本文将简短,但是它将结合一些我们已经学到的概念,并可能使您考虑如何以新的方式编写代码。 以前,当我们谈论枚举时,我告诉过您,它将为您提供选择的选项,而我们只限于那些选项。 我们可以在枚举案例中使用关联的值来定义使用枚举时将实例化的类型。 现在,我告诉您有关完全使用闭包,枚举和泛型的信息。 这是我从纳塔莎机器人那里学到的一个很酷的技巧,我在自己的代码中使用了很多。

Swift中函数的通用专业化

在今天的帖子中,我们将讨论Swift编译器的Generic专业化知识,并对它是什么以及SIL Optimizer为什么执行此操作以获得更高性能的代码进行基本概述。 此外,我们还将简要介绍Swift中间语言(SIL)表示形式以及它在此通用专业优化遍历中的作用。 首先… 编译器 在深入研究泛型专长之前,我们需要至少从高层次上了解有关编译器流程的一些知识。 swift编译器获取您的Swift代码,将其处理为手动编码的Lexer,将其标记化并将其转换为抽象语法树(AST),然后是语义分析(Sema),其中编译器将使用解析器生成的AST并进行类型检查的AST并检查其中的语义问题。 然后,Swift中级语言生成(SILGen)阶段将通过语义分析生成的AST转换为他们所谓的原始SIL,在对SIL进行了一些优化(如通用专业化,ARC优化等)之后……它生成了这种被称为规范SIL的优化SIL。然后将其交给IRGen生成中间表示(IR),该中间表示将传递给LLVM,以使其继续工作并生成目标文件(.o),该文件随后将由链接器粘合在一起并生成最终的二进制文件。 这是对编译器管道的简要概述。 这只是让我们了解编译器的各个阶段,但是在这里,我们将重点介绍发生通用专业化的SILGen和SIL Optimization Pass。 仅供参考,Swift中间语言(SIL)是一种静态单分配形式(SSA形式)中间表示形式,用于实现swift编译器,目的是在源代码与LLVM IR之间架起抽象桥梁,从而提供一种执行高级别的优化,例如通用专业化,保留/发布优化,动态方法去虚拟化等等……以及高级诊断分析。 您可以在快速主存储库的说明文件[1]中找到有关SIL的更多信息。 返回通用专业化 因此,泛型专业化是SIL优化过程,它分析了对泛型函数的所有调用(使用完整模块编译模式时在模块中)或具有@_specialize属性的泛型代码(我们将在后面讨论),然后生成新的特殊化这些函数的版本将泛型的所有专用用法替换为直接调用生成的专用函数。 使用专用函数的性能更高,因为它可以使用特定的具体类型最有效的布局,并且在诸如将参数复制到局部变量之类的操作中,例如,它避免了动态分配泛型类型和保存对运行时类型元数据大小和对齐方式的值见证表。 让我们看一下如何生成专用SIL的实际示例 生成的SIL上还有很多其他内容,但仅突出显示与我们定义的函数相关的内容。 仅查看生成的SIL,我们就可以看到编译器如何发出通用和专用SIL表示形式。 我们可以注意到,主SIL调用了函数@ $ S4main9incrementyxxs13BinaryIntegerRzlFSi_Tg5的引用,正如我们看到的那样,它是增量的专用版本。 这意味着主要功能正在调用优化的专用功能。 另外,我们可以注意到专用版本针对Int进行了完全优化,而在通用SIL上,所有操作都基于基于元类型信息的调用(应用)函数。 告诉SIL优化器不执行专业化 我们可以告诉编译器,由于某种原因,我们不希望使用@_semantics属性对该通用函数进行专用化。 您可以在HighLevelSILOptimizations文档的“优化语义”属性部分中找到有关语义的更多信息。 这就是本文的全部内容\ o / 如果您有任何意见或疑问,请告诉我。 您的反馈意见非常重要,因此我们可以改善此问题以及将来的帖子,很高兴收到它:)) 您可以在Twitter上@ LucianoPassos11找到我。 感谢您阅读🙂 参考文献 Swift中级Languange(SIL)。 https://github.com/apple/swift/blob/master/docs/SIL.rst SIL程序员手册。 https://github.com/apple/swift/blob/master/docs/SILProgrammersManual.md 泛型。 https://github.com/apple/swift/blob/master/docs/Generics.rst SIL中的高级优化。 https://github.com/apple/swift/blob/master/docs/HighLevelSILOptimizations.rst

Swift Generics的力量-第1部分

泛型函数,泛型类型和类型约束 当他们工作时,您爱他们,当他们不工作时,您恨他们。 😀😀 在现实生活中,每个人都知道仿制药的功效:早上起床,决定喝什么,加满杯子☕️ Swift是一种类型安全的语言。 每当使用类型时,都需要指定它们。 例如,我们需要一个可以处理多种类型的函数。 Swift已经提供了Any和AnyObject但是除非必须使用,否则最好不要使用它们。 使用Any和AnyObject将使我们的代码易碎,因为在编译期间我们将无法捕获类型不匹配的情况。 泛型是我们需求的解决方案。 通用代码允许您编写可重用的函数和数据类型,这些函数和数据类型可与任何与您定义的约束匹配的类型一起使用,同时提供编译时类型安全性。 它使您可以编写避免重复的代码,并以清晰抽象的方式表达其意图。 例如,诸如Array, Set and Dictionary类型的类型在该元素上是通用的。 假设我们必须打印整数和字符串数组。 我可以创建2个函数来完成这项工作。 让intArray = [1,2,3,4] 让stringArray = [a,b,c,d] func printInts(array:[Int]){ print(intArray.map {$ 0}) } func printStrings(array:[String]){ 打印(stringArray.map {$ 0}) } 现在,我必须打印浮点数数组或自定义对象的数组。 如果我们看一下上述功能,则所使用的类型只是区别。 因此,无需重复代码,我们可以编写可重用的泛型函数。 泛型函数可以使用由占位符类型T标识的任何类型。占位符类型名称并没有说明T必须是什么,但是它确实说两个array必须是T类型,无论T代表什么。 每次调用print(_:)函数时,都会确定要代替T使用的实际类型。 func print (array:[T]){ 打印(array.map {$ 0}) } 上例中的占位符类型T是类型参数。 通过在尖括号内用逗号分隔多个类型参数名称,可以提供多个类型参数。 如果我们看一下Array 和Dictionary ,它们有一个命名的类型参数,即Element&Key,Value,它说明类型参数与它所使用的泛型类型或函数之间的关系。 注意:始终为类型参数提供大写的驼峰名称(例如T和TypeParameter ),以表明它们是类型的占位符,而不是值。 […]