Передать право собственности во вложенном цикле

Я пытаюсь реализовать сито эратосфенов, оно находит все пирмы ниже n, создавая массив, перебирая этот массив и всякий раз, когда обнаруживается простое число, отмечая все кратные этого простого числа как непростые.

Мой код для шага маркировки:

for (index, val) in is_prime[3..marking_lim].iter_mut().step_by(2).enumerate() {     // borrow of is_prime
    if *val == true {
       primes_found.push(index as i32);           // add the prime to the list
       n_found += 1;                               // counter for primes found, cannot be exceeded in this step
       for val_2 in is_prime[index..(up_to_nth as usize)].iter_mut().step_by(index) {   // second borrow of is_prime
            *val_2 = false;
        }
    }
}

Однако это не работает, так как внутренний цикл принимает изменяемое заимствование is_prime, в то время как он все еще заимствован внешним циклом. Поэтому мне нужно каким-то образом передать право собственности на заимствование внутреннему циклу, чтобы он мог отмечать кратные значения. Как мне это сделать?

Зачем нужен изменяемый итератор?

AspectOfTheNoob 11.01.2023 00:57

Вместо того, чтобы перебирать значения в is_prime во внешнем цикле, вы можете просто перебирать индексы (for index in (3..marking_lim).step_by(2)) и заимствовать is_prime только при необходимости, извлекая val через индекс (is_prime[index]). Тогда вы сможете свободно заимствовать is_prime во внутреннем цикле.

EvilTak 11.01.2023 01:05

@AspectOfTheNoob, потому что я изменяю значения. смотри строчку *val_2 = false

Pioneer_11 11.01.2023 01:08

@ Pioneer_11 Но вы не изменяете val из внешнего цикла.

Chayim Friedman 11.01.2023 03:33

@ChayimFriedman да. Однако из-за системы заимствования Rust «много неизменяемых или один изменяемый» невозможно превратить неизменяемую ссылку в изменяемую ссылку. Однако можно передать право собственности на изменяемую ссылку от одной переменной к другой fn main() { let mut test_arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let a = &test_arr; let b = &mut a; } <-- недопустимо, не компилируется fn main() { let mut test_arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let a = &mut test_arr; let b = a; b[2] += 10; println!("{:?}", b) } <- компилируется

Pioneer_11 11.01.2023 07:08

Я не понимаю, как это связано. Почему нельзя использовать iter() для внешнего цикла?

Chayim Friedman 11.01.2023 07:12

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

Pioneer_11 12.01.2023 06:31
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
Запуск PHP на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Настройка шаблона Metronic с помощью Webpack и Gulp
Настройка шаблона Metronic с помощью Webpack и Gulp
Я пишу эту статью, чтобы поделиться тем, как настроить макет Metronic с помощью Sass, поскольку Metronic предоставляет так много документации, и они...
0
7
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Невозможно сделать именно то, что вы просите. Самое простое решение — избегать заимствования is_prime во внешнем цикле:

for (index, index_2) in (3..marking_lim).step_by(2).enumerate() {
    if is_prime[index_2] {
        // ...

Более причудливое решение — использовать std::cell::Cell, что позволяет изменять элементы массива с помощью ссылки, отличной от mut:

use std::cell::Cell;

let is_prime = Cell::from_mut(&mut is_prime[..]).as_slice_of_cells();

for (index, val) in is_prime[3..marking_lim].iter().step_by(2).enumerate() {
    if val.get() {
        primes_found.push(index as i32);
        n_found += 1;
        for val_2 in is_prime[index..(up_to_nth as usize)].iter().step_by(index) {
            val_2.set(false);
        }
    }
}

Спасибо, я предполагаю, что ячейка - это какой-то контейнер с подсчетом ссылок?

Pioneer_11 13.01.2023 12:49

Brian Bowman 13.01.2023 19:26

Другие вопросы по теме