BigUint и ошибка «не может выйти из заимствованного контента» - PullRequest
0 голосов
/ 21 мая 2018

Я пытался следовать подходу итератора, описанному в Rust в разделе Итератора примера с BigUint:

extern crate num_bigint;

use num_bigint::{BigUint, ToBigUint};

struct FibState {
    a: BigUint,
    b: BigUint,
}

impl Iterator for FibState {
    type Item = BigUint;
    fn next(&mut self) -> Option<BigUint> {
        let b_n = self.a + self.b;
        self.a = self.b;
        self.b = b_n;
        Some(self.a)
    }
}

fn fibs_0() -> FibState {
    FibState {
        a: 0.to_biguint().unwrap(),
        b: 1.to_biguint().unwrap(),
    }
}

fn fib2(n: usize) -> BigUint {
    if n < 2 {
        n.to_biguint().unwrap()
    } else {
        fibs_0().skip(n - 1).next().unwrap()
    }
}

fn main() {
    println!("Fib1(300) = {}", fib2(300));
}

Приведенный выше код не компилируется:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:13:19
   |
13 |         let b_n = self.a + self.b;
   |                   ^^^^ cannot move out of borrowed content

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:13:28
   |
13 |         let b_n = self.a + self.b;
   |                            ^^^^ cannot move out of borrowed content

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:14:18
   |
14 |         self.a = self.b;
   |                  ^^^^ cannot move out of borrowed content

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:16:14
   |
16 |         Some(self.a)
   |              ^^^^ cannot move out of borrowed content

Я не уверен, что это из-за того, что тип BigUint не является примитивным, поэтому у него нет черты Copy.Как я могу изменить итератор, чтобы он работал со структурой FibState?

1 Ответ

0 голосов
/ 21 мая 2018
fn next(&mut self) -> Option<BigUint> {
    let b_next = &self.a + &self.b; 
    let b_prev = std::mem::replace(&mut self.b, b_next);
    self.a = b_prev;
    Some(self.a.clone())
}
  1. BigUint не реализует Copy, но черта Add принимает оба аргумента по значению.BigUint также реализует Add для ссылок, так что вы можете вместо этого взять ссылки на значения.

  2. Мы хотели бы заменить текущее значение b следующим значениемb, но нам нужно сохранить старое значение.Для этого можно использовать mem::replace.

  3. Присвоить старое значение b a просто.

  4. Теперь мы хотим вернуть значение в a, поэтому нам нужно clone всего значения.

BigUintТип не является примитивным, поэтому он не имеет черты Copy

Что-то, что является примитивом, а что-то реализующее черту Copy, не имеет ничего общего друг с другом.Пользовательские типы могут реализовывать Copy, а некоторые примитивы не реализуют Copy.

См. Также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...