D component programming is a joke (Was: Re: Component programming)

Dejan Lekic dejan.lekic at gmail.com
Mon Aug 5 05:11:32 PDT 2013


On Friday, 2 August 2013 at 05:26:05 UTC, H. S. Teoh wrote:
> On Thu, Aug 01, 2013 at 10:34:24AM -0700, Walter Bright wrote:
>> On 8/1/2013 2:23 AM, John Colvin wrote:
>> >On Thursday, 1 August 2013 at 00:47:43 UTC, H. S. Teoh wrote:
>> >Add in some code examples and that could make a nice article.
>> 
>> Yes, please!
>
> Alright, so I decided to prove my point about component 
> programming by
> actually writing a fully-functional version of the calendar 
> layout
> program, so that I have a solid piece of evidence that component
> programming lives up to its promise. :) In addition, I decided 
> that for
> maximum reusability, I want the output lines available in an 
> input
> range, with absolutely no binding to writeln whatsoever (except 
> in
> main() where the range is handed to writeln for output). In 
> retrospect,
> that was perhaps a bit too ambitious... I ran into a few 
> roadblocks to
> actually get the code working, so it took me a lot longer than I
> anticipated to finish the code.
>
> However, I *will* say that I'm very proud of the code: already 
> there are
> a few pieces that, if properly cleaned up and refined, probably 
> deserve
> inclusion in Phobos. Reusability FTW!! Now, just tell me if 
> you've ever
> seen a calendar layout program made of straightforward, 
> reusable pieces.
> I for sure haven't. I tried looking at the C code for the Unix 
> cal
> program once... It looked frighteningly similar to an IOCCC 
> entry. :-/
>
> My D version, however, built using ranges through and through, 
> has many
> pieces that are easily reusable. For example, if you wanted to 
> output
> only a single month instead, you could just call join("\n") on 
> the range
> of formatted month lines that the full year layout algorithm 
> uses to
> splice lines from multiple months together -- it's *that* 
> reusable.
>
> Anyway. Enough hand-waving in the air. Let the actual code 
> speak for
> itself:
>
> 	https://github.com/quickfur/dcal/blob/master/dcal.d
>
> Now, w.r.t. the roadblocks I alluded to.
>
> When I first started working on the code, my goal was to 
> maximize usage
> of existing Phobos facilities in order to show how many 
> batteries D
> already comes with. As it turned out, I could only use basic 
> Phobos
> components; some of the more complex pieces like 
> frontTransversal, which
> would've been perfect for the bit that splices formatted month 
> lines
> together, couldn't be used because it wasn't flexible enough to 
> handle
> the insertion of fillers when some subranges are empty. In the 
> end, I
> had to code that range by hand, and I can't say I'm that happy 
> with it
> yet. But at least, it's nothing compared to the hairy 
> complexity of the
> C version of cal.
>
> Another place where I wanted to use existing Phobos components 
> was
> chunkBy. There's probably a way to do it if you think hard 
> enough about
> it, but in the end I felt it was simpler to just write the code 
> myself.
> Might be a failure on my part to recognize how to put existing 
> Phobos
> ranges in a clever enough way to achieve what I wanted. I did 
> try to do
> something similar to byWeek(), but somehow it didn't do what I 
> wanted
> and I decided to just code it by hand instead of investigating 
> further.
>
> By far the biggest roadblock I ran into was that after I wrote
> everything up to (and including) pasteBlocks, my unittests 
> refused to
> work. Somehow, pasteBlocks kept repeating the first line of the 
> output
> (the month names, if you look at the unittest) and refused to 
> advance
> farther.  Eventually I traced the problem to Lines.popFront(), 
> which
> pops each subrange off the range of ranges. The problem is that 
> this
> only works on some ranges, but not others; if you pass the 
> output of
> formatMonths() straight to pasteBlocks(), it will NOT work. 
> Why? Because
> pasteBlocks return a std.algorithm.Map object, which recreates 
> the
> subrange each time, so Lines.popFront() is only popping a 
> temporary copy
> of the subrange, not the real thing. I was about to give up and 
> try
> another approach, when out of the blue I decided to try and see 
> if I
> could stuff the range returned by formatMonths() into an array, 
> and then
> pass *that* to pasteBlocks() -- and behold, it worked!!
>
> This was a totally unexpected fix, that a newbie probably would 
> never
> have thought of, so this is a potential trap for newcomers to D 
> who
> expect components to just be pluggable. In retrospect, it makes 
> sense --
> you need to somehow buffer the ranges of formatted month lines
> *somewhere* in order to be able to splice them together out of 
> their
> natural depth-first outer/inner range order. But this is not 
> obvious at
> all from first glance; perhaps it's a sign of a leaky 
> abstraction
> somewhere. We should probably look into why this is happening 
> and how to
> fix it. And there should be a way to test for this in 
> pasteBlocks'
> signature constraint so that future code won't fall into the 
> same trap,
> but I can't think of one right now.
>
> Once this last bit worked, though, everything fell into place 
> quickly.
> After all unittests were passing, no more bugs were found!! The 
> program
> can print beautifully laid out calendars with no problems 
> whatsoever.
> I'm so in love with D right now... If I'd done this exercise in 
> C or
> C++, I'd be spending the next 2 days debugging before I could 
> present
> the code for the world to see. D ranges and unittest blocks are 
> t3h
> k00l.
>
>
> T

Good work! I've read the article yesterday. Very educational!


More information about the Digitalmars-d mailing list