2017-02-13 1 views
1

documentation Swift de lit flatMap:flatMap ne filtre pas nul lorsque ElementOfResult est déduit être en option

Renvoie un tableau contenant les résultats non nul d'appeler la transformation donnée à chaque élément de cette séquence.

Dans les exemples suivants lorsque le type de retour ElementOfResult est laissé au compilateur de déduire flatMap œuvres comme indiqué, mais sur la ligne 5 lorsque ElementOfResult est spécifié, ainsi inférées à un type Optional<String> il semble que flatMap arrête le filtrage nil 's.

Pourquoi cela fait-il cela?

~ swift 
Welcome to Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1). Type :help for assistance. 
    1> let words = ["1989", nil, "Fearless", nil, "Red"] 
words: [String?] = 5 values { 
    [0] = "1989" 
    [1] = nil 
    [2] = "Fearless" 
    [3] = nil 
    [4] = "Red" 
} 
    2> words.flatMap { $0 } 
$R0: [String] = 3 values { 
    [0] = "1989" 
    [1] = "Fearless" 
    [2] = "Red" 
} 
    3> let resultTypeInferred = words.flatMap { $0 } 
resultTypeInferred: [String] = 3 values { 
    [0] = "1989" 
    [1] = "Fearless" 
    [2] = "Red" 
} 
    4> let resultTypeSpecified: [String?] = words.flatMap { $0 } 
resultTypeSpecified: [String?] = 5 values { 
    [0] = "1989" 
    [1] = nil 
    [2] = "Fearless" 
    [3] = nil 
    [4] = "Red" 
} 
+0

Rappelez-vous que 'flatMap (_ :)' 'rendement [ElementOfResult]', et le retour de fermeture est de type '' ElementOfResult?. Par conséquent, si vous annotez le retour sous la forme '[String?]', Vous dites que la fermeture renvoie 'String ??'. Ainsi, les éléments optionnels sont promus en optionnels doubles, et sont donc tous '.some', donc ils sont 'non-'nil'. Essayez d'annoter le retour de 'flatMap (_ :)' comme '[String]' à la place, comme je l'ai montré dans [ma réponse à votre question précédente] (http://stackoverflow.com/a/42213785/2976878). – Hamish

+0

Voir aussi cet autre Q & A: [Swift flatMap sur le tableau avec les éléments sont facultatifs a un comportement différent] (http://stackoverflow.com/q/37505787/2976878) (dupe possible?) – Hamish

Répondre

2

est ici la définition de flatMap()

public func flatMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]

Lorsque vous définissez le type de resultTypeSpecified-[String?], vous dites au compilateur que ElementOfResult est Optional<String>.

Votre fermeture de transformateur a un type de (String?) -> Optional<Optional<String>>.

flatMap enlèvera 1 "couche" d'options mais pas 2 couches.

Espérons que cet exemple rend les choses plus claires:

let input: [String??] = [ 
    Optional.some(Optional.some("1989")), 
    Optional.some(Optional.none), 
    Optional.some(Optional.some("Fearless")), 
    Optional.some(Optional.none), 
    Optional.some(Optional.some("Red")) 
] 

let output = input.flatMap({ $0 })