为复数创建我自己的自动装箱 class
Creating my own autoboxed class for complex numbers
所以众所周知,在Swift声明一个class,你说
let variable = ClassName(parameters)
然而,要声明像数组和整数这样的东西,你可以只说
let variable = 32
(而不是 Int(32))
let variable = [3,2,4]
(而不是 let variable = Array<Int>(3,2,4)
假设我想为可以这样声明的复数(虚数)创建一个 class:
let complexNumber = 5i
或
let complexNumber = 3i
请注意,复数不一定是问题的重点,让您自己拆箱是
Swift 文字
在 Swift 中,您描述的这些语法称为“文字”,这是初始化符合特定协议集的类型值的便捷方式。文字的语法不是 user-extensible,因为它依赖于 Swift 解析器来理解如何解析它们。支持的是:
Literal
Protocol
Integer
ExpressibleByIntegerLiteral
Floating-Point
ExpressibleByFloatLiteral
String
ExpressibleByStringLiteral
Extended Grapheme Cluster
ExpressibleByExtendedGraphemeClusterLiteral
Unicode Scalar
ExpressibleByUnicodeScalarLiteral
Boolean
ExpressibleByBooleanLiteral
Nil
ExpressibleByNilLiteral
Array
ExpressibleByArrayLiteral
Dictionary
ExpressibleByDictionaryLiteral
(参见 NSHipster's article about literals for more details)。
但我更广泛地理解您的观点:您想在 Swift 代码中以类似的方式表达来自另一个领域(例如数学)的语法,因此该领域的 subject-matter 专家很熟悉.
有很多解决方法,具体取决于具体问题。
对于您的复数示例,可以定义一个新的 Complex
类型,使用 *
运算符和 i
值,这样您就可以编写:
let complexNumber = 5 * i
有很多数字编程库(特别是 first-party swift-numerics,它们定义了此类类型(尽管语法不一定相同)。
您还可以看到 Apple 使用 SwiftUI 做了什么,使用 result-builders 构建了一个 Swift DSL 来雄辩地描述视图层次结构。
奖金:这不是“拳击”
这里没有拳击比赛。我怀疑您来自 Java 背景,其中装箱是分配对象以存储原始类型的过程,因为只有这样它们才能传递到对象中(例如存储到像 [=15= 这样的容器中) ]).
Swift 并非如此。没有“原始”类型。有引用类型(类 和 class-bound 协议存在的实例)和值类型(结构、枚举和协议存在)。 Swift 的具体化泛型可以处理类似的值和引用对象,例如Int
可以直接进入 Array<Int>
。所以大多数时候,没有拳击可做。
有些地方 Swift 遇到了使 Java 需要装箱值的相同问题:像数组这样的连续存储无法处理具有不同大小的元素,因此代码如下成为挑战:
let x: Array<Any> = [true, "abc", 123, someObject]
此外,还需要某种方式来表达如何处理不同类型的值(保留、释放、复制等)。
为了解决这些问题,编译器会自动生成代码,将这些值装箱到称为“存在容器”的箱子中,箱子存储这些值,table 函数指针描述可以对此值执行。虽然值的大小不同,但所有存在的容器都具有相同的大小,因此您可以用它们创建一个数组。
所以众所周知,在Swift声明一个class,你说
let variable = ClassName(parameters)
然而,要声明像数组和整数这样的东西,你可以只说
let variable = 32
(而不是 Int(32))
let variable = [3,2,4]
(而不是 let variable = Array<Int>(3,2,4)
假设我想为可以这样声明的复数(虚数)创建一个 class:
let complexNumber = 5i
或
let complexNumber = 3i
请注意,复数不一定是问题的重点,让您自己拆箱是
Swift 文字
在 Swift 中,您描述的这些语法称为“文字”,这是初始化符合特定协议集的类型值的便捷方式。文字的语法不是 user-extensible,因为它依赖于 Swift 解析器来理解如何解析它们。支持的是:
Literal | Protocol |
---|---|
Integer | ExpressibleByIntegerLiteral |
Floating-Point | ExpressibleByFloatLiteral |
String | ExpressibleByStringLiteral |
Extended Grapheme Cluster | ExpressibleByExtendedGraphemeClusterLiteral |
Unicode Scalar | ExpressibleByUnicodeScalarLiteral |
Boolean | ExpressibleByBooleanLiteral |
Nil | ExpressibleByNilLiteral |
Array | ExpressibleByArrayLiteral |
Dictionary | ExpressibleByDictionaryLiteral |
(参见 NSHipster's article about literals for more details)。
但我更广泛地理解您的观点:您想在 Swift 代码中以类似的方式表达来自另一个领域(例如数学)的语法,因此该领域的 subject-matter 专家很熟悉.
有很多解决方法,具体取决于具体问题。
对于您的复数示例,可以定义一个新的 Complex
类型,使用 *
运算符和 i
值,这样您就可以编写:
let complexNumber = 5 * i
有很多数字编程库(特别是 first-party swift-numerics,它们定义了此类类型(尽管语法不一定相同)。
您还可以看到 Apple 使用 SwiftUI 做了什么,使用 result-builders 构建了一个 Swift DSL 来雄辩地描述视图层次结构。
奖金:这不是“拳击”
这里没有拳击比赛。我怀疑您来自 Java 背景,其中装箱是分配对象以存储原始类型的过程,因为只有这样它们才能传递到对象中(例如存储到像 [=15= 这样的容器中) ]).
Swift 并非如此。没有“原始”类型。有引用类型(类 和 class-bound 协议存在的实例)和值类型(结构、枚举和协议存在)。 Swift 的具体化泛型可以处理类似的值和引用对象,例如Int
可以直接进入 Array<Int>
。所以大多数时候,没有拳击可做。
有些地方 Swift 遇到了使 Java 需要装箱值的相同问题:像数组这样的连续存储无法处理具有不同大小的元素,因此代码如下成为挑战:
let x: Array<Any> = [true, "abc", 123, someObject]
此外,还需要某种方式来表达如何处理不同类型的值(保留、释放、复制等)。
为了解决这些问题,编译器会自动生成代码,将这些值装箱到称为“存在容器”的箱子中,箱子存储这些值,table 函数指针描述可以对此值执行。虽然值的大小不同,但所有存在的容器都具有相同的大小,因此您可以用它们创建一个数组。