2016-11-28 1 views
-2

Je dois compter la longueur d'un vecteur de (bool, i32) où si le bool est vrai, je compte le nombre d'incréments. J'utilise fois pour ce faire:Utilisation si à l'intérieur du pli

fn main() { 
    let domain = [(true, 1), (false, 2), (true, 3)]; 
    let dom_count = domain.iter() 
     .fold(0, |count, &(exists, _)| if exists {count + 1}); 
    println!("dom_count: {}", dom_count); 
} 

Le compilateur est plaint en disant:

.fold(0, |count, &(exists, _)| if exists {count + 1}) 
           ^^^^^^^^^^^^^^^^^^^^^ expected(), found integral variable 

Alors j'ai ajouté un ; et a obtenu ceci:

.fold(0, |count, &(exists, _)| if exists {count + 1;}) 
           ^^^^^^^^^^^^^^^^^^^^^^ expected integral variable, found() 

Comment utilisez-vous correctement une if déclaration à l'intérieur de fold?

Répondre

3

Quelle est la valeur que vous tentez d'utiliser lorsque la condition if est false?

C'est ce que le compilateur vous dit en premier. Parce qu'il n'y a pas de clause else, le type de retour de la clause manquante doit être (). Et puisque les branches vrai et faux du if doivent avoir le même type, la vraie branche doit renvoyer (). Cependant, votre véritable branche essaie de renvoyer un nombre.

En ajoutant le ;, vous avez fait en sorte que les deux branches du if retour (), qui a ensuite échoué parce que votre fold est supposé retourner un entier.

Une solution est de renvoyer une valeur dans la clause else:

fn main() { 
    let domain = [(true, 1), (false, 2), (true, 3)]; 

    let dom_count = domain.iter() 
     .fold(0, |count, &(exists, _)| { 
      if exists { 
       count + 1 
      } else { 
       count 
      } 
     }); 

    println!("dom_count: {}", dom_count); 
} 

Ou

fn main() { 
    let domain = [(true, 1), (false, 2), (true, 3)]; 

    let dom_count = domain.iter() 
     .fold(0, |count, &(exists, _)| { 
      count + if exists { 
       1 
      } else { 
       0 
      } 
     }); 

    println!("dom_count: {}", dom_count); 
} 

Il est beaucoup plus idiomatiques utiliser filter:

fn main() { 
    let domain = [(true, 1), (false, 2), (true, 3)]; 

    let dom_count = domain.iter() 
     .filter(|&&(exists, _)| exists) 
     .fold(0, |count, _| count + 1); 

    println!("dom_count: {}", dom_count); 
} 

Et l'acte de compter le nombre d'éléments est déjà géré par Iterator::count:

fn main() { 
    let domain = [(true, 1), (false, 2), (true, 3)]; 

    let dom_count = domain.iter().filter(|&&(exists, _)| exists).count(); 

    println!("dom_count: {}", dom_count); 
} 
+0

Merci. Je n'avais aucune idée que si-déclarations se comportaient comme ça. Aussi je m'excuse du manque de MCVE, je l'ai nettoyé. Sur une note connexe, pourquoi Rust autorise-t-il les lignes simples if à manquer de ';' si elles ne retournent pas de valeur? Par exemple, 'count' est une variable pourquoi compiler:' if true {count = 1} '? Ne devriez-vous pas être obligé d'ajouter un point-virgule: 'if true {count = 1;}'? – HiDefender

+0

@HiDefender * s'ils ne retournent pas une valeur * - ils ** font ** retournent une valeur - la valeur '()' du type '()'. C'est le tuple vide, parfois appelé le "type d'unité". – Shepmaster