Matthieu, I tried to model something similar this way. Sometimes the extra pattern matching gets tedious with this approach. You also end up with a lot of constructors with similar names. I also found myself writing a lot of trivial function wrappers around constructors. Of course there are benefits to a non-extensible system like this. For instance, you can tell if you have addressed every case in a match statement.
Someone on IRC mentioned that a feature similar to Haskell pattern synonyms may make it less awkward to use these enum wrappers. Eric On Mar 13, 2014, at 12:56 PM, Matthieu Monrocq <matthieu.monr...@gmail.com> wrote: > And of course I forgot to reply to the list at large... sorry :x > > -- Matthieu > > > On Wed, Mar 12, 2014 at 8:48 PM, Matthieu Monrocq > <matthieu.monr...@gmail.com> wrote: > > > > On Tue, Mar 11, 2014 at 10:18 PM, Patrick Walton <pcwal...@mozilla.com> wrote: > On 3/11/14 2:15 PM, Maciej Piechotka wrote: > Could you elaborate on DOM? I saw it referred a few times but I haven't > seen any details. I wrote simple bindings to libxml2 dom > (https://github.com/uzytkownik/xml-rs - warning - I wrote it while I was > learning ruby) and I don't think there was a problem of OO - main > problem was mapping libxml memory management and rust's one [I gave up > with namespaces but with native rust dom implementation it would be > possible to solve in nicer way]. Of course - I might've been at too > early stage. > > You need: > > 1. One-word pointers to each DOM node, not two. Every DOM node has 5 pointers > inside (parent, first child, last child, next sibling, previous sibling). > Using trait objects would 10 words, not 5 words, and would constitute a large > memory regression over current browser engines. > > 2. Access to fields common to every instance of a trait without virtual > dispatch. Otherwise the browser will be at a significant performance > disadvantage relative to other engines. > > 3. Downcasting and upcasting. > > 4. Inheritance with the prefix property, to allow for (2). > > If anyone has alternative proposals that handle these constraints that are > more orthogonal and are pleasant to use, then I'm happy to hear them. I'm > just saying that dismissing the feature out of hand is not productive. > > > Patrick > > > Please excuse me, I need some kind of visualization here, so I concocted a > simple tree: > > // So, in pseudo C++, let's imagine a DOM tree > struct Element { Element *parent, *prevSib, *nextSib, *firstChild, > *lastChild; uint leftPos, topPos, height, width; bool hidden; }; > struct Block: Element { BlockProperties blockP; }; struct Div: Block {}; > struct Inline: Element { InlineProperties inlineP; }; struct Span: Inline {}; > > > Now, I'll be basically mimicking the way LLVM structures its AST, since the > LLVM AST achieves dynamic casting without RTTI. Note that this has a very > specific downside: the hierarchy is NOT extensible. > > // And now in Rust (excuse my poor syntax/errors) > enum ElementChild<'r> { ChildBlock(&'r Block), ChildInline(&'r Inline) } > > struct Element { > child: Option<&'self ElementChild<'self>>; > parent: &'self Element; > prevSib, nextSib, firstChild, lastChild: Option<&'self Element>; > leftPos, topPos, height, width: uint; > hidden: bool; > } > > > enum BlockChild<'r> { ChildDiv(&'r Div) } > > struct Block { > elementBase: Element; > child: Option<&'self BlockChild<'self>>; > blockP: BlockProperties; > } > > struct Div { blockBase: Block; } > > > enum InlineChild<'r> { ChildSpan(&'r Span) } > > struct Inline { > elementBase: Element; > child: Option<&'self InlineChild<'self>>; > inlineP: InlineProperties; > } > > struct Span { inlineBase: Inline; } > > > Let us review our objectives: > > (1) One word to each DOM element: check => Option<&'r Element> > > (2) Direct access to a field, without indirection: check => > span.inlineBase.elementBase.hidden > > (3) Downcast and upcasting: check => downcast is done by matching: > match(element.child) { ChildBlock(&'r block) => /* act on block */, > ChildInline(&'r inline) => /* act on inline */); upcast is just accessing the > "base" field. > > (4) Inheritance with the prefix property => not necessary, (2) is already > satisfied. > > > Note on (3): multiple bases are allowed easily, it's one field per base. > > > In order to reduce the foot-print; avoiding having a "child" field at each > level of the hierarchy might be beneficial. In this case, only the final > classes are considered in ElementChild > > enum ElementChild<'r> { ChildDiv(&'r Div), ChildSpan(&'r Span) } > > And then downcasting to &'r Block is achieved by: > > match(element.final) { ChildDiv(&'r div) => Some(&'r div.blockBase), _ => > None } > > > I would note that this does not make use of traits at all; the analysis is > only based on Patrick's list of objectives which I guess is incomplete and I > was lacking a realistic example so it might not address the full scope of the > problem... > > ... still, for CLOSED hierarchies, the use of traits should not be necessary, > although it might be very convenient. > > -- Matthieu. > > _______________________________________________ > Rust-dev mailing list > Rust-dev@mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > > _______________________________________________ > Rust-dev mailing list > Rust-dev@mozilla.org > https://mail.mozilla.org/listinfo/rust-dev
_______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev