2016-11-26 3 views
0

den folgenden Code Given (die noch nicht viel tun):Nicht übereinstimm Typen für zurückgegebene Struktur (erwartete <K, V>, gefunden <&K, &V>)

use std::collections::BTreeMap; 
use std::iter::FromIterator; 

trait Node<K, V> { 
    fn split(&self) -> Split<K, V>; 
} 

#[derive(Debug, Copy, Clone)] 
pub struct Config { 
    data_b: usize, 
} 

struct Split<'a, K, V> { 
    left: Box<Node<K, V> + 'a>, 
    right: Box<Node<K, V> + 'a>, 
} 

#[derive(Debug)] 
pub struct DataNode<K, V> { 
    cfg: Config, 
    children: BTreeMap<K, V>, 
} 

impl<K: Clone + Ord, V: Clone> Node<K, V> for DataNode<K, V> { 
    fn split(&self) -> Split<K, V> { 
     let data_b = self.cfg.data_b; 

     Split { 
      left: Box::new(DataNode { 
       cfg: self.cfg.clone(), 
       children: BTreeMap::from_iter(self.children.iter().take(data_b)) 
      }), 
      right: Box::new(DataNode { 
       cfg: self.cfg.clone(), 
       children: BTreeMap::from_iter(self.children.iter().rev().take(data_b)) 
      }), 
     } 
    } 
} 

Der Compiler gibt die folgenden Fehler:

error[E0308]: mismatched types 
    --> lib.rs:68:9 
    | 
68 |   Split { 
    |  ^expected type parameter, found &K 
    | 
    = note: expected type `Split<'_, K, V>` 
    = note: found type `Split<'_, &K, &V>` 

Ich bin ziemlich neu in Rust, also bin ich mir nicht sicher, was das verursacht. Um absolut klar zu sein, die Frage, die ich habe, ist nicht über was die Fehlermeldung bedeutet. Natürlich bedeutet das, dass ich nicht den richtigen Typ zurückgebe. Die Frage ist warum interpretiert der Compiler diesen Code Split {...} als Code, der Split<'_, &K, &V> zurückgibt, wenn ich erwarte, dass es Split<'_, K, V> ist. Jeder Einblick wird geschätzt.

+0

Verstehen Sie [* welche Referenzen *] (https://doc.rust-lang.org/stable/book/references- und-borrowing.html)? Verstehst du, wie ['BTreeMap :: iter'] (https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.iter) funktioniert? IMO, die Fehlermeldung ist ziemlich einfach - Sie haben gesagt, Sie werden eine Sache zurückgeben, aber Sie haben etwas anderes zurückgegeben. Welche Information fehlt uns, die wir weiter klären können? – Shepmaster

+0

Ich habe nicht gesagt, ich habe die Fehlermeldung nicht verstanden. Was ich nicht verstehe, ist * warum * was ich geschrieben habe, ergibt 'Split <'_, &K, &V>'. Wenn es etwas mit einer Subtilität zu tun hat, die mit der Verwendung eines Iterators einhergeht, dann ist das ja jenseits meines Rust-Wissens und ich würde mich über einige Einsichten freuen. Das Beste, was ich tun konnte, bevor ich hierher kam, war zu überprüfen, dass Rückgabetypen von allem, aber nichts darauf hinweisen, dass Referenzen ins Spiel kommen würden. Irgendwie fühlt sich der Compiler irgendwie gezwungen, dies zu tun, und ich würde gerne verstehen, warum und wie ich bekommen kann, was ich will, wenn das möglich ist. – neverfox

Antwort

2

Die Referenzen stammen von wo aus man auf das Kind durchlaufen ein neues BTreeMap zu bauen:

type Item = (&'a K, &'a V) 

dh die Iterator zurückkehrt:

BTreeMap::from_iter(self.children.iter().take(data_b)) 

Wenn man sich die iterator returned by BTreeMap::iter(), die Item Typ aussehen Paare von Referenzen auf den Inhalt. Dies ist sinnvoll, weil Sie beim Iterieren keine Elemente aus der Map verschieben oder sich auf Copy verlassen möchten.

Dies ist etwas anders als z.B. Vec::iter(), wobei es sich um ein Referenzpaar handelt und nicht um einen Verweis auf ein Paar. Dies ist sinnvoll, da ein Verweis auf ein Paar bedeuten würde, dass der Container diese Paare intern enthalten müsste (Einschränkung der internen Datenstruktur).

Die einfachste Sache ist, den Schlüssel und Wert zu klonen:

BTreeMap::from_iter(self.children.iter() 
           .map(|(&a, &b)| (a.clone(), b.clone())) 
           .take(data_b)) 
+0

Danke für die klare Erklärung und den Hinweis auf eine mögliche Lösung. Du hast Recht, dass es Sinn ergibt. Ich habe nach Typen in all den verschiedenen Methoden gesucht, die ich verwendet habe, aber ich wurde von der Dokumentation irregeführt, indem ich sagte: "Fn iter (& self) -> Iter ", also kratzte ich mich am Kopf. Jetzt weiß ich, wo ich hätte hinschauen sollen. – neverfox

+1

Ich mache eine Menge durchklicken Arten in der Online-Dokumentation! Du lernst alle möglichen Dinge. –

Verwandte Themen