A Class in Composition

Chris wendlec at tcd.ie
Tue Aug 27 07:13:24 PDT 2013


I had a very simple method that would read a text file, parse it 
and create a lexicon of the type string[string].

public void loadLexicon(ref string[string] lex, string src)

It was high time I made the method more sophisticated and 
flexible (allowing for comments in the source file, checking for 
formatting errors etc). Because neither the comment bit (C-style 
line comments "//") nor the formatting check are too demanding I 
decided to do it in the existing loop that looked something like:

while (file.readln(buf)) {
   line = to!string(buf);
   // Do something with line
}

Soon, very soon indeed, I ran into all the problems associated 
with loops, which basically boils down to "Where the f.. am I 
now?". So I said to myself that component programming was the 
perfect fit for this kind of problem. I rearranged the program 
and now I have one line in the function that does the job:

public void loadLexicon(ref string[string] lex, string src) {
   // ...
   // arr is of type string[] and holds the lines of the source 
file.
   auto dictionary = Lexicon(); // The output range
   lex = arr.byCommentFilter().byEntry().copy(dictionary).lexicon;
}

It's very nice indeed. The beauty of it is not only that I now 
have a nice, sequentially ordered "one-liner", the outsourcing of 
checks and filters freed my head from the loop logic, which 
helped me to focus on the respective algorithms. This lead to a 
leaner and cleaner implementation of each algorithm, because 
there are no dependecies on loop conditions or the position in 
the loop.

I could easily remove the comment filter, if the deployment 
version of the program ships with tidied up source files, or I 
could add a new component if necessary. In a loop, however 
trivial it may appear at first glance, it would not be so simple 
to add or remove parts of the logic.

One drawback is, that using ranges creates some overheads and 
code duplication. But the neatness of it is amazing, and I 
daresay that a lot of bugs are hidden in loops simply because the 
loop logic distracts and confuses the programmer and bugs finally 
find loopholes they can slip through.

Another drawback is that ranges demand a lot of boilerplate code. 
If properly implemented, there is a lot of code you have to write 
over and over again such as

if (isInputRange!Range && isInputRange!(ElementType!Range) &&
         is(ElementType!(ElementType!Range) == MyType))

I don't know if this could possibly be reduced. Or maybe it's 
just my lack of experience.


More information about the Digitalmars-d mailing list