TGViewer
Rust Rust @rust_code · 8.92K subscribers
Post #333 2.62K
🎥 Rust: рефакторинг для новичков

📌 Отсутствие идиом Rust
Опытным программистам Rust режет глаз тот факт, что следующая функция возвращает кортеж, а не Result<>:

fn add_student() -> (Student, bool)

Данный подход не только не является идиоматическим, но и вводит в заблуждение читателя кода. Непонятно, что подразумевает логическое значение bool. В ответ на вывод этой функции придется написать что-то сложное, как показано ниже:

// Добавление студента на курс
let (st, err) = add_student();

// Проверка наличия ошибки. В случае ошибки продолжить цикл
if !err {
continue;
}


Получается 5 строк с комментариями, объясняющими код. Это считается плохой практикой, так же как и короткие имена переменных.

📌 Рефакторинг
Сначала проведем рефакторинг этих фрагментов. То, что было:

fn add_student() -> (Student, bool) {
// ...
let mut st = Student {
name: "".to_string(),
age: 0,
};
// ...
if student_name.len() < 3 {
// ...
return (st, false);
}
// ...
(st, true)
}


преобразуем в более идиоматический и читаемый вариант:

fn add_student() -> Result<Student, &'static str> {
// ...
if student_name.len() < 3 {
// ...
return Err("Student's name too short");
}
// ...
let age = age.parse.map_err(|_| "Cannot parse student's age")?;

Ok(Student {
name: student_name,
age
})
}


Понятно, что возврат статических строк в качестве ошибок не относится к разряду привычных практик, но вполне подойдет для данного примера.

◾️Метод .map_err() позволяет преобразовать экземпляр типа, содержащийся в значении перечисления Err(e), в такой, который поддерживается функцией.

В этом случае объявленным типом является &'static str (эквивалент Rust для идиомы типа const char* в С), чем объясняется совпадение текстов в кавычках. Оператор ?  — одна из лучших функциональностей Rust. Он проверяет стоящий перед ним экземпляр Result<>. Если значение равно Err(e), возвращает результат, в противном случае продолжает работу. В старом коде встречался макрос try!().

В итоге проверка ожидаемого вывода функции выглядит так:

let student = if let Ok(student) = add_student() {
student
} else {
continue;
}

student_db.push(student.clone());


Это неидеальное условие, поскольку оно фактически исключает любую ошибку. Действуя таким образом, мы исходим из предположения допустимости такого подхода, но предусматриваем обработку перечисления Err(e) на индивидуальной основе.

📌 Ошибка новичков: бесконечный цикл

Читать

@rust_code
  • 👍 17
  • ❤ 5
  • 👎 4
More from @rust_code
  1. Oct 6, 2026🦀 Rust дайджест за неделю: новый релиз, быстрее компилятор и собственные зелёные потоки ⚡…
  2. Oct 6, 2026Одна задача, три языка: Rust, C# или C++? В курсе Google *Comprehensive Rust* есть упражне…
  3. Oct 4, 2026Это не строка
  4. Oct 3, 2026Выпуск Rust 1.99.0. Microsoft перевёл Rust в число первичных языков Опубликован релиз язык…
  5. Oct 2, 2026🦀 Rust 1.99 научился определять C-совместимые variadic-функции Теперь в стабильном Rust м…
  6. Sep 30, 2026ИИ-агенты могут разгонять Rust-код быстрее SOTA-библиотек Макс Вулф провёл серию экспериме…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →