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

Я изучаю Rust, читая книгу, занимаясь шорохами и просматривая видео; Кажется, я понимаю, что здесь происходит, но не понимаю, что с этим делать.

#[derive(Debug)]
enum Message {
    ChangeColor(u8, u8, u8),
    Echo(String),
    Move(Point),
    Quit,
}

#[derive(Debug)]
struct Point {
    x: u8,
    y: u8,
}

struct State {
    color: (u8, u8, u8),
    position: Point,
    quit: bool,
    message: String,
}

impl State {
    fn change_color(&mut self, color: (u8, u8, u8)) {
        self.color = color;
    }

    fn quit(&mut self) {
        self.quit = true;
    }

    fn echo(&mut self, s: String) {
        self.message = s
    }

    fn move_position(&mut self, p: Point) {
        self.position = p;
    }

    fn process(&mut self, message: Message) {
        println!("{:#?}", &message);
        match message {
            Message::ChangeColor(r, g, b) => self.change_color((r, g, b)),
            Message::Echo(s) => self.echo(s),
            Message::Move(p) => self.move_position(p),
            Message::Quit => self.quit(),
        }

        println!("{:#?}", &message); // <--------
    }
} 

Я понимаю, что значение сообщения перемещается в последнюю строку. Я ценю безопасность памяти средства проверки заимствований. Но я просто пытаюсь распечатать сообщение, чтобы посмотреть, что с ним произойдет. Я знаю, что его частично перемещают, и хочу увидеть, как он выглядит до и после перемещения.

Не меняя сигнатуры функций всего, как я могу просто взглянуть на это?

И также, правильно ли поступить, если я хочу сделать что-то еще с сообщением, просто клонировать его или каким-то образом сделать его изменяемым?

Меняется State не Message. Так может быть, вместо этого вы хотели отладить State? Если вы хотите проверить сообщение, вы можете добавить Clone к производному, а затем использовать message.clone() в условии match.

Timsib Adnap 10.06.2024 10:39

состояние определенно меняется, но сообщение перемещается. Меня смущает, что делать с чем-то после того, как оно было перемещено. И действительно, если в целом есть лучший способ отладки или просмотра значений, потому что иногда printlns по какой-то причине даже не печатает на терминал

Andrew Luhring 10.06.2024 10:42
message перемещается в выражении match, а не в последнюю строку. Вы пытаетесь распечатать message после его употребления. В этот момент все прошло. Возможно, он частично освобожден. Вы просто не сможете распечатать его после того, как оно исчезнет, ​​и я не понимаю, зачем вам это нужно.
Sven Marnach 10.06.2024 10:51

После того, как что-то было перемещено, вы не можете делать ничего, кроме перемещенной области. Если вы хотите отладить, вы можете использовать макрос dbg!. Если вы хотите отладить состояние, я могу дать ответ.

Timsib Adnap 10.06.2024 11:22

Я хочу увидеть, как он выглядит до и после перемещения — это все равно, что сказать: «Я хочу увидеть, как выглядит мой объект до и после free()». Управление памятью работает не так — после освобождения (в данном случае частичного, но это не имеет значения) объект становится непригоден для использования. Кроме того, вы даже не меняете объект, поэтому даже если бы вы могли каким-то образом распечатать его после перемещения, вы бы получили то же самое. Если вы хотите, чтобы значение оставалось пригодным для использования, измените match message на match &message и соответствующим образом измените соответствующие рычаги.

user4815162342 10.06.2024 11:46

Если вы получаете доступ к перенесенному значению, вы обязательно должны делать это небезопасным способом (см., например, std::mem::transmute, который позволит вам создать ссылку, пережившую перенесенное значение). Если вы сделаете это, ваша программа потенциально может выйти из строя. Но, вероятно, в этом случае значение не будет отличаться во второй точке, потому что переход от значения - это концепция времени компиляции - во время выполнения значение просто удаляется в конце своей области действия, как обычно, что здесь является концом область действия функции.

user2407038 10.06.2024 20:28

@user2407038 user2407038 Но компилятор может использовать информацию о живучести (т. е. перемещении), чтобы переменные перекрывались (потенциально).

Chayim Friedman 10.06.2024 22:21

@ChayimFriedman Действительно, компилятор имеет большую свободу в выборе того, когда и как он удаляется. Он не указан, поскольку не существует стандарта для его указания, и он может даже отличаться в разных версиях компилятора. Но это именно то, что надеется наблюдать ФП: «Я хочу увидеть, как это выглядит до и после переезда». Здесь «оно» — это ячейка памяти, ранее занятая message.

user2407038 11.06.2024 15:45

@user4815162342 user4815162342 это правильный ответ (совпадение и сообщение), если вы хотите, чтобы он был помечен как ответ, сделайте его и я отмечу его как решенный

Andrew Luhring 26.06.2024 00:06

@AndrewLhring Готово. Рад, что ваша проблема решена!

user4815162342 26.06.2024 09:00
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
10
80
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Итак, здесь есть пара вещей.

Прежде всего, подписи, вероятно, все равно следует немного обновить, функция echo может принять impl Into<String>, а затем вызвать .into(), что означает, что у нас нет частичного перемещения:

fn echo(&mut self, s: impl Into<String>) {
    self.message = s.into()
}

Message::Echo(ref s) => self.echo(s),

Хотя это просто клонирует значение, поэтому другие варианты оставляют параметр как String и просто клонируют s:

Message::Echo(ref s) => self.echo(s.clone()),

Просто вызов .clone() может быть лучшим вариантом, если прямо сейчас вам нужен только отладочный код. Так как вы можете легко удалить его после, и тогда у вас не будет избыточного клонирования.

Что касается Point, вы можете вывести Clone, Copy, поскольку u8 реализует Copy. Это означает, что вам не нужна move структура Point:

#[derive(Debug, Copy, Clone)]
struct Point {
    x: u8,
    y: u8,
}

Message::Move(p) => self.move_position(p),
Ответ принят как подходящий

Я хочу увидеть, как это выглядит до и после переезда.

В безопасном Rust это невозможно, и на то есть веские причины. Это все равно что сказать: «Я хочу увидеть, как будет выглядеть мой объект до и после его разрушения» на C++. После перемещения (в данном случае частичного, но это не имеет значения) значение больше невозможно использовать, и попытки его наблюдения, для чего потребуется небезопасный код, будут неопределенным поведением, т. е. вызовут сбои или неправильную компиляцию.

Если ваша реальная цель — наблюдать за объектом после match, например. для целей ведения журнала вы можете изменить свой match, чтобы он не отклонялся от значения. Самый простой способ сделать это — заменить match message на match &message и соответствующим образом изменить соответствующие плечи.

Другие вопросы по теме