Swift 可失败的 rawValue 初始值设定项复杂度
Swift failable rawValue initializer Complexity
我想知道枚举可失败初始化程序的时间复杂度
示例
enum Operator: Character {
case parenthesis = "("
case brace = "{"
case bracket = "["
}
// Time Complexity?
if let op = Operator(rawValue: "[") {
...
}
请注意,这是一个非常重要的实现细节,因为文档没有说明。
使用我的 Swift 编译器版本 5.3.2,我将您的枚举(使用 -Ounchecked
)编译为二进制文件,并使用 Hopper Disassembler 检查它以查看为原始值初始化程序生成的代码.初始化程序实际上什么都不做,只是直接跳转到另一个过程。该过程看起来像这样:
// pseudo code generated by Hopper
int _$s4main3FooO8rawValueACSgSJ_tcfCTf4nd_n(int arg0, int arg1, int arg2, int arg3, int arg4) {
r12 = arg1;
r15 = arg0;
if ((arg0 == 0x28) && (r12 == 0xe100000000000000)) {
swift_bridgeObjectRelease(r12);
rbx = 0x0;
}
else {
if ((Swift._stringCompareWithSmolCheck(0x28, 0xe100000000000000, r15, r12, 0x0) & 0x1) != 0x0) {
swift_bridgeObjectRelease(r12);
rbx = 0x0;
}
else {
if ((r15 == 0x7b) && (r12 == 0xe100000000000000)) {
swift_bridgeObjectRelease(r12);
rbx = 0x1;
}
else {
if ((Swift._stringCompareWithSmolCheck(0x7b, 0xe100000000000000, r15, r12, 0x0) & 0x1) != 0x0) {
swift_bridgeObjectRelease(r12);
rbx = 0x1;
}
else {
if (r15 == 0x5b) {
if (r12 == 0xe100000000000000) {
swift_bridgeObjectRelease(0xe100000000000000);
rbx = 0x2;
}
else {
rbx = Swift._stringCompareWithSmolCheck(0x5b, 0xe100000000000000, r15, r12, 0x0);
swift_bridgeObjectRelease(r12);
rbx = rbx & 0x1 ^ 0x3;
}
}
else {
rbx = Swift._stringCompareWithSmolCheck(0x5b, 0xe100000000000000, r15, r12, 0x0);
swift_bridgeObjectRelease(r12);
rbx = rbx & 0x1 ^ 0x3;
}
}
}
}
}
rax = rbx;
return rax;
}
注意值 0x28、0x7b 和 0x5b。它们分别匹配 (
、{
和 [
的代码点。看起来该算法基本上是“检查参数是否按顺序匹配每个案例的原始值”。
我尝试添加更多的情况,if 嵌套更多,我可以看到我添加的字符的代码点。
所以看起来确实,更多的情况会导致 init(rawValue:)
在最坏的情况下花费更多的时间(请注意,这并不是算法的时间复杂度)。
但是,如果您使用 Int
作为原始值类型,则它不会执行所有这些复杂的字符串比较,因为它可以使用整数来表示您的枚举。如果您还让编译器推断原始值,则初始化程序将只进行范围检查。在这种情况下,添加更多案例(推断其原始值)不会增加初始化程序所花费的时间。
虽然在一天结束时,我认为执行时间的这一点增加根本不重要。您不会将 数百万 个案例添加到您的枚举中。
我想知道枚举可失败初始化程序的时间复杂度
示例
enum Operator: Character {
case parenthesis = "("
case brace = "{"
case bracket = "["
}
// Time Complexity?
if let op = Operator(rawValue: "[") {
...
}
请注意,这是一个非常重要的实现细节,因为文档没有说明。
使用我的 Swift 编译器版本 5.3.2,我将您的枚举(使用 -Ounchecked
)编译为二进制文件,并使用 Hopper Disassembler 检查它以查看为原始值初始化程序生成的代码.初始化程序实际上什么都不做,只是直接跳转到另一个过程。该过程看起来像这样:
// pseudo code generated by Hopper
int _$s4main3FooO8rawValueACSgSJ_tcfCTf4nd_n(int arg0, int arg1, int arg2, int arg3, int arg4) {
r12 = arg1;
r15 = arg0;
if ((arg0 == 0x28) && (r12 == 0xe100000000000000)) {
swift_bridgeObjectRelease(r12);
rbx = 0x0;
}
else {
if ((Swift._stringCompareWithSmolCheck(0x28, 0xe100000000000000, r15, r12, 0x0) & 0x1) != 0x0) {
swift_bridgeObjectRelease(r12);
rbx = 0x0;
}
else {
if ((r15 == 0x7b) && (r12 == 0xe100000000000000)) {
swift_bridgeObjectRelease(r12);
rbx = 0x1;
}
else {
if ((Swift._stringCompareWithSmolCheck(0x7b, 0xe100000000000000, r15, r12, 0x0) & 0x1) != 0x0) {
swift_bridgeObjectRelease(r12);
rbx = 0x1;
}
else {
if (r15 == 0x5b) {
if (r12 == 0xe100000000000000) {
swift_bridgeObjectRelease(0xe100000000000000);
rbx = 0x2;
}
else {
rbx = Swift._stringCompareWithSmolCheck(0x5b, 0xe100000000000000, r15, r12, 0x0);
swift_bridgeObjectRelease(r12);
rbx = rbx & 0x1 ^ 0x3;
}
}
else {
rbx = Swift._stringCompareWithSmolCheck(0x5b, 0xe100000000000000, r15, r12, 0x0);
swift_bridgeObjectRelease(r12);
rbx = rbx & 0x1 ^ 0x3;
}
}
}
}
}
rax = rbx;
return rax;
}
注意值 0x28、0x7b 和 0x5b。它们分别匹配 (
、{
和 [
的代码点。看起来该算法基本上是“检查参数是否按顺序匹配每个案例的原始值”。
我尝试添加更多的情况,if 嵌套更多,我可以看到我添加的字符的代码点。
所以看起来确实,更多的情况会导致 init(rawValue:)
在最坏的情况下花费更多的时间(请注意,这并不是算法的时间复杂度)。
但是,如果您使用 Int
作为原始值类型,则它不会执行所有这些复杂的字符串比较,因为它可以使用整数来表示您的枚举。如果您还让编译器推断原始值,则初始化程序将只进行范围检查。在这种情况下,添加更多案例(推断其原始值)不会增加初始化程序所花费的时间。
虽然在一天结束时,我认为执行时间的这一点增加根本不重要。您不会将 数百万 个案例添加到您的枚举中。