Ответы пользователя по тегу Rust
  • Можно ли избежать такой конструкции?

    vabka
    @vabka
    Токсичный шарпист
    Чтобы было чуть проще, тебе нужно реализовать оператор для:
    1. m + m
    2. &m + &m
    3. m + &m
    4. &m + m

    https://stackoverflow.com/questions/38811387/how-t...

    Но совсем избавиться от & не получится - компилятор в любом случае должен знать, когда ты хочешь копирование/move, а когда ты хочешь заимствовать.
    Ответ написан
    Комментировать
  • Есть возможность локонично реализовать множественную фильтрацию в if let?

    vabka
    @vabka
    Токсичный шарпист
    В твоём случае логичнее было бы использовать метод any, если ты хочешь просто проверить, что такие элементы существуют.

    Как вариант ты можешь сделать так, если тебе нужны потом переменные poz_*:
    fn read() -> Result<(), io::Err> {
      //let vec: Vec<u8> = !vec[2, 5, 8, 10, 15, 16];
      let pos1 = self.responce.iter().position(|&el| el == 8).ok_or_else(||io::Err::new("understading message"))?;
      let pos2 = self.responce.iter().position(|&el| el == 15).ok_or_else(||io::Err::new("understading message"))?;
      let pos3 = self.responce.iter().position(|&el| el == 12).ok_or_else(||io::Err::new("understading message"))?;
      return Ok(());
    }

    Ещё можно попробовать let-else
    Ответ написан
    8 комментариев
  • Как исправить "cannot borrow as mutable"?

    vabka
    @vabka
    Токсичный шарпист
    Попробуй вместо того что у тебя написано использовать entry()
    self.on_event_closure
      .entry(event)
      .or_insert_with(Vec::new)
      .and_modify(move |vec| vec.push(f));


    А нельзя borrow as mutable из-за того что get заимствует on_event_closure
    Ответ написан
    1 комментарий
  • В чем разница между str и &str?

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

    str - это встроенный тип, который представляет из себя последовательность из байтов utf8.
    Размер значения str не известен во время компиляции, а по тому нигде его нельзя применить в чистом виде (только как содержимое какого-нибудь типа-указателя)
    Можно провести аналогию с массивом (только в случае массивов размер таки известен, но его тоже достаточно редко используют в таком чистом виде)

    &str - это ссылка на эту последовательность байт.
    Это может быть ссылка на содержимое String или ссылка на строковый литерал (&'static str)

    Кстати, String под капотом - это Vec<u8>
    Ответ написан
    Комментировать
  • Какой тип данных у переменной a?

    vabka
    @vabka
    Токсичный шарпист
    См. ответ Дмитрий Беляев
    Ошибочное, но близкое предположение
    Просто для массива реализован трейт AsMut.
    https://doc.rust-lang.org/std/convert/trait.AsMut.html
    По тому
    let a_ : &mut[u8] = &mut a;
    Ответ написан
  • Как решить проблему linking with `link.exe` failed: exit code: 1181 при сборке проекта на Rust?

    vabka
    @vabka
    Токсичный шарпист


    Во-первых, что значит последняя строчка? как это расшифровать?

    Самый простой вариант -скопировать и вставить в строку, например в панели разработчика в браузере.

    Вообще ошибка про то, что он у тебя не может найти нужную библиотеку.

    А добавлять их надо не в PATH, а в LIB_PATH
    Ответ написан
    Комментировать
  • Как исправить ошибку во время сборки Rust build error: failed to run custom build command for `glib-sys v0.8.0`?

    vabka
    @vabka
    Токсичный шарпист
    Ошибка в целом про то, что скрипт сборки не смог найти у тебя нигде бинарник glib.
    Если вы его установили, но не добавили его путь в переменную PKG_CONFIG_PATH, то стоит попробовать это сделать.

    Вариант раз:
    Может быть, если использовать msys/cygwin/mingw с установленным glib - тогда получится собрать.
    Естественно, тогда придётся установить другой тулчейн через
    rustup toolchain install stable-x86_64-pc-windows-gnu
    rustup default stable-x86_64-pc-windows-gnu


    Вариант два:
    Возможно, у собираемого крейта есть какой-нибудь опциональный feature, который позволяет использовать что-то другое, вместо glib или собрать его с нуля из исходников

    Вариант три:
    Возможно, этот крейт в принципе для винды и не задумывался - тогда остаётся только запуск в WSL2

    PS: Если дадите ссылку на собираемый проект, тогда можно будет подсказать больше.
    Ответ написан
  • Выбрать Rust или C++?

    vabka
    @vabka
    Токсичный шарпист
    Rust достаточно стабильный и популярный, чтобы начать с ним работать.
    По геймдеву - в принципе все нужные низкоуровневые библиотеки для работы с графикой там уже есть. Да и движки свои понемногу да появляются.
    Пример из тех, что сейчас активно развиваются - bevy, на нём уже можно делать не очень сложные игры, да и просто как образец он тоже интересный: во главе угла стоит модульность и ECS.
    Ответ написан
    Комментировать
  • Почему Rust нужна хэш-функция для реализации объектов, а JS такое не использует?

    vabka
    @vabka
    Токсичный шарпист
    Вообще объекты в JS - это тоже hashmap, и в этой структуре есть защита от коллизий:
    Если вдруг два разных ключа получили один и тот же хеш, то они складываются в одну корзину, и при попытке получить значение по ключу - придётся ещё пройтись по всем парам ключ-значение в этой корзине, чтобы найти нужный ключ, уже используя Eq.
    Ответ написан
    Комментировать
  • Как правильно описать метод на rust?

    vabka
    @vabka
    Токсичный шарпист
    У тебя проблема не в трейтах, а в том что ты пытаешься обращаться к полям структуры, которая передаётся как T.
    Решить эту проблему можно добавлением ещё одного трейта и ограничением женерика.
    Вот так должно работать:
    pub struct Animal {
        pub name: String,
        pub age: i32,
        pub strength: i32,
    }
    
    pub struct Person {
        pub name: String,
        pub age: i32,
        pub strength: i32,
    }
    // Выделяем новый трейт, который позволяет получить силу
    trait Strength {
        fn strength(&self) -> i32;
    }
    
    trait BaseTrait {
        fn init(&self);
        
        // В старом трейте принимаем target по ссылке и ограничиваем, что принимаем только такой target, который реализует trait Strength
        fn stronger_than<T>(&self, target: &T) -> bool
        where
            T: Strength;
    }
    
    impl Strength for Person {
        fn strength(&self) -> i32 {
            self.strength
        }
    }
    
    
    impl Strength for Animal {
        fn strength(&self) -> i32 {
            self.strength
        }
    }
    
    impl BaseTrait for Person {
        fn init(&self) {
            println!("Hello, im Person: {}", self.name);
        }
    
        fn stronger_than<T>(&self, enemy: &T) -> bool
        where
            T: Strength,
        {
            self.strength > enemy.strength() // вызываем метод, вместо обращения к полю
        }
    }
    
    impl BaseTrait for Animal {
        fn init(&self) {
            println!("Hello, im Animal: {}", self.name);
        }
    
        fn stronger_than<T>(&self, enemy: &T) -> bool
        where
            T: Strength,
        {
            self.strength > enemy.strength()
        }
    }
    
    fn main() {
        let person = Person {
            name: String::from("John"),
            age: 25,
            strength: 12,
        };
        let animal = Animal {
            name: String::from("Elephant"),
            age: 5,
            strength: 360,
        };
    
        person.init();
        animal.init();
        
        if person.stronger_than(&animal) {
            println!("Person is stronger than animal");
        }
        if animal.stronger_than(&person) {
            println!("Animal is stronger than person")
        }
    }

    Либо можно вынести функцию stronget_that в отдельный трейт и реализовать его для каждого T, по аналогии с ответом Василий Дёмин, но тогда реализаций придётся писать целую гору.
    Ответ написан
    Комментировать
  • Почему некорректно отображается цвет?

    vabka
    @vabka
    Токсичный шарпист
    Попробуй вместо clear_color использовать функцию clear_color_srgb - с ней у меня цвет нормальный выдаёт.
    Это как-то связано с тем, как opengl представляет цвета, но найти статью про это я не смог.
    Ответ написан
    1 комментарий
  • Можно ли вызвать ошибку времени компиляции в макросе?

    vabka
    @vabka
    Токсичный шарпист
    Ну if ты не можешь туда впихнуть, но ты можешь сделать что-то типа
    macro_rules! macro {
     (5) => {compile_error! ("5 is unacceptable")}
    }

    https://doc.rust-lang.org/std/macro.compile_error.html

    Делать какие-то сложные проверки с условиями ты в декларативных макросах не можешь.
    Например ты не можешь вычислить значение выражения. И не можешь убедиться, что это значение константное.
    Так что иногда придётся делать динамические проверки, добавляя всякие if-ы и assert-ы
    Ответ написан
    Комментировать
  • Как проверить удерживается ли клавиша на Windows os?

    vabka
    @vabka
    Токсичный шарпист
    Под виндой ты можешь попробовать крейт windows и функцию GetKeyState:
    https://docs.microsoft.com/en-us/windows/win32/api...
    cargo.toml
    [package]
    name = "windows_key_press"
    version = "0.1.0"
    edition = "2021"
    
    
    [dependencies.windows]
    version = "0.37.0"
    features = ["Win32_UI_Input_KeyboardAndMouse"]

    main.rs

    use std::thread;
    use windows::Win32::UI::Input::KeyboardAndMouse::{GetKeyState};
    fn main() {
        const VK_SPACE: i32 = 0x20;
        const HIGHER_ORDER_BIT: i16 = -128;
        loop {
            let state = unsafe { GetKeyState(VK_SPACE) };
            let is_up = state & HIGHER_ORDER_BIT == 0;
            println!("{}", is_up);
            thread::sleep(std::time::Duration::from_millis(100));
        }
    }
    Ответ написан
    Комментировать
  • Как правильно написать макрос для такого выражения?

    vabka
    @vabka
    Токсичный шарпист
    Вот эта ошибка:
    missing tokens in macro arguments

    Означает, что раст не может сматчить макрос с таким аргументом. Дело в том, что "1" не является BlockExpression, который ты ожидаешь в начале (https://doc.rust-lang.org/reference/expressions/bl...)

    Вот примерно рабочий макрос, который ничего не делает.
    macro_rules! name {
        ($t: ty, $({$($el:expr ),*}),*) => {42};
        
    }
    fn main() {
        name!(i32, {1, 2, 3 ,4}, {1,2});
    }
    Ответ написан
  • Как убрать кавычки в результате вывода содержимого файла после его чтения в Rust?

    vabka
    @vabka
    Токсичный шарпист
    {:?} использует Debug для форматирования. В твоём случае он тебе не нужен.

    Попробуй вот так:
    #[get("/index")]
    pub async fn index() -> impl Responder {
        let path = Path::new("test.txt");
        spawn_blocking(|| cat(path)).await?
    }
    
    fn cat(path: &Path) -> io::Result<String> {
        let mut f = File::open(path)?;
        let mut s = String::new();
        match f.read_to_string(&mut s) {
            Ok(_) => Ok(s),
            Err(e) => Err(e),
        }
    }


    Кстати, твоя функция cat использует синхронный IO, так что её следует вызывать в spawn_blocking.
    Но лучше будет перейти на tokio или async_std
    Ответ написан
    3 комментария
  • Есть ли аналог curl для Rust?

    vabka
    @vabka
    Токсичный шарпист
    Оставлю ответ для будущих поколений.
    Есть вполне хороший пакет - reqwest.
    https://github.com/seanmonstar/reqwest

    Код будет такой:
    (сначала надо добавить зависимость)
    [dependencies]
    reqwest = { version = "0.11", features = ["blocking", "json"] } #blocking - только для примера, чтобы не нагружать await-ами. json - чтобы добавить возможность десериализации ответа при помощи serde-json


    use std::collections::HashMap;
    
    fn main() -> Result<(), Box<dyn std::error::Error>> {
        let resp = reqwest::blocking::get("https://httpbin.org/ip")?
            .json::<HashMap<String, String>>()?; // Тут нужно подставлять тот тип, который реализует трейт Deserialize
        println!("{:#?}", resp);
        Ok(())
    }
    Ответ написан
    Комментировать
  • Странный дизайн Rust?

    vabka
    @vabka
    Токсичный шарпист
    Во первых, почему указатели в Rust называются ссылками?

    Потому что в Rust есть свои типа умные ссылки, которые проверяются борроу-чекером - &T и &mut T.
    А есть сырые указатели, которые *const T и *mut T;

    Разница в том, что первые проверяются борроу-чекером, а вторые - нет.
    Первые можно безопасно разыменовать и обращаться к данным, а вторые - нет.

    Вот как это вместить - после плюсов вызывает неприязнь.

    Просто забыть привычки от C++ и плюсовую терминологию, и использовать новую.
    У вас же при изучении нового человеческого языка не возникает проблем от того что какой-нибудь кот называется кэт-ом?
    Ответ написан
    Комментировать
  • Rust мёртв, или только развивается?

    vabka
    @vabka
    Токсичный шарпист
    Rust появился в 2006

    Rust перешёл в stable только в 2015.
    До этого это были всякие прототипы и эксперименты.
    на данное время крупных проектов использующие его (кроме дискорда) нет

    https://www.rust-lang.org/production/users
    Как мне кажется, достаточно много разных крупных и именитых продуктов.

    PS: С Rust у тебя бы не возникло таких вопросов:
    https://qna.habr.com/q/1155256
    https://qna.habr.com/q/1147948
    Ответ написан
    Комментировать