Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail From: bart 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: References: 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: Content-Language: en-GB Bytes: 5462 On 21/04/2025 14:51, Waldek Hebisch wrote: > bart 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) { 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.