Deutsch   English   Français   Italiano  
<vu5ol1$2h3r8$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail
From: bart <bc@freeuk.com>
Newsgroups: comp.lang.c
Subject: Re: Loops (was Re: do { quit; } else { })
Date: Mon, 21 Apr 2025 16:36:01 +0100
Organization: A noiseless patient Spider
Lines: 111
Message-ID: <vu5ol1$2h3r8$1@dont-email.me>
References: <vspbjh$8dvd$1@dont-email.me> <vtin99$vu24$1@dont-email.me>
 <vtiuf0$18au8$1@dont-email.me> <vtj97r$1i3v3$1@dont-email.me>
 <vtl166$36p6b$1@dont-email.me> <vtlcg0$3f46a$2@dont-email.me>
 <vtnekn$1fogv$1@dont-email.me> <vto2mb$20c4n$1@dont-email.me>
 <vtu4i5$3hteg$1@dont-email.me> <vtujko$3uida$1@dont-email.me>
 <vtvfop$rf2p$1@dont-email.me> <vtvto2$15otp$1@dont-email.me>
 <vu01k7$1bfv2$1@dont-email.me> <vu0720$1dva7$1@dont-email.me>
 <vu2hmg$3jn88$1@dont-email.me> <vu2mkc$3noft$1@dont-email.me>
 <vu5ig6$3catv$1@paganini.bofh.team>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Mon, 21 Apr 2025 17:36:02 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="519b62363da5fc709140aed5764e0c61";
	logging-data="2658152"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX1/KVw25LluG29TKa+EgCaRk"
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:7EJjyRffvF8P/OOpg9tLeESXbio=
In-Reply-To: <vu5ig6$3catv$1@paganini.bofh.team>
Content-Language: en-GB
Bytes: 5462

On 21/04/2025 14:51, Waldek Hebisch wrote:
> bart <bc@freeuk.com> wrote:
>>
>> I don't know why people think that cramming as much code as possible
>> into for(...) is a good style of coding. Either into one over-long line,
>> or spilling over multiple lines; both should fail a code review.
>>
>> Actually here's a example from sqlite3.c:
>>
>>      for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
>>          sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
>>      }
>>
>> And this is how you might be forced to write it instead:
>>
>>      p=sqliteHashFirst(&pSchema->trigHash);
>>      while (p) {
>>          sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
>>          p=sqliteHashNext(p);
>>      }
>>
>> Yes, it's spread over two more lines, but so what? It's much clearer:
>> the initialisation is done once and then it's out of the way. Setting p
>> to the next value is now physically written after the body.
> 
> Apparently you do not get why sqlite3.c version is better.
> In short, this is separation of concerns.  The 'for' construct
> is responsible for iteration.  Body of 'for' loop is responsible
> for computation.  You may replace body by empty instruction,
> so there are no computation but the loop still correctly goes
> over the same sequence.  Or you may add instructions to perform
> more computation.  'while' version mixes computation with
> stepping to the next element.  Since in 'for' version all parts
> dealing with iteration are together it is easy to check that
> they are correct.  With 'while' version probablity of forgeting
> to step to next element is higher.

You have to analyse it first. The kind of loop this expresses is:

    p = startvalue()

    while (p) {
       <body>
       p = nextvalue()
    }

Notice how I chose to express it: it reflects how I would describe it in 
English:

    * Set P to Start Value
    * While P isn't Null:
      * Execute the body
      * Set P to Next Value

So, how would /you/ describe it in English? (Or in any language if like, 
as the ordering is more important.)

 >In short, this is separation of concerns.

You seem be picking and choosing which concerns are in need of separation!

The example is this: for(A; B; C) D

You are saying that D must be separate from A B C, but specifically from C.

I'm asking, why shouldn't A B C also be separate from each other?

Especially A, which is only executed once, after which it's no longer 
part of the loop.

As C works now, the alternative might be: A; while (B) { D; C;}.

I wouldn't have minded a syntax like: A; while (B; C) {D} but C doesn't 
have that. In that case, the 'while' version still wins over 'for' IMO.


> FYI: I do not remember making error in a simple 'for' loop.
> I do remember cases when I had to use 'while' for iteration
> (in non-C languages) and stepping was wrong/missing.  So
> for me simple loops (your 98% of cases) are not an issue.

> The issue are remaining cases, and for them C 'for' works
> better.

That's bizarre. It is exactly like saying you don't have a problem with 
writing (or forgetting to write) 'break' in 99% of switch-case blocks, 
because in those 1% of cases where you do want fallthroughit is 'automatic'.

I expect you also either think that:

  for (ch = 0; ch <= 255; ++ch)

is better than: 'do ch = 0, 255', or is much more tolerant of it than I am.

Here's how that C for-loop works, in English:

   * Set ch to 0
   * While c is less than or equal to 255:       (typo left in!)
     * Execute the body
     * Set ch to ch + 1

Here is how that compact version works, in English:

   * For ch having the values 0 to 255 inclusive:
     * Execute the body

However I see that nobody in this group has any objective interest in 
language ergonomics and aesthetics. They more interested in defending 
'their' language.