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