2017-09-04 1 views
4

J'essaie d'écrire une macro pour connaître le temps d'exécution de diverses fonctions.erreur: la variable 'x' est toujours répétée à cette profondeur

macro_rules! timer { 
    ($($x: expr),+) => { 
     let now = SystemTime::now(); 
     let val = $x; 

     match now.elapsed() { 
      Ok(elapsed) => { 
       // This should include a message at some point alongside the timing 
       println!("{}", elapsed.as_secs()); 
      } 
      Err(e) => { 
       println!("{:?}", e); 
      } 
     } 
     val 
    } 
} 

mais le compilateur jette un error: variable 'x' is still repeating at this depth.

Dans une autre langue à saisie statique que j'ai essayée en (F #), l'utilisation de fermetures était l'approche la plus simple. Est-il impossible d'avoir une macro générique comme celle-ci dans Rust?

+3

Le problème est que la macro accepte une ou plusieurs expressions, mais il utilise seulement * un *. Qu'est-ce que c'est censé faire? Le bloc devrait-il se dilater une fois pour chaque expression d'entrée et renvoyer seulement le dernier? Ou devrait-il les rendre tous? Temporisé ensemble ou indépendamment? Et juste pour ajouter: vous * pouvez * le faire facilement avec une fonction régulière; Y at-il une raison pour laquelle vous n'êtes pas? –

+0

@DK. Ma compréhension de la syntaxe macro est qu'il doit être zéro ou une à plusieurs répétitions (je préférerais juste correspondre et évaluer une expression cependant). En ce qui concerne les raisons pour lesquelles je n'utilise pas de fonction de synchronisation, j'essayais juste d'avoir une idée des macros dans la langue. C'est potentiellement (?) Un mauvais ajustement. – wegry

Répondre

4

Le problème le plus immédiat est que vous demandez à la macro d'analyser une séquence d'une ou de plusieurs expressions, lorsque l'extension est capable d'en traiter une seule. Donc, juste demander pour un. Deuxièmement, vous voulez que l'expansion aboutisse à une expression, mais vous l'avez écrite pour la développer en plusieurs instructions. Pour résoudre ce problème, développez un bloc.

Fixation les donne:

macro_rules! timer { 
    ($x: expr) => { 
     { 
      let now = SystemTime::now(); 
      let val = $x; 

      match now.elapsed() { 
       Ok(elapsed) => { 
        // This should include a message at some point alongside the timing 
        println!("{}", elapsed.as_secs()); 
       } 
       Err(e) => { 
        println!("{:?}", e); 
       } 
      } 
      val 
     } 
    } 
}