Вы можете создать некоторые инструментальные типы данных, которые подключаются к различным вызываемым функциям, и распечатывать подробности о них.Это поможет вам понять порядок вещей:
struct InstrumentedInt: ExpressibleByIntegerLiteral, Equatable {
let value: Int
init(integerLiteral: Int) {
print("Initializing InstrumentedInt from \(integerLiteral)")
self.value = integerLiteral
}
static func == (lhs: InstrumentedInt, rhs: InstrumentedInt) -> Bool {
print("checking \(lhs) == \(rhs)")
return lhs.value == rhs.value
}
}
struct InstrumentedDouble: ExpressibleByFloatLiteral, Equatable {
let value: Double
init(integerLiteral: Int) {
print("Initializing InstrumentedInt from \(integerLiteral)")
self.value = Double(integerLiteral)
}
init(floatLiteral: Double) {
print("Initializing InstrumentedInt from \(floatLiteral)")
self.value = floatLiteral
}
static func == (lhs: InstrumentedDouble, rhs: InstrumentedDouble) -> Bool {
print("checking \(lhs) == \(rhs)")
return lhs.value == rhs.value
}
}
func instrumentedValueProducer(value: Any) -> Any {
print("Producing value \(value)")
return value
}
let instrumentedInt: InstrumentedInt = 10
let instrumentedDouble: InstrumentedDouble = 20.0
switch instrumentedValueProducer(value: instrumentedDouble) {
case 10 as InstrumentedInt: print("10 as InstrumentedInt")
case 20.0 as InstrumentedDouble: print("20 as InstrumnetedDouble")
default: print("default")
}
Инициализация InstrumentedInt от 10
Инициализация InstrumentedInt от 20,0
Создание значения InstrumentedDouble (значение: 20.0)
Инициализация InstrumentedInt из 20.0
проверка InstrumentedDouble (значение: 20.0) == InstrumentedDouble (значение: 20.0)
20 as InstrumentedDouble
Удивительно, но хотя 20
является вторым случаем, компилятор не вызывает инициализатор InstrumentedInt.init(integerLiteral: 10)
для использования для сравнения.Я полагаю, что оптимизация может быть разумной и создать справочную таблицу, которая каким-то образом полностью пропускает генерацию значений.