Вызов метода при вызове clap::App перемещает право собственности более одного раза

Даже прочитав главы о владении ссылками и заимствовании, я не могу понять некоторые вещи в следующем коде, что фактически мешает мне вызывать более одного метода из clap::App!

extern crate clap;

use clap::App;

fn main() {
    let mut app =
        App::new("name me").args_from_usage("<input_file>          'Sets the input file to use'");
    let matches = app.get_matches();
    app.print_help();
    println!(
        "Using input file: {}",
        matches.value_of("input_file").unwrap()
    );
}

Компиляция этого кода приводит к:

error[E0382]: use of moved value: `app`
 --> src/main.rs:9:5
  |
8 |     let matches = app.get_matches();
  |                   --- value moved here
9 |     app.print_help();
  |     ^^^ value used here after move
  |
  = note: move occurs because `app` has type `clap::App<'_, '_>`, which does not implement the `Copy` trait
  1. Если я правильно понимаю, app.get_matches() просит одолжить право собственности, таким образом, app должно быть mut. Куда уходит право собственности после возврата функции?
  2. Я думал, что app по-прежнему будет владеть объектом, но у компилятора другое мнение.

Как я могу получить совпадения и эффективно вызвать другой метод, например print_help на app?


person Jiehong    schedule 03.12.2016    source источник


Ответы (1)


Прочтите сигнатуру для App::get_matches:

fn get_matches(self) -> ArgMatches<'a>

Это принимает self по значению, также говоря, что оно использует значение; после этого вы не можете вызывать для него какие-либо методы. С этим ничего не поделаешь; по-видимому, у автора есть веские основания для этого.

Теперь просмотрите App::print_help:

fn print_help(&mut self) -> ClapResult<()>

Он принимает ссылку (которая может быть изменчивой). Вам не нужно передавать право собственности для вызова этого метода.


Если я правильно понимаю, app.get_matches() просит одолжить право собственности, поэтому приложение должно быть mut. Куда уходит право собственности после возврата функции?

Вы не правильно поняли, в многомерности.

  1. get_matches потребляет значение, ничего не заимствуя.
  2. Значение не должно быть изменяемым, чтобы его можно было заимствовать.
  3. Когда вы что-то одалживаете, право собственности никуда не «уходит». Первоначальный владелец продолжает владеть им. Вот почему это называется заимствование.

Как я могу получить совпадения и эффективно вызвать другой метод, например print_help в приложении?

Вы не знаете. Очевидный обходной путь — клонировать исходный объект, создавая второе значение. Затем вы можете использовать одно значение и по-прежнему вызывать методы для второго значения.


По сути, это звучит так, как будто вы пытаетесь сделать что-то, что библиотека отговаривает вас делать. Возможно, вам следует пересмотреть свои цели и/или пересмотреть предполагаемое использование библиотеки. Например, get_matches будет автоматически отображать текст справки, когда пользователь запрашивает его, так почему ваш код должен пытаться это сделать?

Из системы отслеживания проблем с Clap:

У вас есть несколько вариантов. Вы можете либо использовать AppSettings::ArgRequiredElseHelp, либо предотвратить перемещение, используя App::get_matches_from_safe_borrow .

person Shepmaster    schedule 03.12.2016
comment
Спасибо, что пролили свет на мое большое недоразумение! Просто какое-то странное ощущение на какой-то момент Rust, поначалу… - person Jiehong; 03.12.2016
comment
@Jiehong да, определенно есть кривая обучения, но почти у всего есть веская причина для существования. В этом случае я хотел бы точно объяснить, почему эта библиотека спроектирована именно так. Лучшее, что я могу предоставить, это то, что clap::App документация называет себя компоновщиком. Как правило, после того, как вы что-то построили, конструктор расходуется в процессе. - person Shepmaster; 03.12.2016
comment
@Shepmaster хорошо объяснил. Могу я добавить следующее: многие инструменты командной строки показывают полную справку по «голому» вызову команды, включая java и cloc. Поэтому я считаю разумным, чтобы @Jiehong хотел, чтобы хлопок предоставил полное справочное сообщение. Я пока не нашел простого способа обеспечить такое поведение с помощью хлопка. - person David J.; 25.12.2016
comment
@DavidJames, конечно, хотя это звучит как случай запроса функции для самого хлопка. Моя точка зрения в основном состоит в том, что clap решил быть самоуверенным в дизайне, надеюсь, по уважительной причине. Плыть по течению облегчит использование библиотеки. ^_^ - person Shepmaster; 25.12.2016
comment
Re: по-видимому, у автора есть веские причины для этого... Я спросил непосредственно в системе отслеживания проблем Clap: github.com/kbknapp/clap-rs/issues/785 - person David J.; 25.12.2016