Задать вопрос
  • FnMut в немутабельной переменной?

    bingo347
    @bingo347
    Crazy on performance...
    Мутабельность нужна для вызова, так как FnMut вызывается по мутабельной ссылке.
    Здесь же только передаётся владение в метод run

    P.S. что-то мне подсказывает, что сигнатура не совсем корректная. Отсутствует объявление дженерика T (и возможно его ограничений), отсутствует лайфтайм для ссылки в колбэке:
    pub fn run<T, F>(self, event_handler: F) -> Result<(), EventLoopError>
        where
            F: for<'a> FnMut(Event<T>, &'a EventLoopWindowTarget<T>),
    {
        self.event_loop.run(event_handler)
    }
    Ответ написан
    Комментировать
  • Напишите код, которой переделает структуру данных вот в такую?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Если нужно просто методы массива и коротко, то можно так:
    Object.entries(events).flatMap(([date, dateEvents]) => dateEvents.map(event => ({date, event})))
    Ответ написан
    Комментировать
  • Каких вещей следует избегать в Rust?

    bingo347
    @bingo347
    Crazy on performance...
    Я знаю, что следует избегать всяких "продвинутых" штук из ряда связных списков, самореферентных структур и т.п.
    Односвязные списки никаких проблем не доставляют (ну кроме того, что они плохо ложатся на процессорный кэш). Для двусвязных списков и самореферентных структур придётся использовать сырые указатели и unsafe.

    Ещё я обнаружил, что создание больших структур, с методами, с кучей полей, обычно приводит к проблемам с borrow checker.
    Borrow checker абсолютно плевать на размер структур. Это никак не связано.

    А если в структуре будет ссылка или иное заимствование, то это гарантированные проблемы.
    Нет ни каких проблем.

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

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

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

    И очень часто в Rust программах, мне приходится идти на более уродливую архитектуру, дабы избежать проблем с (почти ненужным в однопоточном коде) borrow checker.
    Что-то делаете не так. Скорее всего просто не понимаете borrow checker и пытаетесь писать на новом языке так, как привыкли в каком-то другом.

    И в вопросе о borrow checker, разве не является тот факт, что большинство библиотек избегает &mut self в изменяющих что-то методах, звоночком к наличию большим проблем в языке?
    О каком большинстве речь? Библиотеки используют мутабельные ссылки там где это нужно. Если метод действительно что-то меняет, то будет мутабельная ссылка ну и иногда будет использоваться interior mutability там где это необходимо. В языке нет проблем с мутабельными ссылками.

    В общем, посоветуйте что-то что-бы помогало меньше бороться с borrow checker, потому что сейчас я очень много времени трачу именно на это.
    Для начала понять его. Понять какую проблему он решает. Почитайте, что такое undefined behavior. Почитайте, что такое алиасинг.

    Возможно где-то альтернативой мутабельным ссылкам будут Cell/RefCell в однопоточном коде и Mutex/RwLock в многопоточном.
    Возможно если покажете примеры кода, где у Вас проблемы, то можно будет подсказать что-то более конкретное.
    Ответ написан
    3 комментария
  • Возможно ли выполнить JavaScript код в Rust при помощи NodeJS?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Хоть и вопрос несколько сумбурный и не совсем понятно, что автор хочет на самом деле...
    Но краткий ответ: да, возможно, но есть нюансы...

    Самый простой вариант - запускать node как отдельный процесс. Можно просто запускать на каждый чих, а можно заморочиться и организовать общение между приложением на Rust и приложением на Node.js

    Вариант поинтереснее - Node.js можно собрать как библиотеку (есть даже готовые бинарные сборки такого), линкуем с приложением на Rust. Всё живёт в одном процессе, но node будет запускать свои потоки.

    Есть и обратный последнему вариант. Можно из Rust кода собрать бинарный аддон к Node.js
    Правда тут уже JS код будет запускать код на Rust.
    https://napi.rs
    https://neon-rs.dev

    Можно пойти дальше. Если задача просто исполнять JS код из приложения на Rust, то можно слинковаться с одним из JS движков. Приколюх предоставляемых платформой Node.js здесь не будет (вроде fs или http), хотя никто не мешает реализовать это самостоятельно.
    https://crates.io/crates/v8
    https://crates.io/crates/quickjs_runtime
    Ответ написан
    3 комментария
  • Почему Jest не может распарсить CSS модуля?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    https://jestjs.io/docs/webpack#handling-static-assets

    В обычной сборке у Вас scss файлы собираются бандлером вроде webpack.
    А в jest никакого бандлера нет.
    Ответ написан
    Комментировать
  • Как реализовать свой класс мап, имитируя поведение стандартной хэш-мапы?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Для начала стоит почитать про устройство хэш таблиц:
    https://ru.wikipedia.org/wiki/%D0%A5%D0%B5%D1%88-%...
    https://habr.com/ru/articles/509220/
    Куча вопросов сразу отпадёт.
    Классическая структура данных кстати, полезно знать не зависимо от ЯП.

    1) Не понятно, что конкретно должна делать hash функция
    Вычисляет хэш от ключа. Остаток от деления хэша на длину массива - это индекс бакета, в котором будет хранится пара ключ-значение.

    2) Какой тип использовать у buckets
    Как вариант такой:type Buckets<K, V> = ([K, V] | undefined)[];
    Ответ написан
    Комментировать
  • Как реализовать превращение вектора объектов в дерево?

    bingo347
    @bingo347
    Crazy on performance...
    Главная проблема тут - лайфтаймы. В частности у переменной на стеке никогда не будет лайфтайма 'static.
    Ну и отдавать в куда либо долгоживущее ссылку на временное значение - UB. Благо лайфтаймы и тут спасают.
    Собственно для этого Rc и нужен - он владеющая ссылка. Соответственно в нём должно быть значение, а не ссылка (ссылка на ссылку редко когда нужна).

    use std::cell::RefCell;
    use std::rc::Rc;
    
    #[derive(Default, Clone, Debug)]
    struct NodeInner {
        name: String,
        source: String,
    
        path: String,
        leaf: bool,
        children: Vec<Node>,
    }
    
    #[derive(Default, Clone, Debug)]
    struct Node(Rc<RefCell<NodeInner>>);
    
    impl Node {
        fn fast(name: impl Into<String>, source: impl Into<String>) -> Self {
            Self(Rc::new(RefCell::new(NodeInner {
                name: name.into(),
                source: source.into(),
    
                path: String::new(),
                leaf: true,
                children: Vec::new(),
            })))
        }
    
        fn insert(&self, node: Node) {
            let mut current = self.clone();
            for part in node.0.borrow().source.split(".") {
                let inner = node.0.borrow();
                let found = inner.children.iter().find(|&v| v.0.borrow().path == part);
    
                match found {
                    None => {
                        let tmp = Node::fast(String::new(), String::new());
                        current.0.borrow_mut().children.push(tmp.clone());
                        current = tmp;
                    }
                    Some(val) => current = val.clone(),
                }
            }
        }
    }
    
    fn main() {
        let mut root = Node::default();
        root.insert(Node::fast("First", "e"));
        root.insert(Node::fast("First", "e.sources"));
        root.insert(Node::fast("First", "e.sources.two"));
        root.insert(Node::fast("First", "e.secret"));
        root.insert(Node::fast("First", "e.secret.left"));
        root.insert(Node::fast("First", "e.secret.right"));
        print!("{:#?}", root);
    }

    Как заполнять поля уже сами разбирайтесь, думаю тут не сложно
    Ответ написан
    3 комментария
  • Вызов функций С++ из .h?

    bingo347
    @bingo347
    Crazy on performance...
    Скорее всего придётся сделать extern C обёртку над библиотекой и биндится уже с ней. Ну и надо понимать, что никакие абстракции плюсов вроде темплейтов, классов и т.д. в раст не протащить.

    В какой-то степени может помочь cxx, но надо понимать, что эта штука тоже не всесильна.
    Ответ написан
  • Как правильно организовать shared проект?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Как правильно организовать shared проект?
    Как npm пакет.
    При этом не обязательно публиковать в общий npm репозиторий, можно поднять свой или устанавливать прямо из git
    Ответ написан
    Комментировать
  • Мальчик 15 лет, хочет в будущем стать программистом, что почитать и попробовать, для будущего осознанного понимания и выбора?

    bingo347
    @bingo347
    Crazy on performance...
    Мальчик 15 лет, хочет в будущем стать программистом

    А действительно мальчик хочет? В 15 лет те кто хочет самостоятельно ищут информацию и если не нашли - задают вопросы.
    И вот без этого вообще никуда, ибо поиск информации составляет значимую часть работы программиста. А ещё - нужно умение коммуницировать устно и письменно.

    Ну а по существу вопроса, самое действенное обучение - это взять и начать что-то делать для себя. Любое приложение/сайт/игру, которое будет интересно сделать. Неважно на каком языке. То есть начинаться должно именно с "хочу..."
    Притом "хочу много денег" - плохое "хочу", денег не приносит, но ведет к психологическим проблемам и тратам на их устранение. Хороший психолог начинается с 10 тыс. рублей в час...
    Хорошее "хочу" выглядит как "хочу написать свой тетрис", "хочу чтоб комп решал за меня школьные задачки", "хочу своего бота для любимой онлайн игры", "хочу телеграм бота, который будет присылать мне домашку из электронного дневника" и так далее.
    И вот когда определились с "хочу" гуглим как это сделать, какие языки позволяют это сделать.
    Начинаем делать и гуглим всё что непонятно как сделать.

    Ну и если всё таки придёт, что "не хочу", то не надо себя насиловать. IT - это не только программисты, а деньги - это не только IT. Любое дело можно монетизировать и получать хорошие деньги, если это дело любимое.
    Ответ написан
    4 комментария
  • Можно ли где-то подрабатывать/работать с небольшими знаниями в данных областях?

    bingo347
    @bingo347
    Crazy on performance...
    Плюсом к выше сказанному, можно попробовать себя приходящим админом-эникеем (задачи от принтер заправить до установить/настроить некоторый софт) сразу в несколько неайтишных маленьких контор. Для таких штатный админ может быть дорого, а иметь вот такого "по вызову" с оплатой по факту сделанного может быть вполне подъёмным.
    Ответ написан
    1 комментарий
  • Почему время жизни параметров берутся из дженериков?

    bingo347
    @bingo347
    Crazy on performance...
    Советую почитать вот эту статью: https://habr.com/ru/articles/515034/

    А вообще, времена жизни - это часть типа.
    Условный u32 имеет время жизни 'static
    А ссылка на u32 - &'a u32 (где 'a это диапазон от объявления исходного u32 до его последнего использования) будет иметь время жизни 'a
    Пример по сложнее, ссылка на ссылку - &'a &'b u32 - будет иметь время жизни наименьшее из 'a и 'b

    Передаётся через дженерик, так как функция должна работать с абстрактным временем жизни
    fn example<'a>(r: &'a u32) -> &'a u32 { r }
    
    fn f_a() {
        let a = 1;
        let r = example(&a);
    }
    
    fn f_b() {
        let b = 1;
        let r = example(&b);
    }
    В этом примере очевидно что переменная a в f_a будет иметь время жизни отличное от b в f_b, но example спокойно работает и с тем и с другим, то есть она является обобщённой по времени жизни, в первом случае она вернёт ссылку с временем жизни как у переменной a, во втором - как у b.

    А ещё помимо времен жизни и типов в дженериках могут быть некоторые константы:
    fn make_array<const SIZE: usize>(el: u32) -> [u32; SIZE] {
        [el; SIZE]
    }
    
    let arr = make_array::<3>(1); // [1, 1, 1]
    Ответ написан
    3 комментария
  • Что делает метод as_bytes?

    bingo347
    @bingo347
    Crazy on performance...
    Представление структуры в памяти в виде байтов
    Ответ написан
  • Вызов drop в вызове drop?

    bingo347
    @bingo347
    Crazy on performance...
    Почему drop принимает ссылку, а не значение?

    Потому что метод drop трейта Drop вызывается компилятором, каждый раз когда переменная владеющая чем-либо выходит из области видимости. И сам метод drop тут не исключение. То есть если бы self тут был по значению, компилятор был бы обязан его дропнуть в конце функции, что вызвало бы бесконечную рекурсию.

    Причём если вызывать drop() руками
    Функция core::mem::drop никакого отношения к трейту Drop не имеет. Если Вы глянете на её реализацию, то это просто пустая функция, которая принимает аргумент по значению, а он уже дропается на общих основаниях, так как выходит из области видимости в ней.

    Почему сначала вызывается drop для A, а потом для B? По логике drop должен сначала вызываться для полей.
    У Вас неверная логика. В метод трейта Drop приходит ссылка, а значит должна быть гарантия того что данные по ней полностью валидные. Всегда дропается сначала внешняя структура,а затем её поля. Более того компилятор не даст Вам даже мувнуть части структуры имплиментирующей Drop.

    Если очень нужно, то владение из поля можно забрать через std::mem::swap/std::mem::replace/std::mem::take
    Хотя проще это сделать обернув такое поле в Option и забирая владение его методом take
    Ответ написан
    2 комментария
  • Как установить bspwm на Arch'е?

    bingo347
    @bingo347
    Crazy on performance...
    В арч вики же всё подробно расписано:
    https://wiki.archlinux.org/title/Bspwm_(%D0%A0%D1%...

    Так же советую поставить polybar:
    https://wiki.archlinux.org/title/Polybar_(%D0%A0%D...

    И rofi:
    https://wiki.archlinux.org/title/Rofi_(%D0%A0%D1%8...

    В уже установленной системе, чтоб прописать что-то в конфиг, зайдите в консольную сессию (Ctrl+Alt+F3) и сделайте базовые настройки через консольные редакторы (vim/neovim/nano). Как минимум пропишите сочетание на запуск терминала для начала. (Терминал тоже нужно установить, тут уж на своё усмотрение, могу порекомендовать Allacritty)
    Ответ написан
    5 комментариев
  • Почему Vite.createServer не дожидается асинхронного кода?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    У vite внутри есть собственный обработчик события request, который отвечает раньше Вашего.

    Скорее всего Вам поможет вот это:
    https://vitejs.dev/config/server-options.html#serv...
    Ответ написан
  • Как написать такой макрос?

    bingo347
    @bingo347
    Crazy on performance...
    Я бы тут не парился, и превращал бы это:
    #[r]
    fn bar(a: usize) -> usize {
        if a % 2 == 0 {
            return 0;
        }
        1
    }


    В это:
    fn bar(a: usize, res: *mut usize) {
        fn bar_impl(a: usize) -> usize {
            if a % 2 == 0 {
                return 0;
            }
            1
        }
        unsafe { *res = bar_impl(a); }
    }
    Главная фишка в том, что исходный код оставляем без изменений, парсить надо только сигнатуру (что с использованием syn - легко).
    По сути просто генерируем обёртку. Для универсальности стоит учесть async fn.

    Ну и если совсем по хорошему, то тут легко UB поймать с сырым указателем, и генерируемую функцию имеет смысл делать unsafe.
    Ответ написан
    Комментировать
  • Возврат собственного типа ошибки из main с печатью сообщения об ошибке?

    bingo347
    @bingo347
    Crazy on performance...
    fn main() -> MainResultWrapper {
        MainResultWrapper(main_inner())
    }
    
    #[inline(always)]
    fn main_inner() -> Result<(), GlobalError> {
        let config = read_config_from_file()?;
        Ok(())
    }
    Ответ написан
    Комментировать
  • Как в Intersection Observer узнать, что элемент пропал из поля зрения?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Комментировать
  • Как внести в массив символы, которым соответствует диапазон u8?

    bingo347
    @bingo347
    Crazy on performance...
    fn main() {
        let src: Vec<[u8; 1]> = (0..u8::MAX).map(|i| [i]).collect();
        let mut info =  Vec::<&str>::with_capacity(u8::MAX.into());
        for u in &src {
            let t = std::str::from_utf8(&*u).unwrap_or("Err");
            info.push(t);
        }
        println!("\n{:#?}", info);
    }

    но надо понимать, что info будет связан лайфтаймом с src, чтоб избавится от этого нужно хранить в нём не &str а String или Box<str>
    fn main() {
        let info: Vec<Box<str>> = (0..u8::MAX).map(|i| {
            let u = [i];
            let t = std::str::from_utf8(&u).unwrap_or("Err");
            t.into()
        }).collect();
        println!("\n{:#?}", info);
    }
    Ответ написан
    1 комментарий