Swift 读标准库源码笔记 -- Integers(基本数据类型篇)
Integers
按照由基本到复杂的逻辑走,先从数据基本类型说起。每句代码都会看,会翻译备注,直接的记笔记。
涉及文件:
- IntegerTypes.swift.gyb
- Integers.swift
- IntegerParsing.swift
源码链接:https://github.com/apple/swift/blob/master/stdlib/public/core
.gyb文件是什么
GYB(模板生成)是一个 Swift 内部使用的工具,可以用模板生成源文件。
问:在这里为什么要使用gyb文件?
答:Swift 标准库整型,它有诸如符号整数( Int8 , Int16 , Int32 , Int64 )这样的类型家族,其中各个类型的实现除大小之外没有其他不同。
拷贝粘贴可以作为一次性的解决方案(假设你第一次就做的没有错误),但这种方法无法继续维护。每当你想修改这些派生的实现,都会有引入细微不一致的风险,久而久之导致这些实现变得不相同——有一点类似于地球上生命的多样性是因为基因随机突变导致的一样。
从 C++ 模板和 Lisp 宏到 eval 和 C 预处理器指令,不同的语言使用不同的技术来应对这个问题。
Swift 没有宏系统,并且因为标准库本身是使用 Swift 编写的,所以它也不能利用 C++ 元编程的能力。因此,Swift 的维护者们使用一个叫作 gyb.py 的 Python 脚本和一些模板标签来生成代码。
详细了解参考两篇文章理解:
http://ju.outofmemory.cn/entry/363956
https://www.jianshu.com/p/35e2ca4592cf
读Integer.swift源码
第一段:初始化
// FIXME(integers): This should go in the stdlib separately, probably.
// 大神也有可爱和不确定的地方,他认为这部分似乎可以从stdlib分开
extension ExpressibleByIntegerLiteralwhere Self : _ExpressibleByBuiltinIntegerLiteral {// @_transparent该特性会导致编译器在管道(pipeline)中更早地将函数内联。@_transparent public init(integerLiteral value: Self) {self = value}
}
上面代码是ExpressibleByIntegerLiteral实现部分。
第二段:加性算术
//===----------------------------------------------------------------------===//
//===--- AdditiveArithmetic -----------------------------------------------===//
//===----------------------------------------------------------------------===///// A type with values that support addition and subtraction.
/// 让一个类型的值支持加减法
///
/// The `AdditiveArithmetic` protocol provides a suitable basis for additive
/// arithmetic on scalar values, such as integers and floating-point numbers,
/// or vectors. You can write generic methods that operate on any numeric type
/// in the standard library by using the `AdditiveArithmetic` protocol as a
/// generic constraint.
/// “加法算术”协议为标量值(如整数、浮点数或向量)的加法算术提供了一个合适的基础。通过使
/// 用“additivearith”协议作为泛型约束,可以编写对标准库中的任何数字类型进行操作的泛型方法。
///
/// The following code declares a method that calculates the total of any
/// sequence with `AdditiveArithmetic` elements.
///
/// extension Sequence where Element: AdditiveArithmetic {/// func sum() -> Element {/// return reduce(.zero, +)
/// }
/// }
///
/// The `sum()` method is now available on any sequence with values that
/// conform to `AdditiveArithmetic`, whether it is an array of `Double` or a
/// range of `Int`.
///
/// let arraySum = [1.1, 2.2, 3.3, 4.4, 5.5].sum()
/// // arraySum == 16.5
///
/// let rangeSum = (1..<10).sum()
/// // rangeSum == 45
///
/// Conforming to the AdditiveArithmetic Protocol
/// =============================================
///
/// To add `AdditiveArithmetic` protocol conformance to your own custom type,
/// implement the required operators, and provide a static `zero` property
/// using a type that can represent the magnitude of any value of your custom
/// type.
public protocol AdditiveArithmetic : Equatable {/// The zero value.////// Zero is the identity element for addition. For any value,/// `x + .zero == x` and `.zero + x == x`.static var zero: Self { get }/// Adds two values and produces their sum.////// The addition operator (`+`) calculates the sum of its two arguments. For/// example:////// 1 + 2 // 3/// -10 + 15 // 5/// -15 + -5 // -20/// 21.5 + 3.25 // 24.75////// You cannot use `+` with arguments of different types. To add values of/// different types, convert one of the values to the other value's type.////// let x: Int8 = 21/// let y: Int = 1000000/// Int(x) + y // 1000021////// - Parameters:/// - lhs: The first value to add./// - rhs: The second value to add.static func +(lhs: Self, rhs: Self) -> Self/// Adds two values and stores the result in the left-hand-side variable.////// - Parameters:/// - lhs: The first value to add./// - rhs: The second value to add.static func +=(lhs: inout Self, rhs: Self)/// Subtracts one value from another and produces their difference.////// The subtraction operator (`-`) calculates the difference of its two/// arguments. For example:////// 8 - 3 // 5/// -10 - 5 // -15/// 100 - -5 // 105/// 10.5 - 100.0 // -89.5////// You cannot use `-` with arguments of different types. To subtract values/// of different types, convert one of the values to the other value's type.////// let x: UInt8 = 21/// let y: UInt = 1000000/// y - UInt(x) // 999979////// - Parameters:/// - lhs: A numeric value./// - rhs: The value to subtract from `lhs`.static func -(lhs: Self, rhs: Self) -> Self/// Subtracts the second value from the first and stores the difference in the/// left-hand-side variable.////// - Parameters:/// - lhs: A numeric value./// - rhs: The value to subtract from `lhs`.static func -=(lhs: inout Self, rhs: Self)
}public extension AdditiveArithmetic where Self : ExpressibleByIntegerLiteral {/// The zero value.////// Zero is the identity element for addition. For any value,/// `x + .zero == x` and `.zero + x == x`.static var zero: Self {return 0}
}
上面的代码主要介绍了AdditiveArithmetic协议:
AdditiveArithmetic协议里的+,+=,-,-=四个方法,还有一个zero属性,下面是zero的默认实现。
协议用法如注释例子(重复一遍):
extension Sequence where Element: AdditiveArithmetic {func sum() -> Element {return reduce(.zero, +)}}let arraySum = [1.1, 2.2, 3.3, 4.4, 5.5].sum()// arraySum == 16.5let rangeSum = (1..<10).sum()// rangeSum == 45
第三段:数字协议
//===----------------------------------------------------------------------===//
//===--- 数字协议 ----------------------------------------------------------===//
//===----------------------------------------------------------------------===//
/// A type with values that support multiplication.
/// 遵守该协议的类型值会支持乘法性质运算
///
/// The `Numeric` protocol provides a suitable basis for arithmetic on
/// scalar values, such as integers and floating-point numbers. You can write
/// generic methods that operate on any numeric type in the standard library
/// by using the `Numeric` protocol as a generic constraint.
///
/// `Numeric`这个协议为类似整型,浮点型这种标量提供计算的基础,
/// 你可以写操作标准库中任何数字类型的泛型方法,使用“Numeric”协议作为通用约束。
///
/// The following example extends `Sequence` with a method that returns an
/// array with the sequence's values multiplied by two.
///
/// 下面的例子是扩展了`Sequence` ,添加了一个方法使序列的每一个值都乘以2
///
/// extension Sequence where Element: Numeric {/// func doublingAll() -> [Element] {/// return map { $0 * 2 }
/// }
/// }
///
/// With this extension, any sequence with elements that conform to `Numeric`
/// has the `doublingAll()` method. For example, you can double the elements of
/// an array of doubles or a range of integers:
///
/// let observations = [1.5, 2.0, 3.25, 4.875, 5.5]
/// let doubledObservations = observations.doublingAll()
/// // doubledObservations == [3.0, 4.0, 6.5, 9.75, 11.0]
///
/// let integers = 0..<8
/// let doubledIntegers = integers.doublingAll()
/// // doubledIntegers == [0, 2, 4, 6, 8, 10, 12, 14]
///
/// Conforming to the Numeric Protocol
/// ==================================
///
/// To add `Numeric` protocol conformance to your own custom type, implement
/// the required initializer and operators, and provide a `magnitude` property
/// using a type that can represent the magnitude of any value of your custom
/// type.
/// 自定义类型想去遵守该协议,需要实现初始化方法和操作符, 和提供一个`magnitude`属性。
///
public protocol Numeric : AdditiveArithmetic, ExpressibleByIntegerLiteral {/// Creates a new instance from the given integer, if it can be represented/// exactly./// 可以从给定的整型初始化,并成功转换。////// If the value passed as `source` is not representable exactly, the result/// is `nil`. In the following example, the constant `x` is successfully/// created from a value of `100`, while the attempt to initialize the/// constant `y` from `1_000` fails because the `Int8` type can represent/// `127` at maximum:////// 如果给定的数据不能准确的转换成功,那么结果返回nil./// 下面的例子,100转换成常量x被成功创建.当试图去从1_000创建y的时候失败了,因为`Int8` 类型只能在 127之内转换。/// let x = Int8(exactly: 100)/// // x == Optional(100)/// let y = Int8(exactly: 1_000)/// // y == nil////// - Parameter source: A value to convert to this type.init?<T : BinaryInteger>(exactly source: T)
/// A type that can represent the absolute value of any possible value of the/// conforming type./// 一个可以等同于准守协议类型值绝对值的类型。associatedtype Magnitude : Comparable, Numeric
/// The magnitude of this value.////// For any numeric value `x`, `x.magnitude` is the absolute value of `x`./// You can use the `magnitude` property in operations that are simpler to/// implement in terms of unsigned values, such as printing the value of an/// integer, which is just printing a '-' character in front of an absolute/// value./// numeric类型的值`x`,`x.magnitude` 是 `x`的绝对值。/// 你可以使用这个属性很容易的去使用无符号值,例如打印一个整数的值,它只是在绝对值前面打印一个“-”字符。/// let x = -200/// // x.magnitude == 200////// The global `abs(_:)` function provides more familiar syntax when you need/// to find an absolute value. In addition, because `abs(_:)` always returns/// a value of the same type, even in a generic context, using the function/// instead of the `magnitude` property is encouraged./// 当您需要查找绝对值时,全局' abs(_:) '函数提供了更熟悉的语法。此外,因为' abs(_:) '总是返回 /// 相同类型的值,即使在通用上下文中也是如此,因此建议使用函数而不是'magnitude'属性。var magnitude: Magnitude { get }
/// Multiplies two values and produces their product.////// The multiplication operator (`*`) calculates the product of its two/// arguments. For example:////// 2 * 3 // 6/// 100 * 21 // 2100/// -10 * 15 // -150/// 3.5 * 2.25 // 7.875////// You cannot use `*` with arguments of different types. To multiply values/// of different types, convert one of the values to the other value's type.////// let x: Int8 = 21/// let y: Int = 1000000/// Int(x) * y // 21000000////// - Parameters:/// - lhs: The first value to multiply./// - rhs: The second value to multiply.static func *(lhs: Self, rhs: Self) -> Self
/// Multiplies two values and stores the result in the left-hand-side/// variable.////// - Parameters:/// - lhs: The first value to multiply./// - rhs: The second value to multiply./// lhs 要使用inout,为了避免值拷贝,应在原来内存的值里修改。static func *=(lhs: inout Self, rhs: Self)
}
第四段:有符号数字协议
/// A type that can represent both positive and negative values.
/// 一个可以同时表示正值和负值得类型
///
/// The `SignedNumeric` protocol extends the operations defined by the
/// `Numeric` protocol to include a value's additive inverse.
///
/// `SignedNumeric`协议扩展了`Numeric`的操作,包括了加性逆元素(-x 是 x 的加性逆元素)。
/// Conforming to the SignedNumeric Protocol
/// ========================================
///
/// Because the `SignedNumeric` protocol provides default implementations of
/// both of its required methods, you don't need to do anything beyond
/// declaring conformance to the protocol and ensuring that the values of your
/// type support negation. To customize your type's implementation, provide
/// your own mutating `negate()` method.
///
///因为' SignedNumeric '协议提供了它所需要的两个方法的默认实现,所以除了声明协议的一致性和确保类型 的值支持否定之外,您不需要做任何事情。要自定义类型的实现,请提供您自己的“negate()”方法。
///
/// When the additive inverse of a value is unrepresentable in a conforming
/// type, the operation should either trap or return an exceptional value. For
/// example, using the negation operator (prefix `-`) with `Int.min` results in
/// a runtime error.
///
/// 当准守这个协议的值不可以被表示出来的时候,应该被捕捉或者返回异常值。
/// 举个例子,在`Int.min`使用用负号(前缀-)运行时会报错误。(因为内存溢出)
/// let x = Int.min
/// let y = -x
/// // Overflow error
public protocol SignedNumeric : Numeric {/// Returns the additive inverse of the specified value.////// The negation operator (prefix `-`) returns the additive inverse of its/// argument.////// let x = 21/// let y = -x/// // y == -21////// The resulting value must be representable in the same type as the/// argument. In particular, negating a signed, fixed-width integer type's/// minimum results in a value that cannot be represented.////// let z = -Int8.min/// // Overflow error////// - Returns: The additive inverse of this value.static prefix func - (_ operand: Self) -> Self
/// Replaces this value with its additive inverse.////// The following example uses the `negate()` method to negate the value of/// an integer `x`:////// var x = 21/// x.negate()/// // x == -21////// The resulting value must be representable within the value's type. In/// particular, negating a signed, fixed-width integer type's minimum/// results in a value that cannot be represented.////// var y = Int8.min/// y.negate()/// // Overflow errormutating func negate()
}
extension SignedNumeric {/// Returns the additive inverse of the specified value.////// The negation operator (prefix `-`) returns the additive inverse of its/// argument.////// let x = 21/// let y = -x/// // y == -21////// The resulting value must be representable in the same type as the/// argument. In particular, negating a signed, fixed-width integer type's/// minimum results in a value that cannot be represented.////// let z = -Int8.min/// // Overflow error////// - Returns: The additive inverse of the argument.@_transparent
public static prefix func - (_ operand: Self) -> Self {var result = operandresult.negate()
return result}
/// Replaces this value with its additive inverse.////// The following example uses the `negate()` method to negate the value of/// an integer `x`:////// var x = 21/// x.negate()/// // x == -21////// The resulting value must be representable within the value's type. In/// particular, negating a signed, fixed-width integer type's minimum/// results in a value that cannot be represented.////// var y = Int8.min/// y.negate()/// // Overflow error@_transparent
public mutating func negate() {self = 0 - self}
}
/// Returns the absolute value of the given number.
///
/// The absolute value of `x` must be representable in the same type. In
/// particular, the absolute value of a signed, fixed-width integer type's
/// minimum cannot be represented.
///
/// let x = Int8.min
/// // x == -128
/// let y = abs(x)
/// // Overflow error
///
/// - Parameter x: A signed number.
/// - Returns: The absolute value of `x`.
@inlinable
public func abs<T : SignedNumeric & Comparable>(_ x: T) -> T {if T.self == T.Magnitude.self {return unsafeBitCast(x.magnitude, to: T.self)}
return x < (0 as T) ? -x : x
}
extension AdditiveArithmetic {/// Returns the given number unchanged.////// You can use the unary plus operator (`+`) to provide symmetry in your/// code for positive numbers when also using the unary minus operator.////// let x = -21/// let y = +21/// // x == -21/// // y == 21////// - Returns: The given argument without any changes.@_transparent
public static prefix func + (x: Self) -> Self {return x}
}
这样写下去有点头大,策略不对。
决定改为总结性重点方法使用分析。
Swift 读标准库源码笔记 -- Integers(基本数据类型篇)相关推荐
- 彻底弄懂Python标准库源码(一)—— os模块
目录 第1~22行 模块整体注释.nt与posix 第24~46行 模块引入._exists方法._get_exports_list方法 第48~97行 根据系统不同导入不同的方法和属性 第100~1 ...
- 整理网上资料---C标准库值篇二 :标准库源码下载地址、标准库手册下载地址
C标准库源码及手册.zip,包括: http://download.csdn.net/detail/yangzhao0001/9057823 C标准库函数集(头文件索引)------手册-AH.pdf ...
- Swift标准库源码阅读笔记 - Array和ContiguousArray
关于 ContiguousArray ,这边有喵神的文章介绍的很详细了,可以先看看这个文章. Array 接着喵神的思路,看一下 Array 以下是从源码中截取的代码片段. public struct ...
- Kotlin StandardKt 标准库源码走一波
距离上篇Kotlin文章,应该有差不多半年时间.没别的原因,因为,懒,而且,想产出一篇稍微质量好的博客好难. 最近在研究Python,所以最近也可能会更新一些Python的学习笔记. Standard ...
- 彻底弄懂Python标准库源码(三)—— pprint模块
目录 模块整体注释 依赖模块导入.对外暴露接口 saferepr函数--返回对象的字符串表示,并为无限递归数据结构提供保护 isreadable函数--返回对象的是否"可读" is ...
- Swift 标准库源码 第三方,Almofire,Kingfisher,SwiftyJson,KakaJson,单元测试 request
?? 两个optional比较会包装成等?的类型,再进行比较 json 反射 request 开发工具
- CPython 标准库源码分析 collections.Counter
Counter 是一个专门计数可哈希对象的 dict 子类,元素会被当做 dict 的 key,计数的数量被当做 value 存储. 这是 Counter 的 doc string,直接明确的指出了元 ...
- rock带你读CornerNet-lite系列源码(二)
文章目录 前言 CorNerNet 结构 CornerNet_saccade结构 attention机制 CornerNet_Squeeze结构 构建Groundtruth 热图 focal loss ...
- 三方库源码学习2-Retrofit
文章目录 一.参考博客 二.Retrofit的介绍 三.什么是动态代理 四. Retrofit.Create()方法 五. ServiceMethod 六. 初看HttpServiceMethod 七 ...
- android 三方_面试官送你一份Android热门三方库源码面试宝典及学习笔记
前言 众所周知,优秀源码的阅读与理解是最能提升自身功力的途径,如果想要成为一名优秀的Android工程师,那么Android中优秀三方库源码的分析和理解则是必备技能.就拿比较热门的图片加载框架Glid ...
最新文章
- java实现混合运算_java图形化界面实现简单混合运算计算器
- mysql where 拼接_分一个mysql拼接where语句的Directive,并请教一个问题
- sqlplus登录方式,列出所有表,列出表结构,sqlplus行和列显示设置,别名,空值问题,连接符,DISTINCT
- EChart 标题 title 样式,x轴、y轴坐标显示,调整图表位置等
- 主题:Centos6.4安装JDK
- 〖Windows〗Linux的Qt程序源码转换至Windows平台运行,编码的解决
- Eclipse 如何修改默认工作空间和切换工作空间(Workspace)
- kettle 资料_Kettle的使用-初级
- arcgis api 3.x for js 入门开发系列六地图分屏对比(附源码下载)
- canvas动画 - 背景线条 - 应用篇
- linux mysql降权_怎样将mysql数据库root降权
- vue动态设置文字布局方式_十大惊人的文字动画特效
- 开源 ERP 软件 Odoo 提速指南
- android 柱状图_安卓控件 仪表盘控件 柱状图控件 曲线控件 xamarin.android 分类器 瓶子控件 报警控件 水箱控件 进度条控件等...
- s7-200plc编程及应用_西门子S7200PLC编程应用15个为什么
- 计算机c盘如何扩容,C盘满想换SSD遇涨价?教你C盘扩容技巧
- Python就业方向都有什么?该如何选择?
- 小窗终曲说策划(有空就看看吧,可能对设计想法有所帮助,不仅仅是游戏方面
- 灰、黄、蓝三种颜色的收集装置模型练习及实现思路
- python语言下,B站(bilibili)热门排行榜视频封面爬取程序V1.0 小白也能看懂,八十岁没牙老太太看完拿舌头都能爬封面!!
热门文章
- cloopen java_GitHub - cloopen/java-sms-sdk: Yuntongxun SMS SDK for Java
- 正则的replace方法详解
- python最小二乘法线性回归_python 分别用梯度下降法和最小二乘法求线性回归 | 学步园...
- ionic ion-refresher刷新完毕
- 飞书深诺在港上市招股书再失效:毛利率较高,遭完美世界提前减持
- vue3 + js-cookie加密解密(普通版本/TS版本)
- 反病毒引擎设计(一):绪论 本文来自:剑盟反病毒技术门户(www.janmeng.com)
- Latex数学公式-矩阵中省略号的表示
- nuc8 黑苹果_NUC Hades Canyon (NUC8) 黑苹果(Hackintosh)安装指南
- Omniverse数字孪生实战