Rust_backtrace=1

Компилятор выдает сообщение “note: Run with RUST_BACKTRACE=1 environment variable to display a backtrace.”
Куда я должен это вставить или где искать?

Как выставлять зависит от ОС. В линуксах я обычно делаю просто RUST_BACKTRACE=1 cargo run.

У меня виндовс и VS Code, в котором я создал tasks.json

  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "shell",
      "label": "cargo run",
      "command": "cargo",
      "args": [
        "run",
      ],
      "problemMatcher": [
        "$msCompile",
      ]
    }
  ]
} ~~~
Пробовал вставить в команду перед cargo - получил ошибку.
Что нужно создавать переменную окружения виндовс?

Для начала нужно определится, Вы действительно хотите увидеть трейс? потому что ошибка как правило написана до этого сообщения, а этот текст “Run with RUST_BACKTRACE=1 environment variable to display a backtrace” - это дополнительная информация которая, говорит о том, что если хотите посмотреть трейс, то выставите переменную окружения RUST_BACKTRACE=1. Там даже в начале написано, что это note а не ошибка.

Проблема в том, что сама программа компилируется и запускается идеально без одного замечания, вот ввод с клавиатуры вызывает панику и вот это предложение. Все тесты проходят тоже идеально.
И я даже знаю где она случается:

io::stdin().read_line(&mut guess)
            .expect("<<<");

        //=================================
        let caps  = RE.captures(guess.trim()).unwrap();  

ее выдает unwrap, но поскольку я новичек в rust, то не могу понять в чем смысл.

unwrap это “грязный” метод. Он пытается из Result получить всегда успешный результат, а из Option всегда что то. Если результат содержит ошибку, то будет паника. Если Option будет содержать None будет тоже паника.

Сразу возникает вопрос “Зачем он нужен?”

Раст заставляет программиста всегда прописывать исход всех событий, что делать в случае ошибки, что делать в случае когда мы получим None. Если программист хочет проверить идею, или уверен что у него в этом месте всегда будет значение, он использует данный метод. Но так как он вызывает панику, его лучше не использовать в продакшене.

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

Я пытался вставить что-нибудь другое, например ok_or(), но все время получаю ошибку.
На данный момент я просто перевожу простенькие программы с С++ так как понимаю алгоритм и что должно быть на выходе.
Тут мне посоветовали почитать документацию по классу String - это 68 страниц А4 английского текста - это нереально.

Что такое RE и что возвращает метод captures?

Это регулярное выражение и сравнение с ним введенной с клавиатуры строки символов.

captures у регекса возвращает Option соответственно методов ok_or у Option нет. Нужно либо вызывать метод unwrap_or и прописывать дефолтное значение, либо использовать паттерн match.

В любом случае, лучше почитать учебник по расту, где все эти вещи более детально разжёваны. Учебник доступен и на русском языке в открытом доступе. Rust содержит слишком много отличий от других языков и просто так, зная один пересесть на другой не читая документацию по языку, не получится…

Три учебника в Интернете - cargo, std, regex. Плюс эта же программа еще на 5 языках - C++, PowerShell, Perl, PHP, Python,
Плюс несколько программок на Rust типа вычисления факториала.
Кстати, в одной книге и есть пример:

let captures = semver.captures(haystack)
.ok_or("должно соответствовать регулярному выражению semver")?;

Вам нужен базовый учебник, после которого у вас будет понимание как нужно программировать на Rust и уже потом можно в остальном по мере необходимости разбираться. Базовый учебник есть на официальном сайте, русская версия тут.

Сейчас все ваши вопросы уровня что такое if и как с ним работать. Я понимаю что Вы возможно знаете ни один язык, но тут принцип иной, отличный. И по этому Option, Result основы языка, а по мимо этих вещей в языке существует десятки других. По этому и призываю прочитать учебник , там найдете ответы на все Ваши вопросы :wink:

По поводу примера с semver, метод ok_or преобразует Option в Result. После чего стоит символ “?” это значит что в случае ошибки он возвращает ошибку для текущего метода и исполнение кода, дальше не идет. В случае успеха, значение записывается в переменную captures. В вашем случае Вы делали конвертацию option в Result, но дальше наверняка ни чего не предприняли. Мало написать знак вопроса в конце, вызываемый метод должен ожидать и тип возврата Result. В общем лучше почитать учебник, там это есть :wink:

1 лайк

У меня есть этот учебник и даже скомпилированный в html формат. Базовые знания языка у меня есть и даже вот эта программа скомпилировалась без единого предупреждения.

#[macro_use] 
extern crate lazy_static;

extern crate regex;

use std::io;
use regex::Regex;

//===========================
fn main() 
{
    //let re = Regex::new(r"([-+]?[0-9]+(?:[.][0-9]*)?)[[:space:]]*([CF])").unwrap();

    lazy_static! 
    {
        static ref RE: Regex= Regex::new(r"([-+]?[0-9]+(?:[.][0-9]*)?)[s]*([CF])").unwrap();
    }

    //===================================
    loop
    {
        println!("Enter a temperature (e.g., 32F, 100C) >>> ");

        let mut guess = String::new();

        io::stdin().read_line(&mut guess)
            .expect("<<<");

        if guess.trim() == "q"
        {
            break;
        }

        //=================================
        let caps  = RE.captures(guess.trim()).unwrap();  

        let temperature = caps[1]
                                .trim()
                                .parse()
                                .expect("<<<");
        
       // println!("{}", temperature);

        let scale = caps[2].trim();

       // println!("{}", scale);

        //================================
        if caps[0].trim() != ""
        {
            //===============================
            if scale == "c" || scale == "C"
            {
                let celsius = temperature;
                let fahrenheit = (celsius * 9 / 5) + 32;

                println!("{} C is {} F", 
                        celsius, 
                        fahrenheit);
            }
            else 
            {
                let fahrenheit = temperature;
                let celsius = (&fahrenheit - 32) * 5 / 9;

                println!("{} C is {} F", 
                        celsius, 
                        fahrenheit);
            }
        }
        else 
        {
            println!("Mystake");
        }
    }
}

И даже запускается и даже выходит из цикла.

У Вас нет понимание Option, unwrap, Result и try по этому я и отослал Вас к учебнику. Там эти моменты разжеваны. Сейчас Вы написали, что если регулярное выражение не выполняется, паникуем. И спрашиваете почему паникуем, хотя сами подобное и написали. Пишите без unwrap и сразу станет все понятно. Unwrap существует для определенных кейсов, например по быстрому показать рабочий код и чтоб валидатор кода не упал, но ни как не для продакшен кода.

А я и не утверждаю, что являюсь профи в Rust - если бы это было так, то меня бы здесь не было.
Просто все рекомендуют ставить unwrap где надо и где не надо. Вот что получилось когда я его убрал

   Compiling convert v0.1.0 (C:\Users\Wlad\Documents\rustProjects\convert)
error[E0608]: cannot index into a value of type `std::option::Option<regex::Captures<'_>>`
  --> src\main.rs:37:27
   |
37 |         let temperature = caps[1]
   |                           ^^^^^^^

error[E0608]: cannot index into a value of type `std::option::Option<regex::Captures<'_>>`
  --> src\main.rs:44:21
   |
44 |         let scale = caps[2].trim();
   |                     ^^^^^^^

error[E0608]: cannot index into a value of type `std::option::Option<regex::Captures<'_>>`
  --> src\main.rs:49:12
   |
49 |         if caps[0].trim() != ""
   |            ^^^^^^^

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0608`.
error: Could not compile `convert`.

To learn more, run the command again with --verbose.
Процесс терминала завершен с кодом выхода: 1

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

Я уже сказал что нужно почитать. Полностью главы про Option, Result и unwrap. Споллер, unwrap Вам не нужно использовать.

Так же учимся читать ошибки, которые на 100% отвечают о проблеме компиляции. Например выше раст говорит что не может взять элемент с индексом у типа Option потому что тип Option не имеет индекса доступа

Еще, наверное, раздел про перечисления и match: https://rustycrate.ru/book/ch06-00-enums.html

1 лайк

На всякий, порпобую просуммировать:

У тебя сейчас проблема в том, что

io::stdin().read_line(&mut guess).expect("<<<");
let caps  = RE.captures(guess.trim()).unwrap();

грохается на unwrap, правильно?

Доки этой функции говорят, что она возвращает Option<Captures<'t>>. Т.е. в случае успешного сопоставления строки с образцом она выдает Option::Some(тут полезные данные о сопоставлении), а если сопоставление с регуляркой прошло неудачно, то вернется Option::None.

Ты берешь этот Option и дергаешь у него unwrap метод, который роняет паникой все приложение при получении None.

Т.е. тебе надо почитать в учебнике про способы обработки Option, которых довольно много может быть. Ссылок и названий глав выше много дали.

Простым и прямолинейным способом, хоть и не осоюбо изящным, с которого я бы начал, является обычный match:

let caps  = match RE.captures(guess.trim()) {
    Some(caps) => caps,
    None => {
        println!("No match found, aborting"); // пишем какое-то понятное сообщение пользователю
        return; // завершаем выполнение main функции
    }
};

Я уж наверное скоро наизусть выучу всю документацию что тоже не плохо - когда все с ходу все получилось, то тут же и забылось.
Но почему то у меня подозрение, что не unwrap дело - я с таким столкнулся на С++ - ни один компилятор не воспринимает пробельные символы типа \s или \t.
Ну вставлю я match и узнаю, что caps = None, но ведь это и так понятно.
Поэтому я пришел сюда в надежде на то, что кто-нибудь посмотрит на само регулярное выражение - может именно в нем ошибка.