2017-11-06 10 views
1
entlehnt

Ich habe 2 Funktionen:Kann nicht `self.x` zuweisen, da es

// A simple struct 
struct S { 
    w: u8, 
    h: u8, 
    x: Vec<u8>, 
    y: Vec<u8>, 
} 

// Implementation of the struct S 
impl S { 
    // Seems to work 
    fn new(_w: u8, _h: u8, _x: &Vec<u8>, _y: &Vec<u8>) -> S { 
     S { 
      w: _w, 
      h: _h, 
      x: _x.clone(), 
      y: _y.clone(), 
     } 
    } 

    fn calc(&mut self) { 
     let mut min_x = self.x.iter().min().unwrap(); 
     let mut max_x = self.x.iter().max().unwrap(); 
     let mut min_y = self.y.iter().min().unwrap(); 
     let mut max_y = self.y.iter().max().unwrap(); 

     // Here's the line that gives the error 
     self.x = self.x 
      .iter() 
      .map(|v| norm_value(*v, *min_x, *max_x, 0, self.w)) 
      .collect(); 
    } 
} 

fn norm_value<A, B, C, D, E>(_: A, _: B, _: C, _: D, _: E) -> ! { panic!() } 
  1. new macht ein neues S Objekt. Dies scheint zu funktionieren, aber korrigieren Sie mich, wenn ich etwas schrecklich falsch gemacht habe und gerade passiert, um zu arbeiten.

  2. calc versucht, die Mitglieder x und y zu ändern.

Der Compiler meldet diesen Fehler:

error[E0506]: cannot assign to `self.x` because it is borrowed 
    --> src/main.rs:28:9 
    | 
22 |   let mut min_x = self.x.iter().min().unwrap(); 
    |       ------ borrow of `self.x` occurs here 
... 
28 |/  self.x = self.x 
29 | |    .iter() 
30 | |    .map(|v| norm_value(*v, *min_x, *max_x, 0, self.w)) 
31 | |    .collect(); 
    | |______________________^ assignment to borrowed `self.x` occurs here 

Wo habe ich self.x ausleihen? Ich bin neu in Rust, aber solche Dinge machen keinen Sinn.

Antwort

2

Alle der Variablenbindungen zu Beginn der calc Rückkehr Referenzen geteilt (&u8) zu self.x und self.y, was bedeutet, dass Sie nicht mehr, sie mutieren können.

Um nicht durch diese leiht an dem Punkt der letzten Zuweisung gebunden zu sein, um die Referenzen clone() können regelmäßig u8 s zu erhalten:

let mut min_x = self.x.iter().min().unwrap().clone(); 
let mut max_x = self.x.iter().max().unwrap().clone(); 
let mut min_y = self.y.iter().min().unwrap().clone(); 
let mut max_y = self.y.iter().max().unwrap().clone(); 

Ich bin mir nicht sicher, ob dies alle Ihre Fragen löst, weil Sie die Signatur nicht angegeben haben.

Was die new Methode, werden Sie wahrscheinlich wollen die Signatur ändern, um sie von Wert zu erhalten, anstatt durch Verweis:

fn new(w: u8, h: u8, x: Vec<u8>, y: Vec<u8>) -> S { 
    S { w: w, h: h, x: x, y: y } 
} 

let s = S::new(10, 10, vec![1, 2, 3, 4], vec![52, 10, 23, 56]); 

Bitte beachte, dass ich die Unterstrichen entfernt - Sie müssen nicht vorangestellt wird Die Funktionsargumente mit ihnen, wenn Sie sie entfernen, wird es dem Compiler immer noch klar sein. Das Voranstellen variabler Bezeichner mit Unterstrichen wird normalerweise zum Stummschalten der #[warn(unused_variables)] Warnungen verwendet.

+0

Tatsächlich funktioniert das. Also, wenn ich es richtig verstehe: 'min(). Unwrap()' gibt einen Verweis auf ein Element von 'self.x' zurück, was bedeutet, dass das gesamte' self.x' entlehnt ist (oder nur ein einzelnes Element? (Min)). Schließlich kopiert 'clone()' den referenzierten Wert und gibt die Referenz frei? – DimChtz

+0

@DimChtz 'iter()' gibt einen Iterator über unveränderliche Referenzen zurück und borgt das ganze 'self.x' oder' self.y' (aber nicht das ganze 'self').' Min(). Unwrap() 'gibt das zurück Verweis auf das kleinste Element; es verbraucht den Iterator, behält aber den Kredit in Kraft. 'clone()' erhält den referenzierten Wert und gibt den Borrow frei, yes. – ljedrz

+0

Dinge wie diese lassen mich das Gefühl haben, Rost ist durcheinander, aber ich mag immer noch Rost: P Wie auch immer, danke. – DimChtz

Verwandte Themen