On 16.11.2010 14:40, spir wrote:
On Tue, 16 Nov 2010 05:37:52 -0500
bearophile<bearophileh...@lycos.com>  wrote:

spir:

(and bug-prone, because sometimes the absence of a fields seems not caught, for 
any reason), so I add fields to the top type.
What do you mean? Do you have an example?
(Adding fields to the top type doesn't look like a good idea, generally).

Bye,
bearophile
For instance, I have 2 sub-classes of nodes: one leaf kind with element (here 
called slice), one branch kind with an array of (child) nodes. They are 
exclusive, and none of the data fields should appear on the top Node type. But 
everywhere the Node class must be used, since a branch (as the top tree) can 
indifferently hold leaves or sub-branches, right?
Each time I need to post-process results, since I apparently get Nodes (even if 
I know they are actually of one or the other type), I would first have to 
down-cast each node to the proper kind before doing anything. Else, I would get 
compiler errors, or plain bugs, for not having the proper field. So, I ended up 
setting fake fields on Node (and remove them from the sub-classes). And yes, I 
agree it's A Bad Thing to do. Just tell me of an elegant solution, and I apply 
it at once.

Looks like a good question for D.learn.
That's what opApply is made for. Namely: internal iteration.

Idea - basically what you need is apply some block of code (delegate) on each element.
If you provide in your node-like classes function opApply with signature:
int opApply(int delegate(ref A)); //where A is your data-type

foreach(a; node){
    writeln(a);//here a is element of data not Node or some such
}

Is rewritten as
node.opApply((ref a){ writeln(a); return 0;});
compiler rewrites code with breaks and so on to return 1, while at the normal end of flow to return 0

To get that idea better, try this example program

import std.stdio;
class Node{
    abstract int opApply(int delegate(ref int));
}
class Leaf: Node{
    this(int _data){
        data = _data;
    }
    int data;
    int opApply(int delegate(ref int) dg){
        return dg(data);
    }
}
class Branch: Node{
    Node[] nodes;
    this(Node[] _nodes...){
        nodes = _nodes.dup;
    }
    int opApply(int delegate (ref int) dg){
        Node[] n = nodes;
        while(n.length){
            int result = n[0].opApply(dg);
            if(result) return result; ///to handle breaks
            n = n[1..$];
        }
        return 0;
    }
}
void main(){
    Branch b = new Branch(new Leaf(17), new Leaf(19));
    Node n = new Branch(new Leaf(10),new Leaf(20),b);
    foreach(val;n){
        if(val == 17)//try playing around with break
            break;
        writeln(val);

    }

}

Also check the section 12.10 in TDPL if you have one, it goes in great detail about it.
Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com



--
Dmitry Olshansky

Reply via email to