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