Re: Letter to US Sen. Byron Dorgan re unpaid overtime

From: Richard Heathfield (dontmail_at_address.co.uk.invalid)
Date: 12/21/03


Date: Sun, 21 Dec 2003 10:29:57 +0000 (UTC)

Edward G. Nilges wrote:

>> >>
>> > Unlike a For loop in Basic or Fortran, the condition in C has to be
>> > repeatedly evaluated.
>>
>> You make "has to be" sound like a problem, whereas it is generally
>> considered to be a convenience by those who use the C language.
>>
>> I just tested your assertion re Basic in VB.NET; the assertion is
>> correct,
>
> You had to test it. You should have known it.

Don't be silly. I make no claims to being a VB.NET programmer. Of course, if
VB.NET were standardised, I could have looked the answer up in the
Standard. But it isn't, so I couldn't.

>> which makes a pleasant change. Note that it doesn't really matter which
>> of these choices the language makes, as long as the choice is clearly
>> documented, and as long as the programmer knows which choice was made. If
>> the choice is clearly documented, it is not the fault of the language if
>> the programmer screws it up.
>>
> This is nonsense. Ritchie SCREWED UP in designing the for loop because
> the expression of the limit condition, in evaluating variables, is
> both less efficient and less safe than the Fortran and Basic standard.

I beg to differ. If you wish the limiting expression to be calculated once,
you need only calculate it once. If you wish it to be calculated each time,
you have that choice. It's a CHOICE.

If you want Fortran or Basic, you know where to find them.

> The C for loop is actually trying to do what a do loop does. In Basic
> and Fortran there is a clean conceptual separation between the for and
> the do, but in C, you can express a complex condition, which takes
> into account changes in variable values, in a for. This is messy, to
> say the least.

C programmers do not find it so. If you don't like C, don't use it. But to
try to impose your likes and dislikes on others is an exercise doomed to
failure.

> It means that the C programmer has to think in Fortran terms to write
> clear code.

No, it means that the C programmer had jolly well better be able to think in
C terms to write clear code.

> It's also less efficient since the possibly changed variables have to
> be re-accessed each time through each of the billions of for
> statements executed around the world, time which could be better used
> to find a cure for aids. Or something.

I have not found C to be wanting in the speed department.

>> > but you are right, to a limited extent: the C code will
>> > repeatedly evaluate the strlen function.
>>
>> Yes. That the condition is evaluated afresh on each iteration is useful,
>> provided you know it happens.
>>
> Only if you engage in the unsafe practice of modifying for loop limits
> inside a for loop.

I often invoke the terminating condition of a for loop manually inside the
loop, and do not find it even remotely unsafe. Example follows (E&OE - this
is hand-typed, not an extract from an actual program):

for(thisline = 0; SUCCESS == rc && thisline < numlines; ++thisline)
{
  rc = ProcessLine(line[thisline]);
}

> The original intent of the grandfather construct,
> the Do loop of Fortran, was to make processes using vectors and arrays
> predictable.

Who cares? The discussion here is about C loops, not Fortran loops. If you
want to discuss Fortran loops, that's fine, but do it with someone else,
okay?

> Basic does this because changes to control variables are not reflected
> in the evaluation of its For clause. C does not.

I consider that to be a strength of C, in that it does what I expect. I was
surprised to find that VB.NET does things differently.

>> > The problem is that 9 out of ten "competent" programmers are
>> > completely unaware of how C versus Fortran and Basic evaluate what
>> > looks like the same statement,
>>
>> Looks like you were one of the nine, Mr Nilges.
>>
> You reminded me of a C fact which I knew when I implemented a C
> compiler in 1993.

I do not believe that you are capable of writing a conforming C compiler.
Please provide evidence that you have done so, if you wish to be
persuasive.

> The phenomenon is that I have forgotten more about C
> than you may know.

Yes, we established that this is trivially true, because I don't actually
know everything there is to know about C. (I despair of your actually
understanding this reply.)

> When I implemented the for loop I looked up the ANSI standard and
> realized that I had to evaluate the for.

What on earth does that mean? "evaluate the for"? It's a meaningless
statement in terms of C. And anyway, if you're writing a C compiler, you
don't have to do /anything/ special for the for-loop condition. It's just
an expression-opt, like any other expression-opt. No Special Treatment
Required. Duh.

> Whereas in the Basic compiler for my book I simply load the stack with
> the constant or nonconstant value.
>
> In other words, C, like James Joyce's history, is a nightmare from
> which I would like to awake.

C is clearly not the right language for you. I'm beginning to think ITA
might be the right language for you, but C definitely isn't. I think you'd
be happier playing in a BASIC sandbox.

> My point was that the entire issue is ignored in most programming
> circles other than this.

There is /no/ real issue here. You wrote some crap C code. Those who know
the C language and who read your code saw it was crap. You blamed C. We
showed that C is not to blame. End of story.

>> > but will still feel qualified to tell
>> > you all about what is efficient or not
>>
>> Yes, it /still/ looks like you're one of the nine. You are describing
>> your own behaviour perfectly.
>
> No, we're not talking about rote memory of one language.

Rather, we're talking about common sense macro-efficiency gains (or, in your
case, losses).

> We're talking
> about the awareness of the very issue itself. I am completely not
> interested in your continued sniping since when I need the knowledge I
> go to the book.

THEN WHY DIDN'T YOU?

Fcol.

>>
>> > Furthermore, it is only micro-inefficient in code otherwise
>> > well-organized to use strlen in the for condition,
>>
>> **splutter!!!**
>
> splut. Your point being?

Can you say O(n*n)?

>> > because determining
>> > the strlen is the execution of one instruction, that which scans for
>> > Nul.
>>
>> But the scanning takes time.
>
> Read Kant. Everything takes time. And if you would disabuse yourself
> of the very idea that everything must happen at once, and that we
> should learn one language, and remember all of its silly details, you
> would be a better person.

We don't need everything to happen at once, but on the other hand we cannot
ignore efficiency. You seem to be arguing that it's okay for your code to
be O(n*n) when anyone with half a brain could achieve the same objective in
O(n) (for significant n). Well, if that really is what you're arguing, few
here will continue to wonder about your competence.

>> > If the code is otherwise well-organized you can be certain that
>> > (1) the string will not be overlong, for you will know the programmer
>> > hasn't misused strings to contain what should have been data bases
>>
>> O(n*n) doesn't need a huge n for things to get very slow very fast.
>> Furthermore, it is not always possible for the programmer to know in
>> advance just how big a string his program will be expected to handle. The
>> grep program is a fine example of this.
>>
> If you are truly writing a truly general tool, then, consider writing
>
> for ( intLength = strlen(strInstring), intIndex1 = 0;
> intIndex < intLength;
> intIndex++ )

Don't be silly. intLength is a hopeless name, which suggests that the object
is of type int whereas any competent C programmer knows that strlen returns
size_t.

> But your comments on strlen suggest you may be ignorant of modern
> compiler optimization.

Here is a simple program which hashes each line in a file. As you can see, I
have implemented it in two ways. The first way caches the length of the
string in a temp, a la Heathfield. The second does not, a la Nilges.

I compiled each version using gcc's -O2 optimisation switch. Let's have a
look at the code, and then the results:

$ cat foo.c
#include <stdio.h>
#include <string.h>

unsigned long hash(const char *s)
{
  unsigned long n = 0;
  size_t len = strlen(s);
  size_t i;
  for(i = 0; i < len; i++)
  {
    n *= 33;
    n += s[i];
  }
  return n;
}

int main(void)
{
  char buf[2048] = {0};
  while(fgets(buf, sizeof buf, stdin))
  {
    printf("%lu\n", hash(buf));
 
  }
  return 0;
}

This version uses strlen-caching.

(test.in has 7752 lines and is 219554 bytes in size.)

$ time ./foo < test.in > test.out

real 0m0.053s
user 0m0.040s
sys 0m0.020s

Here is the uncached equivalent:

unsigned long hash(const char *s)
{
  unsigned long n = 0;
  size_t i;
  for(i = 0; i < strlen(s); i++)
  {
    n *= 33;
    n += s[i];
  }
  return n;
}

Same optimisation level - fairly aggressive but not dangerously so:
$ time ./foo < test.in > test.out

real 0m0.113s
user 0m0.100s
sys 0m0.010s

Your technique is still way slower, you see.

> A good optimizer would not track invariants in loops as variables, it
> would extend the tracking to expressions including
> strlen(strInstring).

Having seen your C code, I am not prepared to accept anything you say about
optimisation at face value. Note that the compiler /cannot/ legitimately
make this assumption without understanding what strlen actually /is/. That
would mean putting code in specifically for optimising strlen calls in the
particular case where the length of the string doesn't change between
invocations. Are you seriously suggesting this? Does anyone here know of
/any/ compiler that does this?

> It would add strInstring to its table of invariant variables in the
> for, or conversely make a short table of pointers to variables which
> change in the loop.
>
> If the loop does not contain any calls to external functions and no
> aliased references, this short table is "safe" therefore the optimizer
> can create in effect the above code, and a temp variable for
> intLength, thus avoiding discovering strlen each time.

But strlen /is/ an external function.

> C's unrestricted semantics make this harder but still possible. If the
> body of the loop is something like { a = b } and a and b are simple
> variables then there is I think no chance that the assignment might
> conceal an alias.

The loop body you supply here won't actually compile. Note that few C loops
are that simple (and in general, they do in fact compile).

> In general the fact that C allows aliasing does not mean that the
> compiler cannot do a sort of symbolic evaluation of the text inside
> the loop and conclude either that "the effect of this loop is known"
> or else "the effect of this loop is not known".

More to the point, it makes sense to perform this trivial optimisation in
one's own code, so that we don't have to assume that our end
user-programmer has access to an all-singing all-dancing whizzy optimising
compiler.

<snip>

>> > In fact, the over-generality of the C for loop is a major problem
>>
>> <grin> First, C isn't powerful enough - and now it's /too/ powerful. Make
>> your mind up, Mr Nilges! Are you really saying that:
>>
>> for(expression-opt; expression-opt; expression-opt) statement
>>
>> is so difficult to understand that it is actually beyond your grasp?
>>
> It's an irresponsible hack because Kernighan if not Ritchie had as a
> model the Algol and Fortran work.

Brian Kernighan wrote (most of) the *book* - not the language. As for
"because", are you ***serious***? There's nothing inherently irresponsible
about doing something differently to the way it's been done before. If
Dennis Ritchie had wanted to write an Algol compiler, he'd have written an
Algol compiler.

> They ignored it because they were
> sort of passively-aggressively engaged with the computing
> Establishment in the context of the early 1970s, and wanted to make
> their own construct. They managed to screw up because the semantics of
> the For statement aren't clear and temporarily confuse smart people
> like me.

It's a poor workman who blames his tools.

>> > that
>> > is inherited by C++ and C#, precisely because it forces the compiler
>> > to re-evaluate values.
>>
>> Depends on the values. The optimiser has quite a lot of leeway. But it
>> draws the line at anticipating the results of function calls!
>
> strlen is probably generated inline.

Inlining ***doesn't help*** here! The problem is not in the *call*, but in
the *code*! I mean, DUH, do you really not understand this? I can't believe
that even you are this stupid! The problem is that you have to count the
number of characters OVER and OVER and OVER. In comparison, the function
call overhead is trivial!

>> > In fact, these defects in C MEAN that skill-at-programming is NOT
>> > skill-at-C,
>>
>> They're not defects in C, Mr Nilges. They're defects in your
>> understanding of C.
>>
> An understanding which comes and goes when I need it.

Well, no: you needed it last year, and it didn't come.

<sociology snipped>

> I concede that insofar as I sit down and write C it is absolutely
> essential for me to understand these issues just in time

Just too late, in your case.

> (and I claim
> that 9 out 10 programmers don't bother their heads with these issues
> at all).

Sturgeon's Law. So what? Here in comp.programming, we assume that the 9 out
of 10 are too busy debugging to bother with Usenet.

<silliness snipped>

> I abandoned C and adopted object oriented VB because I wanted to
> organize larger problems and conveniently forgot the semantics of for
> until you reminded me.

It should not be assumed that, just because you say you are incapable of
using C to "organize larger problems", others would necessarily have the
same problem. C has been used successfully on extremely large problems.

> That's why people like you are useful.

Ah, it's good to know that one of us is useful.

> But please don't confuse your knowledge with wisdom.

Never have yet. And I don't confuse my ignorance with wisdom, either. I
cheerfully commend this course to you.

>> > and you and "programmer" "dude" wasted your time in
>> > building elaborate Web sites about my competence based on my C praxis,
>>
>> ROTFL! Are you trying to outdo your own personal record for sheer idiocy
>> today?
>>
>> I have a single page given over to the discussion of your code. It
>> comprises two cut-n-paste quotes from Usenet, plus a couple of jumpy
>> linky things. It's about as elaborate as a brick. It was written some
>> time ago, so I don't recall exactly how long it took me, but I doubt if
>> it was more than five minutes. This is not what I call "elaborate".
>>
> That makes it all the more libelous, then. You didn't do your
> homework.

It's not libelous at all, and I /did/ do my homework. The proof is at
http://users.powernet.co.uk/eton/compprog/nilges.html

>> Anyway, your code and my critique is there for all to see, so they can
>> judge for themselves whether your C is up to the job:
>>
>> http://users.powernet.co.uk/eton/compprog/nilges.html
>>
>> > Skill at programming in fact means being able to spot issues such as
>> > the above which are by nature between the lines.
>>
>> And I did. And you didn't.
>>
> In that case, you did.

Quite. Skill at programming. Something you appear to lack.

> But because you overspecialize in C you had to
> test the VB assertion.

The VB.NET assertion, actually. And anyway you're being ridiculous.
Knowledge of one language is not a *cause* of ignorance in another.

>> > Skill at programming
>> > means that you are able to explain an algorithm in natural and not
>> > computer language while remaining courteous and pleasant.
>>
>> Look back over your "contributions" to this newsgroup. Count the number
>> of times you have used expletives. Now count the number of times I have
>> used expletives. A significant disparity exists, and it is not in your
>> favour. You have done more than most to make this newsgroup unsuitable
>> for family viewing, so don't you /dare/ talk to me about "remaining
>> courteous and pleasant".
>>
> You can count expletives all you want, dickwad.

See what I mean?

> You started the
> flaming, the libel and the incorrect interpretation of the charter.

Please don't be so childish. I have not libelled you. I have not flamed you.
And I have not incorrectly interpreted the charter.

(Did! Didn't! Did! Didn't!)

> Nonetheless, dickwad,

Courteous? Pleasant? You? Don't make me laugh.

> I am obliged for your correction on the damaged
> semantics of C's for statement.

I have no problem with the semantics of C's for statement. If you do, I
suggest you avoid the language altogether.

> You might consider, dickwad,

Is this still you trying to be courteous and pleasant?

> that when
> you focus on areas of your competence (which do not include this ng's
> charter) you come across better.

Where, specifically, Mr Nilges, does the charter mention sociology,
post-modernism, or Fascism? These are the topics you would have us believe
are relevant here. I see no evidence whatsoever in the charter to support
that position.

> And note that I can add three occurence to your expletive count,
> dickwad (oops, four) while remaining courteous and pleasant.

If you truly believe that, I am concerned for your mental health; please
seek help from a competent psychiatrist.

> The
> implication, dickwad (there I go again), is that there are no metrics
> for courtesy.

The absence of a metric for courtesy does not mean that courtesy cannot be
assessed qualitatively. Your repeated expletives make it clear that you are
not interested in being courteous, no matter how much you protest
otherwise.

-- 
Richard Heathfield : binary@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Loading