#swift #type-conversion #coercion #type-coercion
#swift #преобразование типов #принуждение #тип-принуждение
Вопрос:
У меня есть метод:
func allRegions() -> [MappedRegion] {
return self.items.lazy.compactMap { item in item.valveAny }.flatMap { valve in valve.regions }
}
Я был откровенно удивлен, что это сработало. Я здесь делаю ленивые вещи, но, по-видимому, ленивая последовательность, которая превращается в последовательность MappedRegion, будет такой же.
Затем я плохо рассчитал время и изменил функцию для чтения:
func allRegions() -> [MappedRegion] {
let startTime = Date()
let result = self.items.lazy.compactMap { item in item.valveAny }.flatMap { valve in valve.regions }
self.sumRender = (Date() - startTime)
return result
}
Но это создало ошибку:
Cannot convert return expression of type 'LazySequence<FlattenSequence<LazyMapSequence<LazyMapSequence<LazyFilterSequence<LazyMapSequence<LazySequence<[StatusRowItem]>.Elements, ValveAbstract?>>, ValveAbstract>.Elements, [MappedRegion]>>>' (aka 'LazySequence<FlattenSequence<LazyMapSequence<LazyMapSequence<LazyFilterSequence<LazyMapSequence<Array<StatusRowItem>, Optional<ValveAbstract>>>, ValveAbstract>, Array<MappedRegion>>>>') to return type '[MappedRegion]'
Поначалу это было неожиданностью. Я обнаружил, что если я указал возвращаемый тип result
as [MappedRegion]
, все было хорошо (например let result:[MappedRegion] = ...
).
Что здесь происходит? Я понимаю, что исходная однострочная функция выводит тип результата как [MappedRegion] , поэтому я, вероятно, не получаю особых преимуществ от ленивого использования. Но что меня смущает, так это то, что это принудительное преобразование ленивой последовательности в фиксированный массив автоматически напоминает кастинг в C, и я думал, что Swift не выполняет кастинг?
Комментарии:
1. Возможно, компилятор оптимизирует
lazy
вызов, поскольку он обнаруживает, что он не понадобится.
Ответ №1:
Нет, кастинг не выполняется. Вызываются просто две разные flatMap
функции. LazyMapSequence
имеет две flatMap(_:)
функции (ну, технически четыре, но две устарели).
В вашем первом блоке кода выводится эта функция (потому что эта версия flatMap
имеет тип возвращаемого значения, который соответствует allRegions
типу возвращаемого значения вашей функции):
func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence
И в вашем втором блоке кода эта функция выводится (потому что в вашей локальной переменной нет аннотации типа, которая заставляет ее выбирать указанную выше версию flatMap
):
func flatMap<SegmentOfResult>(_ transform: @escaping (Element) -> SegmentOfResult) -> LazySequence<FlattenSequence<LazyMapSequence<LazyMapSequence<Base, Element>, SegmentOfResult>>> where SegmentOfResult : Sequence