2015-11-09 4 views
5

Dieser Code korrekt kompiliert. Es hat ein paar ungenutzte Code-Warnungen, aber das ist in Ordnung für jetzt.Wann und wie ein Vektor von Referenzen verwenden

use std::collections::BTreeMap; 

enum Object<'a> { 
    Str(String), 
    Int(i32), 
    Float(f32), 
    Vector(Vec<&'a Object<'a>>), 
    Prim(fn(State) -> State) 
} 

struct State<'a> { 
    named: BTreeMap<String, &'a Object<'a>>, 
    stack: Vec<Object<'a>> 

} 

impl<'a> State<'a> { 
    fn push_int(&mut self, x: i32) { 
     self.stack.push(Object::Int(x)); 
    } 
} 


fn main() { 
    println!("Hello, world!"); 
    let obj = Object::Str("this is a test".to_string()); 
} 

Der wichtige Teil dieses Codes ist push_int und stack: Vec<Object<'a>>.

Ich versuche irgendwie einen Stack-basierten VM zu machen. Ich möchte den Status an Funktionen übergeben, die Material vom Stapel nehmen, das Zeug manipulieren und dann etwas zurück auf den Stapel legen können; Das benannte Feld wird benannte Objekte enthalten.

Ich habe das Gefühl, dass es besser wäre, den Stapel als stattdessen Vec<&'a Object<'a>> dargestellt zu haben. So wie ich es jetzt habe, befürchte ich, dass ich einen Ineffizienzfehler begehe. Ist meine Ahnung richtig?

Der zweite Teil des Problems ist, dass ich weiß nicht, wie der Vektor der Referenzen Version erhalten zu arbeiten. Einen neuen Wert mit den richtigen Lebensdauern zu erstellen, um auf den Stapel zu drücken, funktioniert nicht für mich.

Ich bin ein bisschen vage über dieses Thema, also wenn ich unklar waren, fragen Sie mich Fragen Sachen zu klären.

+0

Sie möchten 'Vec >>' für einen eigenen Zeiger.Sie haben Ineffizienz, da "Object :: Int" so viel Platz benötigt wie "Object :: String", aber das Boxen wird es nur noch schlimmer machen (selbst wenn das Boxen kompaktere Darstellungen erlaubt). Ich würde einfach 'Str (String)' zu 'Str (Box )' und 'Vector >' zu 'Vector >>' ändern und es belassen, da das die einzigen Dinge entfernt, die 'Objekt' * auch behalten * groß. Es ist jedoch immer noch möglich, dass die zusätzliche Indirektion für kleinere (wahrscheinlich gebräuchlichere) Werte schlechter ist als die Ineffizienz. – Veedrac

+1

was meinst du mit "ineffizienz"? Fragen Sie, wie Sie Speicher sparen oder leistungsfähiger werden? Auch ich denke, diese Frage gehört auf http://codereview.stackexchange.com/ –

+0

@ker Ich denke, ich meinte beides; Ich war vage, weil ich nicht genug wusste, um genauer zu sein. Ja, es hätte zur Codereview gehen können; Ich war mir nicht sicher. – phil

Antwort

6

Der Grund, warum Sie es nicht funktionieren könnte, ist, dass structs keine Felder haben kann, die auf andere Bereiche beziehen. (Siehe Links unten zu unterstützen.)

Was Sie tun können, ist gesetzt, alle Object s in Ihrem Vec und haben die HashMap die Indizes der genannten Elemente enthalten sie verweist.

struct State { 
    named: BTreeMap<String, usize>, 
    stack: Vec<Object> 
} 

Ich würde auch alle Lebensdauern von Ihrem Beispiel entfernen, da dies vollständig mit eigenen Objekten durchgeführt werden kann.

enum Object { 
    Str(String), 
    Int(i32), 
    Float(f32), 
    Vector(Vec<Object>), 
    Prim(fn(State) -> State) 
} 

Sie können in den Playground

Unterstützung Links, um eine funktionierende Implementierung ausprobieren:

+2

Ein Style-Point in Bezug auf "(ja, jedes Wort ist ein anderer Link)". Eine Aufzählungsliste mit Links zu anderen Stack Overflow-Fragen ist übersichtlicher, da SO die Titel automatisch nachschlägt und anzeigt. –

Verwandte Themen