Ответы пользователя по тегу Rust
  • Использовать String или &str?

    keksmen
    @keksmen
    Just a programmer
    Решение тут не вполне однозначное.

    С одной стороны, гораздо эффективнее было бы таскать ссылки (&str), т.к. их копирование или извлечение ссылки на subslice весьма дёшево. Это позволит создавать и отбрасывать структуры при синтаксическом разборе без оглядки на overhead от владения String.

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

    В любом случае, я бы порекомендовал использовать &str. Однако, без кода подсказать, как лучше сохранить исходный String до конца обработки запроса, я не смогу.
    Ответ написан
    Комментировать
  • Выделяется ли память при создание &str?

    keksmen
    @keksmen
    Just a programmer
    Тут есть немного недопонимания. Под выделением памяти обычно подразумевают её выделение в динамической памяти, в то время как переменные и аргументы живут в стековой памяти.

    А теперь, отвечая на ваш вопрос:
    • Да, &str - это действительно лишь адрес байтов и длина среза, на который адрес ссылается.
    • Нет, динамическая память при этом не выделяется, т.к. хранение на стеке предсказуемо, однозначно и достаточно для этого случая.
    Ответ написан
    Комментировать
  • Вопрос про владение в Rust, что не так?

    keksmen
    @keksmen
    Just a programmer
    Дело в том, что, как и сказал компилятор, вы пытаетесь использовать значение после его перемещения.
    Рассмотрим участок кода.
    // умножаем  слой на предыдущую  матрицу
    buf = v.mat_mul(&buf);
    // результат записываем в вектор 
    result.push(buf);

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

    Отвечая на ваш второй вопрос: да, клонирование - то, что вам нужно использовать в данном случае.
    // умножаем  слой на предыдущую  матрицу
    buf = v.mat_mul(&buf);
    // результат записываем в вектор 
    result.push(buf.clone());


    Однако, клонирование - операция дорогая. Учитывая, что для умножения нужна всего-лишь иммутабельная ссылка на матрицу, мы можем переписать код следующим образом:
    // вектор, где будут хранится  произведения матриц
    let mut result = vec![];
    
    for v in layers {
    	// пытаемся достать предыдущую матрицу
    	let previous_matrix = match result.last() {
    		Some(last) => last,
    		// а если таковой нет - ей станет входная
    		None => &input,
    	};
    	// умножаем  слой на предыдущую (или входную) матрицу
    	let next_matrix = v.mat_mul(previous_matrix);
    	result.push(next_matrix);
    }


    Метод Vec::<T>::last возвращает Option<&T>, которая содержит ссылку на последний элемент ветора, если таковой существует. Его сложность O(1), поэтому по поводу ухудшения производительности можно не беспокоиться.
    Это именно то, для чего и создавалась переменная-буфер. Теперь нам не нужно производить лишнее клонирование.
    Ответ написан
    1 комментарий
  • Почему условие не работает?

    keksmen
    @keksmen
    Just a programmer
    Дело в том, что вот этот участок
    for k in 0..z
    определяет итерацию от 0 до z-1. Поэтому, k никогда не равно z.
    Если нужна итерация от 0 до z, вам стоит использовать следующий синтаксис:
    for k in 0..=z
    Ответ написан
    Комментировать