lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Control flow in page_with_tabular_report::render()


From: Greg Chicares
Subject: Re: [lmi] Control flow in page_with_tabular_report::render()
Date: Tue, 13 Feb 2018 19:31:39 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2

On 2018-02-13 13:48, Vadim Zeitlin wrote:
> On Mon, 12 Feb 2018 22:45:15 +0000 Greg Chicares <address@hidden> wrote:

[...snip code example...]

> GC> It's just a handful of lines of code, all self-contained.
> 
>  Sorry, but it's far from obvious that this code is correct.

There's one thing about it that I find especially compelling: its
compactness. Apart from the lines that contain only a single brace,
all the work is done in four lines of code. I can focus deeply on
those four lines and pretty quickly come to a deep understanding of
what they do and how they do it. I don't have to page up a hundred
lines to consult a base class's implementation, look in another file
to find a template, etc.; instead, I can get it all at a glance.

>  Compare this with something like
> 
>       class tabular_report : paginator
>       {
>               int get_fixed_page_part_height() override
>               {
>                       return render_or_measure_fixed_page_part(...);
>               }
> 
>               void on_data_row(int y, int n) override
>               {
>                       table.output_row(y, values[n]);
>               }
> 
>               void on_blank_row(int y) override
>               {
>                       // nothing to do here
>               }
>       };
> 
> which is painfully obviously correct by construction.

My code actually printed an array. This isn't quite comparable in
that sense. Would it be too much trouble if I asked you to flesh
it out, to the same degree as the little program I had posted,
so that we can compare our design philosophies in microcosm?
I'd like to see whether we're striving for much the same thing
in much the same way, but describing our viewpoints in such
different terms that it's hard to see where we're in agreement.

> GC> No fancy design patterns needed. No iterators. No lambdas.
> 
>  This is not completely fair. The "template method" pattern is not fancy at
> all and many people use it without ever even realizing they do it. And
> lambdas was an alternative to using it, so it's either one or the other
> (and, of course, what could be more like ANSI C than using callbacks...).

Custom iterator classes, lambdas, and function pointers really do
seem fancy to me. I can't write them off the top of my head without
thinking hard. OTOH, I wrote the sample code [snipped above] from
beginning to end without pause, and only had to go back to fix a
single mistake (which turned out to be a carelessly misplaced brace).
I don't have that degree of fluency with, say, function-pointer
declarations.

Perhaps I'm like a pianist who can play anything in C major because
it's white keys only, but whose heart sinks at the thought of black
keys. I don't occupy a position of objectivity from which I can say
whether black keys really are harder as opposed to less familiar.

> GC> I'd say lambdas, function<>, and "design patterns" are unnecessary
> GC> impediments to comprehension here:
> 
>  Sorry, but I completely disagree. There is nothing complicated about this
> design pattern (I didn't use the word to be fancy, but just to make it
> clear what I was talking about). It has been used since 50 years in C under
> the name of "callback function pointer"

I've tried to read the GoF book several times, hoping to realize that
I've used at least some of its patterns without realizing it--like
Molière's character who's excited to learn that he's been speaking
prose all his life. But that realization never comes, and I've grown
to suspect that most of this stuff isn't pragmatically useful for me.
Well, Singleton is, and I guess lmi's input sequences constitute an
Interpreter (though the GoF didn't invent interpreters), but that's
about as far as I've gotten with this book.

And I have had the "I can speak prose" insight with other patterns
not on the GoF list. For instance, it's clear to me that if we'd
never heard of CRTP, we'd all have to invent it. More strikingly,
when I first heard of MVC, I realized first that I'd been doing it
for years, but poorly; and second, that MVC was better than anything
I would have invented myself.

Maybe I'd understand this better if you can point out something I've
written in lmi that exemplifies the Template pattern (or others in
the GoF catalog). I'm not asking you to spend a lot of time poring
over hundreds of source files--I'm hoping you might have noticed a
GoF pattern or two somewhere already and can just point me to it.

> GC> whatever can be written well and clearly in the C subset of C++ is
> GC> simplest and clearest when written that way, and introducing
> GC> unnecessarily fancy techniques can only make it less clear.
> 
>  And I disagree even completier with this. "Brief for" loops are a C++
> technique which is very fancy (it uses iterators internally!), but is much
> more clear and less error-prone than the equivalent C loops using indices.
> C++ smart pointers (they use templates!) are very fancy, yet incomparably
> safer than simple malloc/free. And C++ strings (they use move semantics!)
> are, of course, so much less powerful than C char[], you can have real
> trouble writing even a simple buffer overflow with them, which was, and
> continues to be, easily doable in standard C since 1970s.

I didn't explain my viewpoint very clearly. I wouldn't want to use char[],
and I'd add it (and its accompanying <cstring> functions) to the list of
tools that I avoid as being too hard for me to use correctly. So I'm not
at all suggesting that C is an ideal language for the task at hand. What I
am saying is that if we want to express the sort of control flow for which
K&R designed for(), then we should use for(). And I think the task at hand
is a matter of control flow, and one for which for() is best suited.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]