Also this approach uses more memory. At least a byte per pointer and maybe more with padding. In most cases like this you would prefer to use a vtable instead of tags to reduce the memory footprint.
Eric On Mar 13, 2014, at 1:17 PM, Eric Summers <eric.summ...@me.com> wrote: > 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
_______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev