• Как изменить данные завернутые в Box, который завернут в Option?

    bingo347
    @bingo347
    Crazy on performance...
    Во-первых стоит познакомится с такой конструкцией, как if let.
    Но здесь, с Box, у Вас не получится обойти borrow checker.
    Нормальным решением будет использовать счетчики ссылок (Rc или Arc) и избавиться с их помощи от зависимости на лайфтаймы. А для ссылки на parent нужно использовать Weak ссылку, чтоб она не влияла на подсчет ссылок.

    https://doc.rust-lang.org/std/rc/struct.Rc.html
    https://doc.rust-lang.org/std/rc/struct.Weak.html

    https://doc.rust-lang.org/std/sync/struct.Arc.html
    https://doc.rust-lang.org/std/sync/struct.Weak.html

    use std::rc::{Rc, Weak};
    
    pub struct Node {
        parent: Weak<Node>,
        data: u32,
        pub left: Option<Rc<Node>>,
        pub right: Option<Rc<Node>>,
    }
    
    #[derive(Debug)]
    pub struct SetChildError;
    
    impl Node {
        pub fn new(data: u32) -> Self {
            Self {
                parent: Weak::new(),
                data,
                left: None,
                right: None,
            }
        }
    
        pub fn set_left(self: &mut Rc<Self>, mut child: Rc<Self>) -> Result<(), SetChildError> {
            let child_mut = Rc::get_mut(&mut child).ok_or(SetChildError)?;
            child_mut.parent = Rc::downgrade(self);
    
            let self_mut = Rc::get_mut(self).ok_or(SetChildError)?;
            self_mut.left = Some(child);
    
            Ok(())
        }
    }
    Ответ написан
    5 комментариев
  • Как равномерно заполнить 3 массива с учетом высоты элементов?

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

    // Сохраняем исходные индексы и сортируем по высоте по убыванию
    const preparedData = data
        .map((e, i) => ({i, e}))
        .sort((a, b) => b.e.height - a.e.height);
    
    for (const el of preparedData) {
        const { height } = el.e;
        // тут никогда не вернет -1, так как мы ищем элемент который точно есть в массиве - минимальный
        const index = columnHeight.indexOf(Math.min(...columnHeight));
        // обновляем данные массивов по выбранному индексу
        columnHeight[index] += height;
        columns[index].push(el);
    }
    
    // нормализуем columns
    for (let i = 0; i < columns.length; ++i) {
        // восстановим исходный порядок, отсортировав по сохраненному индексу по возрастанию
        columns[i].sort((a, b) => a.i - b.i);
        // избавимся от сохраненных индексов, оставив только исходные объекты
        columns[i] = columns[i].map(({ e }) => e);
    }
    Ответ написан
    Комментировать
  • Объясните пожалуйста работу этого кода?

    bingo347
    @bingo347
    Crazy on performance...
    1)curr = dummy = ListNode()
    что это за конструкция. ну вернее я знаю, что это объект класса, но зачем сразу 2 переменные? сделал вот так
    dummy = ListNode() и не работает

    2 переменные нужны, что бы иметь ссылку и на начало и на конец списка, в конец будем добавлять ноды из других списков, а начало нужно чтоб потом сделать return

    if l1.val >l2.val:
                    curr.next = l2 
                    l2 = l2.next
    объясните пожалуйста вот эти 2 строчки
    curr.next = l2 
    l2 = l2.next
    Через if выбрали из какого из 2 списков будем вставлять ноду в наш список и добавили ее туда, потом запомнили ссылку на следующую ноду выбранного списка

    3) Почему возвращаем именно dummy и next?
    return dummy.next
    В dummy у нас начальная нода нашего списка, но она опорная, мы ее сами создали, а не взяли из исходных списков, а вот следующая - уже нода одного из списков.
    Ответ написан
  • Почему не работает onclick при работе с webpack?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    HTML ищет обработчики в только глобальной области видимости.
    Хранить что-либо в глобальной области видимости - чревато проблемами.
    webpack изолирует область видимости модулей в замыканиях дабы таких проблем не возникало.

    Навешивайте обработчики через JS, например как показал Yorido Satoshi
    Ответ написан
    Комментировать
  • Как это убрать в VS code?

    bingo347
    @bingo347
    Crazy on performance...
    За это отвечает свойство "editor.cursorStyle" в настройках
    Ответ написан
    Комментировать
  • Хорошее ли это решение для резюме?

    bingo347
    @bingo347
    Crazy on performance...
    Для начала стоит убедиться, что формат резюме соответствует общепринятым нормам.
    Затем стоит подумать а кому и как вообще будет отправляться резюме, где искать работодателя.
    Даже если отправляете ссылкой, должна быть простая возможность выгрузить его в pdf.
    Как по мне, гораздо удобнее держать резюме в актуальном состоянии на сайтах linkedin.com и hh.ru, кроме того там и работодателей можно искать.
    Ответ написан
  • Как сделать так что бы сайт спрашивал у пользователя доступ к камере?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    navigator.mediaDevices.getUserMedia({video: true})
    https://developer.mozilla.org/ru/docs/Web/API/Medi...

    Браузер сам запросит разрешение, когда Вы запросите камеру
    Ответ написан
    Комментировать
  • Правильно ли решил задачу?

    bingo347
    @bingo347
    Crazy on performance...
    Задачка прикольная для обучения, позволяет поработать сразу со многими конструкциями языка.

    Для начала комментарии по Вашему решению:
    1. Тип String алоцирует память на куче, операция += над типом String может приводить к реалокации памяти. Алокация памяти не дешевая операция, в данной задаче можно обойтись вообще без нее.
    2. Для повторяющихся операций придумали циклы, а с циклами хорошо сочетаются коллекции, например массивы и слайсы.
    3. Уже писали в комментах, но все же, if true - бесполезная штука.

    Теперь давайте посмотрим на текст песни. У нас 12 куплетов.
    Каждый куплет начинается с очень похожих строчек: "On the first day of Christmas", "On the second day of Christmas", и т.д., меняется только числительное.
    Потом всегда идет строчка "My true love sent to me" в каждом куплете.
    Затем идет от 1 до 12 строчек, повторяющиеся из куплета в куплет, но в i-том куплете будет только i таких строчек. Притом тут есть особенность, что первая строчка в куплете иногда отличается от своих аналогов в последующих куплетах.
    Ну и наконец, в 12 куплете мы видим, что строка "And a partridge in a pear tree" присутствует 2 раза, что выбивается из общего правила.

    Решение с объяснением

    Для начала вынесем факт того, что у нас 12 куплетов в константу, это нам пригодится для дальнейшего объявления массивов и итерации по ним.
    const NUMBER_OF_VERSES: usize = 12;

    Заведем массив числительных, которые меняются в первых строчках куплетов.
    const NUMERALS: [&str; NUMBER_OF_VERSES] = [
        "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth",
        "11th", "12th",
    ];


    Так же заведем массив, для повторяющихся строчек куплетов.
    const LINES: [&str; NUMBER_OF_VERSES] = [
        "And a partridge in a pear tree",
        "Two turtle-doves",
        "Three French hens",
        "Four calling birds",
        "Five golden rings (five golden rings)",
        "Six geese a-laying",
        "Seven swans a-swimming",
        "Eight maids a-milking",
        "Nine ladies dancing",
        "Ten lords a-leaping",
        "Eleven pipers piping",
        "12 drummers drumming",
    ];


    Так же нам понадобится массив первых строчек куплетов, так как среди них есть отличающиеся. Я нашел такие в 1 и 11 куплете (так как массивы у нас индексируются с 0, то они будут под индексами 0 и 10 соответственно). Остальные же будут такими же как в массиве LINES, а значит можно по экономить размер бинаря и занимаемую память за счет того что в массивах у нас только ссылки на строки, которые можно копировать.
    Тут конечно можно написать что-то вроде
    const DIFFERING_LINES: [&str; NUMBER_OF_VERSES] = [
        "A partridge in a pear tree",
        LINES[1],
        LINES[2],
        // ...
    ];
    но это дикая копипаста, которая плохо читается и подвержена ошибкам.
    Благо в Rust есть константные функции, которые могут выполняться в compile-time и возвращают константы, а значит можно наш константный массив сгенерировать. Правда константные функции довольно сильно ограничены, в них можно пользоваться лишь ветвлениями, циклами, простейшей арифметикой (в том числе над указателями, а значит и получать доступ к элементам массива по индексу). Так же можно вызывать другие константные функции. Цикл for нам к сожалению тут не доступен, так как он работает поверх итераторов, а методы IntoIter::into_iter и Iterator::next, которые он вызывает, не являются константными. Но цикл со счетчиком можно сделать и через while. По итогу получим такую функцию:
    const fn gen_differing_lines() -> [&'static str; NUMBER_OF_VERSES] {
        let mut i = 0;
        let mut lines = [""; NUMBER_OF_VERSES];
        while i < NUMBER_OF_VERSES {
            lines[i] = match i {
                0 => "A partridge in a pear tree",
                10 => "I sent 11 pipers piping",
                i => LINES[i],
            };
            i += 1;
        }
        lines
    }

    И инициализируем ей наш массив:
    const DIFFERING_LINES: [&str; NUMBER_OF_VERSES] = gen_differing_lines();


    Теперь еще особенность, в самих куплетах, строчки из LINES в них идут в обратном порядке. То есть для 4 куплета (индекс 3) нам помимо строчки DIFFERING_LINES[3] нам нужно напечатать строки под индексами 2, 1 и 0 из LINES. Для удобства вынесем печать строк из LINES в отдельную функцию:
    fn print_verse(mut i: usize) {
        while i > 0 {
            i -= 1;
            println!("{}", LINES[i]);
        }
    }


    Ну и осталось написать основной код для печати:
    fn main() {
        for i in 0..NUMBER_OF_VERSES {
            println!("On the {} day of Christmas", NUMERALS[i]);
            println!("My true love sent to me");
            println!("{}", DIFFERING_LINES[i]);
            print_verse(i);
        }
        println!("{}", LINES[0]);
    }


    А полное решение можно посмотреть и запустить тут:
    https://play.rust-lang.org/?version=stable&mode=re...
    Ответ написан
    Комментировать
  • Почему wasm код не генерируется при компиляции rust кода с сырыми указателями?

    bingo347
    @bingo347
    Crazy on performance...
    Начну пожалуй с того, что в первом примере у Вас UB (undefined behavior):
    #[no_mangle]
    pub fn test() {
        // Вот тут на стеке выделено 4 байта
        let mut idx: i32 = 10;
        // Указатель на эти 4 байта
        let ptr = &mut idx as *mut i32;
    
        // По сути указатель на те же 4 байта, но на деле указатель на 40 байт
        let buffer = unsafe { core::slice::from_raw_parts_mut(ptr, 10) };
    
        // И тут мы работаем с этими 40 байтами,
        // но нормальные из них только 4 байта в начале,
        // а остальные смотрят в глубь стека и меняют его
        // то есть перетирают адрес возврата и данные на стеке вызвавшей функции
        for pixel in buffer.iter_mut() {
            *pixel = 0x7d2b7500;
        }
    }
    То есть после завершения данная функция должна не вернуться в вызывающую функцию, а передать управление непонятно куда.

    Ну и еще один момент, это оптимизация, данная функция не имеет сайд эффектов и ничего не возвращает. После инлайна функции core::slice::from_raw_parts_mut и метода Iterator::iter_mut компилятор вполне может понять, что данный код не имеет сайд эффектов, а значит бесполезен и его можно вырезать. Вот собственно он его и вырезает.
    Во втором же примере у нас есть сайд эффект - изменение данных по указателю пришедшему извне через аргументы.

    P.S. Во втором примере кстати тоже можно увидеть работу оптимизации, цикл из 10 итераций, пишущих i32 в смещение по указателю, был заменен на обычные 5 записей i64 в смещение по указателю.
    Ответ написан
    1 комментарий
  • Как фронтенд понимает, что мы авторизованы?

    bingo347
    @bingo347
    Crazy on performance...
    2. Сервер присылает нам ответ, если он позитивный, то возвращает set-cookie, где устанавливает в cookie бразуера сессионный ключ;
    Притом set-cookie он возвращает с флагами secure (доступно только по https) и http-only (недоступно из js). Это единственный доступный вариант хранить сессионный ключ, чтоб его не угнали.

    Во время работы приложения - каким образом фронтент понимает, что отображать? Авторизованную страницу с данными или экран авторизации.
    Делает запрос на эти данные, если успешно - пользователь авторизован, можно записать это в стейт в памяти, как и данные, если 401 - пишем в стейт и на основе этого у нас экран авторизации.
    При отправке логина и пароля так же по ответу сервера можно понять что рендерить.
    Ответ написан
    Комментировать
  • Как массив строк превратить в объект?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const arr = ['utmTerm=java', 'utmTerm=javascript', 'utmTerm=swift'];
    const res = arr.reduce((acc, item) => {
        const [key, value] = item.split('=', 2);
        (acc[key] ??= []).push(value);
        return acc;
    }, {});
    console.log(res);
    Ответ написан
    Комментировать
  • Несколько языков в портфолио и как сделать выбор в направлении?

    bingo347
    @bingo347
    Crazy on performance...
    1. Стоит ли продолжать изучение front-end, если данное направление реально нравится или ситуация действительно такая, что там уже не нужны новые люди?
    Новых людей особо нигде не жалуют. Но пробиться всегда есть варианты:
    1. Большие компании иногда могут нанимать стажеров по абсолютно любым направлениям и обучать их. Работа будет больше рутинная, но для старта можно и потерпеть.
    2. Есть маленькие компании, у которых туго с деньгами, но разрабатывать им надо, соответственно нанимают того кто по карману. Развития здесь скорее всего не будет, но для первой строчки в резюме пойдет, если с 1 вариантом не получилось.

    2. Если уровень подготовки будет выше, чем описанные требования к джуну, то нормально ли будет подавать отклик на вакансии мидла или это плохой тон и мидл это не просто уровень знаний, но и обязательно опыт работы?
    Попробовать конечно можно, за попытку никто Вам ничего плохого не сделает.
    Но вообще джун-мидл-синьер - это вообще не про уровень знаний в программировании, это больше про софт скилы, которые приобретаются только с опытом работы. Условно я бы так разделил:
    Джун - умеет писать код под достаточно конкретные задачи, умеет гуглить если что-то не знает, умеет спросить если не сумел загуглить.
    Мидл - как джун + умеет декомпозировать более абстрактную задачу, при необходимости задать по ней правильные вопросы, умеет работать в команде (обсудить проблему, поревьювить чужой код, позаботиться чтоб собственный код был удобен остальным).
    Синьер - как мидл + умеет решать проблемы бизнеса с помощью кода.

    1. Делать простой бек для своих проектов на nodejs, чтобы проекты были более интересными и показывали мои навыки в js. Будет ли базовое знание nodejs плюсом для front-end разработчика?
    Будет, большинство инструментария написано на node и конфигурируется js кодом. Ну и уметь накидать себе заглушку на express пока нормальное api в разработке тоже будет плюсом.

    2. Как вообще поступить, если на данном этапе мне хочется попробовать себя в бекенде и подстраховаться на случай того, если не получится найти работу во front-end? Создать второй гитхаб и там выкладывать что-то на других языках или пока нахожусь на стадии обучения и выбора, то просто делать все в одном профиле и потом скрыть?
    Не заморачиваться и делать все в одном github. Лучше заморочиться тем как этот github оформлен, например сделать readme для профиля. Нормально оформлять коммиты. Не плодить кучу форков разных чужих проектов. Если есть форк чужого проекта, обязательно должен быть пул реквест туда, ну или хотя бы собственные коммиты в форке.

    3. Если я выберу nodejs и буду добавлять его к своим проектам, то нормально ли тогда будет подавать отклик и к фронт и к бек вакансиям?
    Нормально. Как и нормально изредка менять направление, а значит и не знать что больше по душе пока не работал. Нормально будет, если полгода-год поработали с одной технологией, а потом несколько лет с другой, но плохо, если менее чем за 2 года смените 3+ стэка.
    Я например начинал с php, через год ушел в node.js, еще через пару лет добавил фронт не убирая node.js, еще через 4 года добавил Rust.
    Ответ написан
    1 комментарий
  • Что такое signature и implementation?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Сигнатура функции - это по сути ее тип, который состоит из списка аргументов с типами и типа возвращаемого значения.
    Имплементация функции - это функция с телом.
    То есть следующие строки - это сигнатуры:
    function position(): MyPosition
    function position(a:number, b:number): MyPosition
    function position(a:number): MyPositionWithDefault

    Это тоже сигнатура: function position(a?: number, b?:number), но она так же является частью имплементации:
    function position(a?: number, b?:number) {
        if (!a && !b) {
            return {x: undefined, b: undefined}
        }
        if(a && !b) {
            return {x: a, b: undefined, default: a.toString()}
        }
        return {x: a, y: b}
    }


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

    Еще один важный момент для данного примера - это вывод типов. Если где-то тип не указать, то TS попробует его вывести, но делает он это весьма топорно - из первого значения которое будет присвоено переменной, ну и из первого return если речь идет о выводе возвращаемого значения функции.
    В Вашем случае TS выведет возвращаемое значение имплементации из следующей строчки: return {x: undefined, b: undefined}
    Тип такого значения будет:
    interface ReturnTypeOfPosition {
      x: undefined
      b: undefined
    }
    Проблема тут в двух вещах, во-первых в поле b вместо поля y, во-вторых в отсутствии поля default.
    Если исправить так:
    function position(): MyPosition
    function position(a: number, b: number): MyPosition
    function position(a: number): MyPositionWithDefault
    function position(a?: number, b?: number): MyPosition | MyPositionWithDefault {
        if (!a && !b) {
            return {x: undefined, y: undefined}
        }
        if(a && !b) {
            return {x: a, y: undefined, default: a.toString()}
        }
        return {x: a, y: b}
    }
    то все будет ок

    Ну и еще важный момент про перегрузки, TS использует в месте вызова ту перегрузку, которая первой подошла по аргументам, пробуя их в том порядке, как они записаны у Вас в коде, сверху вниз. Соответственно остальные типы в месте вызова будут выводится из данного факта.

    P.S. у меня в профиле есть ссылка на доклад по системе типов TS, про перегрузки там тоже есть. Система типов в TS полностью построена на математике множеств, если понять эту математику, то поймете и TS.
    Ответ написан
    2 комментария
  • Как отобразить процесс работы в терминале?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    setTimeout(function f(percent) {
        if (!process.stdout.isTTY) return;
        if (percent > 100) {
            process.stdout.write('\n');
            return;
        }
        const FILL = 9608;
        const SHADE = 9617;
        const progressSize = process.stdout.columns / 2;
        const fillSize = Math.ceil(progressSize * percent / 100);
        const shadeSize = Math.floor(progressSize) - fillSize;
        const fillText = String.fromCharCode(FILL).repeat(fillSize);
        const shadeText = shadeSize > 0
            ? String.fromCharCode(SHADE).repeat(shadeSize)
            : '';
        process.stdout.clearLine();
        process.stdout.write(`\r${fillText}${shadeText} ${percent}%`);
        setTimeout(f, 250, percent + 1);
    }, 100, 0);

    https://nodejs.org/dist/latest-v18.x/docs/api/tty.html
    https://unicode-table.com/en/blocks/block-elements/
    Ответ написан
    Комментировать
  • Как webpack собирает импорты и экспорты?

    bingo347
    @bingo347
    Crazy on performance...
    Есть 2 основных подхода для решения проблемы изоляции имен в модулях:
    - подход webpack до 4 версии включительно - завернуть каждый исходный модуль в свою функцию и переложить эту задачу на средства языка js;
    - подход rollup и последователей типа vite - произвести переименование сущностей так, чтоб разные сущности из разных модулей названные одинаково назывались по разному, а одни и те же сущности названные по разному в разных модулей назывались одинаково.

    У каждого из подходов есть свои плюсы и минусы.
    В подходе webpack с одной стороны получается очень надежная изоляция, так как работают средства самого языка, но с другой на выходе получается больше кода, так как добавляются обертки + некий рантайм для взаимодействия виртуальных модулей. Так же такой код хуже оптимизируется на постобработке, так как тулзы вроде terser банально не могут восстановить связи между разными модулями. Хотя тот же рантайм позволяет гибко разбивать код на чанки и эмулировать динамические импорты.
    В подходе rollup возможны ошибки на промежуточной обработке (сам rollup предусматривает большинство из них, а вот плагины могут накосячить, особенно на больших проектах), зато нет дополнительного кода и тулзы вроде terser могут обрабатывать весь бандл целиком со всеми межмодульными связями, а значит делать более эффективные оптимизации.

    В webpack 5 был использован гибридный подход. Модули все так же изолируются средствами языка и соединяются посредством рантайма. Но часть модулей могут быть соединены в один по принципу rollup, что улучшает общий размер бандла и оптимизацию на постобработке.

    P.S. сделайте небольшой проект из примерно 10 модулей, соберите его webpack/rollup в dev режиме и посмотрите что получается на выходе, очень многое станет понятно, если просто почитать код получившегося бандла.
    Ответ написан
    1 комментарий
  • Как скопировать текст из iframe в переменную js?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Если в iframe загружена страница с того же origin (протокол + домен + порт) откуда загружена текущая - то Вы имеете полный доступ к его window через свойство contentWindow. Соответственно можете обращаться к его DOM, глобальным переменным, менять их и т.д.

    Если в iframe будет страница с другого origin, то ничего этого нет, с ней можно лишь общаться через postMessage api, но если страница не Ваша, то и скрипт для обработки postMessage + каких-либо еще действий Вы туда не вставите.

    Если сторонний сайт отдает нормальные CORS заголовки при запросе с Вашего сайта (что судя по вопросу не так, но все же), то можно скачать страницу как текст через fetch api и распарсить ее через DOMParser.

    В противном случае остается только делать прослойку у себя на сервере, тут простор фантазии может быть очень широким, от банального reverse proxy прямо в nginx до чего-то более умного на любом серверном ЯП.
    Ответ написан
    Комментировать
  • Какой тип данных у переменной a?

    bingo347
    @bingo347
    Crazy on performance...
    У переменной a указан тип встроенный массив [T; n]. Но у такого типа нет метода get_unchecked_mut(). Он есть у среза на массив [T]
    Тут нужно понять как в Rust работает оператор точка.

    Во-первых, мало кто пишет, но операторов точка на самом деле в Rust целых 2:
    - Доступ к полю структуры/кортежа/юниона
    - Вызов метода
    Rust различает их по наличию круглых скобок:
    struct S {
        a: i32,
        f: fn(),
    }
    
    impl S {
        fn a(&self) {}
    }
    
    let s = S { a: 0, f: || {} };
    s.a; // Доступ к полю
    s.a(); // Вызов метода
    (s.f)(); // Вызов функции по указателю, который лежит в поле f

    С доступом к полю все просто, компилятор преобразует его в смещение в памяти где это поле лежит относительно самой структуры.
    А вот с вызовом метода все интереснее, Rust пытается рассахарить его в одну из следующих конструкций в следующем порядке:
    S::a(s);
    S::a(&s);
    S::a(&mut s);
    <S as Deref>::Target::a(S::deref(&s));
    <S as DerefMut>::Target::a(S::deref_mut(&mut s));
    <<S as Deref>::Target as Deref>::Target::a(<S as Deref>::Target::deref(S::deref(&s)));
    <<S as DerefMut>::Target as DerefMut>::Target::a(<S as DerefMut>::Target::deref_mut(S::deref_mut(&mut s)));
    // ...
    и так пока либо не найдет вариант, который компилируется, либо пока не обнаружит что для очередного типа не реализован трейт Deref.
    Подробнее можно почитать тут: https://doc.rust-lang.org/stable/nomicon/dot-opera...

    У всех массивов есть Deref к слайсу, в core библиотеке прописано что-то вроде:
    impl<T, const N: usize> Deref for [T; N] {
        type Target = [T];
        fn deref(&self) -> &[T] {
            // ...
        }
    }
    За счет этого все массивы (а так же векторы, у которых тоже Deref к слайсу) получают методы слайса. И по тому же принципу String получает методы str.

    Ну и кстати, неявный вызов deref может еще происходить при взятии ссылки.

    Ну и из комментов к вопросу:
    Что тут делает unsafe код как раз понятно
    Однозначно понятно, он здесь делает UB так как обращается к памяти владелец которой неизвестен.
    Ответ написан
    1 комментарий
  • Как подружить VS Code + Remote SSH + WSL?

    bingo347
    @bingo347
    Crazy on performance...
    Ваша проблема в том, то Вы абсолютно не понимаете как работает WSL. Давайте немного объясню.

    Начиная с WSL2 подсистема Linux крутится в полноценной виртуальной машине. И винда кстати тоже. Это работает следующим образом: когда Вы запускаете свой компьютер первой загружается на самом деле не винда, а гипервизор HyperV. Для пользователя происходит все прозрачно, так как HyperV настроен сразу запускать 2 виртуальные машины - с виндой и с линем. В машину с виндой HyperV сразу прокидывает все Ваши устройства (видеокарту, USB и прочее). Так же HyperV поднимает виртуальную сеть между этими двумя виртуалками. В машине с линем еще не Ваша Ubuntu, там легковесная ОС состоящая только из ядра и оркестратора LXC контейнерами (с ней кстати можно по взаимодействовать по сети, как это делает Docker Desktop например, ну или утилита wsl.exe). Ваша Ubuntu запускается в контейнере, так попросту быстрее ее запускать и останавливать, ибо ядро всегда висит в памяти. Опционально в линь монтируются папки (диски) из винды, делается это посредством патча ядра Linux от Microsoft. Обратный доступ предоставляется из винды посредством сетевого ресурса wsl$.
    Главное что тут стоит понять - винда и линь в WSL по сути работают на разных компах, пусть и виртуальных.

    Теперь ответьте на вопрос, на каком из этих компов работает Ваш VSCode?
    Правильный ответ на винде. А значит и взаимодействовать он будет с виндой. И искать ключи для подключения к ssh будет в домашней папке юзера в винде.

    Можете просто скопировать ключи из линя на винду и все заработает.
    Ответ написан
    2 комментария