Je joue avec Rust et j’essaie d’accéder au premier argument de la ligne de commande avec ce code:
use std::env; fn main() { let args: Vec = env::args().collect(); let dir = args[1]; }
Et je reçois cette erreur:
error[E0507]: cannot move out of indexed content --> src/main.rs:5:15 | 5 | let dir = args[1]; | --- ^^^^^^^ cannot move out of indexed content | | | hint: to prevent move, use `ref dir` or `ref mut dir`
Si je le change pour let ref dir
, ça comstack, mais je ne comprends pas ce qui se passe. Quelqu’un pourrait-il expliquer ce que “contenu indexé” signifie?
Lorsque vous utilisez un opérateur d’index ( []
), vous obtenez l’object réel à l’emplacement de l’index. Vous ne recevez pas de référence, de pointeur ou de copie. Puisque vous essayez de lier cet object avec une liaison let
, Rust essaie immédiatement de se déplacer (ou de copier, si le trait Copy
est implémenté).
Dans votre exemple, env::args()
est un iterator de Ssortingng
s qui est ensuite collecté dans un Vec
. Ceci est un vecteur appartenant aux chaînes possédées, et les chaînes possédées ne sont pas automatiquement copiables.
Vous pouvez utiliser une liaison let ref
, mais l’alternative plus idiomatique consiste à prendre une référence à l’object indexé (notez le symbole &
):
use std::env; fn main() { let args: Vec<_> = env::args().collect(); let ref dir = &args[1]; // ^ }
Déplacer implicitement un Vec
n’est pas autorisé car il le laisserait dans un état invalide – un élément est déplacé, les autres ne le sont pas. Si vous avez un Vec
mutable, vous pouvez utiliser une méthode comme Vec::remove
pour obtenir une seule valeur:
use std::env; fn main() { let mut args: Vec<_> = env::args().collect(); let dir = args.remove(1); }
Pour votre problème particulier, vous pouvez également utiliser Iterator::nth
:
use std::env; fn main() { let dir = env::args().nth(1).expect("Missing argument"); }