mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-24 20:00:37 +00:00
3.7 KiB
3.7 KiB
Swift 模式匹配
模式匹配的底层实现
为了去除其他语句对汇编研究造成的干扰,所以 case 和 default 里面都很简单,聚焦于研究 case 的模式匹配实现。测试代码如下:
var age = 28
switch age {
case 0...30:
break
default:
break
}
在 case 0...30: 处加断点可以看到汇编,然后看到可疑方法 Swift.RangeExpression.~= infix(τ_0_0, τ_0_0.Bound) -> Swift.Bool
LLDB 输入 si 进去窥探下
看样子,函数还没到底,看到地址 0x00007ff81a86f530 很大很大,猜测应该是一个系统动态库方法地址,继续跟进去研究 si
可以看到内部还有函数调用
继续跟进 si
看上去是在做继续 clasedRange 区间符合的判断,继续跟进 si,里面确实是在判断是否命中区间的判断。不一一研究了,这次目的是判断 switch...case pattern 的实现。
结论:switch case pattern 模式匹配,系统底层实现是依赖
模式匹配的应用
自定义模式匹配。根据上面通过汇编进行分析,我们知道
-
static func ~=(pattern: case 后面的值, value: switch 后面的值)pattern 代表的是 case 后面的值,value 代表 switch 后面的值。 -
当 case 有不同类型的时候,如果编译报错,则需要重写
static func ~=(pattern: ,value: )方法,调整 pattern 的数据类型,数据类型应该和 case 后的数据类型一致(可以是函数等)
struct Student {
var score = 0
var name = ""
/// Student 和 Int 模式匹配的方法
/// - Parameters:
/// - pattern: case 后面的内容
/// - value: switch 后面的内容
/// - Returns: 是否命中
static func ~= (pattern: Int, value: Student) -> Bool {
value.score >= pattern
}
static func ~= (pattern: Range<Int>, value: Student) -> Bool {
pattern.contains(value.score)
}
static func ~= (pattern: ClosedRange<Int>, value: Student) -> Bool {
pattern.contains(value.score)
}
static func ~= (pattern: String, value: Student) -> Bool {
Int(pattern) == value.score
}
}
var student: Student = Student(score: 55, name: "杭城小刘")
switch student {
case 100:
print(">=100")
case 90:
print(">=90")
case 80..<90:
print("[80, 90)")
case 60...79:
print("[60, 79]")
case "55":
print("斯国一")
default:
print("just so so")
}
// console
斯国一
修改 var student: Student = Student(score: 78, name: "杭城小刘") 则输出 [60, 79]
extension String {
static func ~=(pattern: (String) -> Bool ,value: String) -> Bool {
pattern(value)
}
}
func hasPrefix(_ prefix: String) -> (String) -> Bool {
{$0.hasPrefix(prefix)}
}
func hasSuffix(_ prefix: String) -> (String) -> Bool {
{$0.hasSuffix(prefix)}
}
var name = "城小刘"
switch name {
case hasPrefix("杭"):
print("有杭哦")
case hasSuffix("刘"):
print("有刘哦")
default:
print("just a name")
}
// console
有刘哦
