2017-02-05 2 views
2

Рассмотрим этот код ...Почему flatMap, используемый через расширение, возвращает разные результаты, чем при вызове напрямую?

import Foundation 

let source = ["A", "B", nil, "D"] 
print(type(of:source)) 

let result1 = source.flatMap{ $0 } 
print(type(of:result1)) 
print(result1) 

extension Array 
{ 
    func sameThing() -> Array 
    { 
     return self.flatMap{ $0 } 
    } 
} 

let result2 = source.sameThing() 
print(type(of:result2)) 
print(result2) 

result1 является Array<String> в то время как result2 является Array<Optional<String>>. Но почему?

Я попытался использовать последовательность вместо массива, но и не повезло.

+1

Это все еще не объясняет 'nil' в' result2' –

+0

. Чтобы облегчить эту работу для дополнительных массивов, см. Http://stackoverflow.com/q/38434125/2976878 – Hamish

ответ

1

Ваш возвращаемый тип сохраняет обобщенный тип

func sameThing(separator:String = " ") -> Array 

Поэтому на дополнительных элементов подписи этой операции эквивалентно [T?] -> [T?]

Sequence.flatMap имеет два перегруженных с специально умыслом подписей

func flatMap<SegmentOfResult : Sequence>(
    _ transform: (${GElement}) throws -> SegmentOfResult 
) rethrows -> [SegmentOfResult.${GElement}] 

func flatMap<ElementOfResult>(
    _ transform: (${GElement}) throws -> ElementOfResult? 
) rethrows -> [ElementOfResult] { 

во втором один выигрывает. Но так как вы попросили массив опций, ElementOfResult становится Optional<String>, а transform становится Optional<String> -> Optional<Optional<String>>.

Таким образом, когда закрывающий { $0 } возвращается nil, он получает поднимается до Optional(nil), т.е. имеющей .some(nil) значения, а не .none. Затем он передаст нулевой охранник и появится в результате.

+0

Интересно! Я продолжаю забывать, как Swift использует возвращаемые типы как часть подписи, которой нет на других языках, таких как C#. Тем не менее, как мне изменить мою функцию, чтобы точно соответствовать возврату flatMap? Я пытаюсь инкапсулировать некоторую функциональность, частью которой является flatMap, поэтому я могу ее повторно использовать. Кинда тут же запнулся. – MarqueIV

+1

@MarqueIV см. Здесь http://stackoverflow.com/a/38548106 – paiv