• Вопрос про владение в 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 комментарий
  • Обобщения. Как возвести в квадрат элементы в векторе?

    ozkriff
    @ozkriff
    Rust э̶н̶т̶у̶з̶и̶а̶с̶т сектант, хобби игродел
    Если ты хочешь изменять внешний массив, то его надо принимать по `&mut` ссылке. `mut input:Vec` аргумент будет передан просто перемещением, `mut` сделает его изменяемым только внутри функции (аналогично с обычными `let mut` объявлениями).

    Если ты хочешь присвоить результат обобщенного умножения переменной типа T, то надо явно потребовать у типажа умножения Output соответвующего типа: `Mul`.

    Так же, если ты хочешь использоват разыменования (`*`), надо потребовать типаж `Copy`.

    use std::ops::Mul;
    
    fn square_elements<T: Mul<Output=T> + Copy>(data: &mut [T]) {
        for i in data.iter_mut() {
            *i = *i * *i;
        }
    }
    
    fn main() {
        let mut v: Vec<f64> = vec![0.10, 20.60, 17.7];
        println!("before: {:?}", v);
        square_elements(&mut v);
        println!("after: {:?}", v);
    }


    playground
    Ответ написан
    Комментировать
  • Почему выходит паника - panicked at 'panicked at 'index out of bounds: the len is 0 but the index is 0'?

    john36allTa
    @john36allTa
    alien glow of a dirty mind
    Вектор проинициализирован, но память не выделена. Сделайте так:
    let mut matrix_c = vec![type;size];
    Ответ написан
    1 комментарий
  • Почему выходит паника - panicked at 'panicked at 'index out of bounds: the len is 0 but the index is 0'?

    bingo347
    @bingo347
    Crazy on performance...
    У вас вектор matrix_c изначально пустой, Вы пытаетесь писать в несуществующий элемент.
    Вижу, что у Вас закоменчен вариант с методом push (почему он Вам не подошел не знаю).
    Как вариант можно сразу создать вектор нужного размера, заполненный значениями по умолчанию (например нулями):
    // добавлю пару констант, для простоты модификации
    let rows = 2;
    let cols = 2;
    
    let matrix_a =  vec![1,2,3,4];
    let matrix_b =  vec![5,6,7,8];
    let mut  matrix_c = vec![0; rows * cols]; // 0 - default, rows * cols - размер (4)
    
    for row in 0..rows {
      for col in 0..cols {
        let mut vec_buf = 0;
        for k in 0..2 {
          vec_buf = vec_buf + matrix_a[row * 2 + k] * matrix_b[k * 2 + col];
        }
        matrix_c[row * 2 + col] = vec_buf; // теперь должно быть все ок
                             // так как спокойно передаем владение существующему элементу вектора
      }
    }
    
    
    for (i, x) in matrix_c.iter().enumerate(){
      println!(" элем = {:?}, значение = {:?}", i, x);
    }
    Ответ написан
    1 комментарий