Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #165626 > unrolled thread
| Started by | Jens Stuckelberger <Jens_Stuckelberger@nowhere.net> |
|---|---|
| First post | 2022-04-12 18:05 +0000 |
| Last post | 2022-04-14 12:39 +0200 |
| Articles | 20 on this page of 22 — 10 participants |
Back to article view | Back to comp.lang.c
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Memorizing C operator precedence Jens Stuckelberger <Jens_Stuckelberger@nowhere.net> - 2022-04-12 18:05 +0000
Re: Memorizing C operator precedence Alan Mackenzie <acm@muc.de> - 2022-04-13 18:09 +0000
Re: Memorizing C operator precedence Siri Cruise <chine.bleu@yahoo.com> - 2022-04-13 15:23 -0700
Re: Memorizing C operator precedence Kaz Kylheku <480-992-1380@kylheku.com> - 2022-04-13 23:36 +0000
Re: Memorizing C operator precedence Kaz Kylheku <480-992-1380@kylheku.com> - 2022-04-13 23:48 +0000
Re: Memorizing C operator precedence Alan Mackenzie <acm@muc.de> - 2022-04-14 10:38 +0000
Re: Memorizing C operator precedence Kaz Kylheku <480-992-1380@kylheku.com> - 2022-04-14 21:05 +0000
Re: Memorizing C operator precedence Alan Mackenzie <acm@muc.de> - 2022-04-16 14:27 +0000
Re: Memorizing C operator precedence Paul N <gw7rib@aol.com> - 2022-04-23 10:23 -0700
Re: Memorizing C operator precedence Alan Mackenzie <acm@muc.de> - 2022-04-25 10:21 +0000
Re: Memorizing C operator precedence Vir Campestris <vir.campestris@invalid.invalid> - 2022-04-25 16:43 +0100
Re: Memorizing C operator precedence Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-04-26 03:02 -0700
Re: Memorizing C operator precedence Kaz Kylheku <480-992-1380@kylheku.com> - 2022-04-26 13:58 +0000
Re: Memorizing C operator precedence Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-04-25 14:48 -0700
Re: Memorizing C operator precedence Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-04-25 15:16 -0700
Re: Memorizing C operator precedence Alan Mackenzie <acm@muc.de> - 2022-04-26 10:34 +0000
Re: Memorizing C operator precedence Ben <ben.usenet@bsb.me.uk> - 2022-04-26 13:13 +0100
Re: Memorizing C operator precedence Alan Mackenzie <acm@muc.de> - 2022-04-26 17:25 +0000
Re: Memorizing C operator precedence Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-04-26 06:12 -0700
Re: Memorizing C operator precedence Alan Mackenzie <acm@muc.de> - 2022-04-26 17:17 +0000
Re: Memorizing C operator precedence Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-04-30 07:05 -0700
Re: Memorizing C operator precedence David Brown <david.brown@hesbynett.no> - 2022-04-14 12:39 +0200
Page 1 of 2 [1] 2 Next page →
| From | Jens Stuckelberger <Jens_Stuckelberger@nowhere.net> |
|---|---|
| Date | 2022-04-12 18:05 +0000 |
| Subject | Re: Memorizing C operator precedence |
| Message-ID | <t34f1f$s4u$1@gioia.aioe.org> |
On 12 Apr 2022 13:03:39 GMT, Stefan Ram wrote: > [...] What for? Use parentheses - that's what they are there for.
[toc] | [next] | [standalone]
| From | Alan Mackenzie <acm@muc.de> |
|---|---|
| Date | 2022-04-13 18:09 +0000 |
| Message-ID | <t373kj$1avk$1@news.muc.de> |
| In reply to | #165626 |
Jens Stuckelberger <Jens_Stuckelberger@nowhere.net> wrote: > On 12 Apr 2022 13:03:39 GMT, Stefan Ram wrote: >> [...] > What for? Use parentheses - that's what they are there for. If you want to use parentheses, you should be writing in Lisp. ;-) Too many parentheses can make C code difficult to read. Difficult to read translates to "more bugs". A knowledge of C's precedence levels, at least to a moderate degree, can help avoid such bugs. Maybe some day we'll get the compiler warning "unnecessary parentheses". -- Alan Mackenzie (Nuremberg, Germany).
[toc] | [prev] | [next] | [standalone]
| From | Siri Cruise <chine.bleu@yahoo.com> |
|---|---|
| Date | 2022-04-13 15:23 -0700 |
| Message-ID | <chine.bleu-839F13.15232913042022@reader.eternal-september.org> |
| In reply to | #165660 |
In article <t373kj$1avk$1@news.muc.de>, Alan Mackenzie <acm@muc.de> wrote: > Too many parentheses can make C code difficult to read. Difficult to > read translates to "more bugs". A knowledge of C's precedence levels, > at least to a moderate degree, can help avoid such bugs. Not if you insert line breaks and indentation to line up openners and closers. -- :-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @ 'I desire mercy, not sacrifice.' /|\ Discordia: not just a religion but also a parody. This post / \ I am an Andrea Doria sockpuppet. insults Islam. Mohammed
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <480-992-1380@kylheku.com> |
|---|---|
| Date | 2022-04-13 23:36 +0000 |
| Message-ID | <20220413162441.432@kylheku.com> |
| In reply to | #165660 |
On 2022-04-13, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
> Alan Mackenzie <acm@muc.de> writes:
>>Too many parentheses can make C code difficult to read. Difficult to
>>read translates to "more bugs". A knowledge of C's precedence levels,
>>at least to a moderate degree, can help avoid such bugs.
>
> When I would see an expression such as "( 3 * x )+ t", I might spend
> some time wondering about why the redundant parentheses are there!
Maybe it was copy and pasted from a macro expansion, where 3 * x
had come in as an argument.
Extra parens can help with indentation when an expression
is broken up into multiple lines.
given:
a*b*c*d*... + m*n*o*p* + ...
we might do this at first
a*b*c*d*... +
m*n*o*p*... +
...
the terms of the addition go on separate lines. Now suppose
the terms themselves are too long: now what?
a*b*c*
d*... +
m*n*
o*p*... +
...
that's not very good; extra parens improve it.
(a*b*c*d*...) +
(m*n*o*p*...) +
(...)
then:
(a*b*c*
d*...) +
(m*n*o
*p*...) +
(...)
Chances are your editor will handle this automatically.
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <480-992-1380@kylheku.com> |
|---|---|
| Date | 2022-04-13 23:48 +0000 |
| Message-ID | <20220413163721.82@kylheku.com> |
| In reply to | #165660 |
On 2022-04-13, Alan Mackenzie <acm@muc.de> wrote: > Jens Stuckelberger <Jens_Stuckelberger@nowhere.net> wrote: >> On 12 Apr 2022 13:03:39 GMT, Stefan Ram wrote: > >>> [...] > >> What for? Use parentheses - that's what they are there for. > > If you want to use parentheses, you should be writing in Lisp. ;-) When you write in Lisp, most of the formatting is automatic and almost always looks good, so you can concentrate on coding. There are some new developments in this area in the last few years, like the "parinfer" algorithm. "parinfer" creates a two-way linkage between indentation and parentheses. Write your code, adjusting indentation as you go, and the right parentheses materialize automatically. Or, tweak the parentheses and the indentation fixes itself accordingly. Google for demos of this. > > Too many parentheses can make C code difficult to read. Difficult to > read translates to "more bugs". A knowledge of C's precedence levels, > at least to a moderate degree, can help avoid such bugs. Too much complexity in one expression makes it hard to read. Other than breaking it up into smaller expression, what can help is to split it into multiple lines and use indentation. Parenthesized expressions are much more amenable for splitting across lines and indenting than pure infix operator expressions. -- TXR Programming Language: http://nongnu.org/txr Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
[toc] | [prev] | [next] | [standalone]
| From | Alan Mackenzie <acm@muc.de> |
|---|---|
| Date | 2022-04-14 10:38 +0000 |
| Message-ID | <t38tjs$cnl$1@news.muc.de> |
| In reply to | #165673 |
Kaz Kylheku <480-992-1380@kylheku.com> wrote:
> On 2022-04-13, Alan Mackenzie <acm@muc.de> wrote:
>> Jens Stuckelberger <Jens_Stuckelberger@nowhere.net> wrote:
>>> On 12 Apr 2022 13:03:39 GMT, Stefan Ram wrote:
>>
>>>> [...]
>>> What for? Use parentheses - that's what they are there for.
>> If you want to use parentheses, you should be writing in Lisp. ;-)
> When you write in Lisp, most of the formatting is automatic and almost
> always looks good, so you can concentrate on coding.
Yes.
> There are some new developments in this area in the last few years,
> like the "parinfer" algorithm. "parinfer" creates a two-way linkage
> between indentation and parentheses. Write your code, adjusting
> indentation as you go, and the right parentheses materialize
> automatically. Or, tweak the parentheses and the indentation fixes
> itself accordingly. Google for demos of this.
I think that would drive me crazy!
>> Too many parentheses can make C code difficult to read. Difficult to
>> read translates to "more bugs". A knowledge of C's precedence levels,
>> at least to a moderate degree, can help avoid such bugs.
> Too much complexity in one expression makes it hard to read. Other
> than breaking it up into smaller expression, what can help is to
> split it into multiple lines and use indentation.
This is a common attitude, and I'm sure it is wrong a lot of the time.
Breaking up a complicated expression _fragments_ it - it spreads it over
a greater number of source code lines, some of which may not be visible
on the screen. While each fragment may in itself be easier to read, the
entire expression has become more difficult.
> Parenthesized expressions are much more amenable for splitting across
> lines and indenting than pure infix operator expressions.
I'm not sure I agree with this, my background being the maintainer of
Emacs's CC Mode.
How about a real world example? In the following (from Emacs's
syntax.c):
if (code == Sendcomment
&& SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style
&& (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ?
(nesting > 0 && --nesting == 0) : nesting < 0)
&& !comment_ender_quoted (from, from_byte, syntax))
, which is a moderately complicated example, extra parentheses around
the operands of the &&s would clutter up the code rather than clarifying
it. Yet the whole expression being on just five lines makes it
relatively easy to understand.
> --
> TXR Programming Language: http://nongnu.org/txr
> Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
--
Alan Mackenzie (Nuremberg, Germany).
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <480-992-1380@kylheku.com> |
|---|---|
| Date | 2022-04-14 21:05 +0000 |
| Message-ID | <20220414134305.103@kylheku.com> |
| In reply to | #165685 |
On 2022-04-14, Alan Mackenzie <acm@muc.de> wrote:
> Kaz Kylheku <480-992-1380@kylheku.com> wrote:
>> On 2022-04-13, Alan Mackenzie <acm@muc.de> wrote:
>>> Jens Stuckelberger <Jens_Stuckelberger@nowhere.net> wrote:
>>>> On 12 Apr 2022 13:03:39 GMT, Stefan Ram wrote:
>>>
>>>>> [...]
>
>>>> What for? Use parentheses - that's what they are there for.
>
>>> If you want to use parentheses, you should be writing in Lisp. ;-)
>
>> When you write in Lisp, most of the formatting is automatic and almost
>> always looks good, so you can concentrate on coding.
>
> Yes.
>
>> There are some new developments in this area in the last few years,
>> like the "parinfer" algorithm. "parinfer" creates a two-way linkage
>> between indentation and parentheses. Write your code, adjusting
>> indentation as you go, and the right parentheses materialize
>> automatically. Or, tweak the parentheses and the indentation fixes
>> itself accordingly. Google for demos of this.
>
> I think that would drive me crazy!
>
>>> Too many parentheses can make C code difficult to read. Difficult to
>>> read translates to "more bugs". A knowledge of C's precedence levels,
>>> at least to a moderate degree, can help avoid such bugs.
>
>> Too much complexity in one expression makes it hard to read. Other
>> than breaking it up into smaller expression, what can help is to
>> split it into multiple lines and use indentation.
>
> This is a common attitude, and I'm sure it is wrong a lot of the time.
> Breaking up a complicated expression _fragments_ it - it spreads it over
> a greater number of source code lines, some of which may not be visible
> on the screen.
A large expression won't be visible all at once, eithery way; if it is on
too few lines, they end up long. If we have multiple choices about
how to break it up, we can achieve a best fit.
> While each fragment may in itself be easier to read, the
> entire expression has become more difficult.
>
>> Parenthesized expressions are much more amenable for splitting across
>> lines and indenting than pure infix operator expressions.
>
> I'm not sure I agree with this, my background being the maintainer of
> Emacs's CC Mode.
>
> How about a real world example? In the following (from Emacs's
> syntax.c):
>
> if (code == Sendcomment
> && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style
> && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ?
> (nesting > 0 && --nesting == 0) : nesting < 0)
> && !comment_ender_quoted (from, from_byte, syntax))
Interestingly, you have unnecessary parentheses there, in the ternary:
a ? (b) : c
b is already flanked by a ? opener and : closer. I will keep those,
and for consistency parenthesize the (c) also.
> , which is a moderately complicated example, extra parentheses around
> the operands of the &&s would clutter up the code rather than clarifying
> it. Yet the whole expression being on just five lines makes it
> relatively easy to understand.
Proposal:
if ((code == Sendcomment) &&
(SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style) &&
(SYNTAX_FLAGS_COMMENT_NESTED (syntax)
? (nesting > 0 && --nesting == 0)
: (nesting < 0)) &&
(!comment_ender_quoted (from, from_byte, syntax)))
There is now consistent alignment. When we scan the left edge, we
don't see funny business like:
code ==
(SYNTAX...
SYNTAX..
I find that the infix operators are best put at the end of the previous
line, so that the left edge always begins with an operand, where we can
have a parenthesis for promoting alignment.
This can be visualized in chunks like this:
if ((...................) &&
(...............................................) &&
(....................................
? (.............................)
: (...........)) &&
(!.............................................)))
It is a regret that the && operators are not vertically aligned.
Not knowing quite where to put the infix operators is just the scourge
of infix:
(if (and (eq code 'sendcomment)
(eq (syntax-flags-comment-style syntax 0) 'style)
(if (syntax-flags-comment-nested syntax)
(if (plusp nesting) (zerop (dec nesting)))
(minus nesting))
(not (comment-gender-quoted from from-byte syntax)))
(then-do-this))
No neet to repeat the "and": just write it once and give it arguments.
line by line, indented to the same column.
If we want to be slightly sneaky, we take advantage of and being a
generalization of if:
(and (eq code 'sendcomment)
(eq (syntax-flags-comment-style syntax 0) 'style)
(if (syntax-flags-comment-nested syntax)
(if (plusp nesting) (zerop (dec nesting)))
(minus nesting))
(not (comment-gender-quoted from from-byte syntax))
(then-do-this))
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
[toc] | [prev] | [next] | [standalone]
| From | Alan Mackenzie <acm@muc.de> |
|---|---|
| Date | 2022-04-16 14:27 +0000 |
| Message-ID | <t3ejp3$2ch3$1@news.muc.de> |
| In reply to | #165685 |
Stefan Ram <ram@zedat.fu-berlin.de> wrote: > Alan Mackenzie <acm@muc.de> writes: >>Breaking up a complicated expression _fragments_ it > Example for the refactor "extract variable" in pseudocode: > return quantity * item_price - > max(0, quantity - 500) * item_price * 0.05 + > min(quantity * item_price * 0.1, 100); > ------------------> > const base_price = quantity * item_price; > const quantity_discount = > max( 0, quantity - 500 )* item_price * 0.05; > const shipping = min( base_price * 0.1, 100 ); > return base_price - quantity_discount + shipping; > . There is no reason to fall behind the state of the art. Whatever that might be in this particular matter. In your rearrangement of code, you have doubled its size. You have increased the number of operators used from 8 to 10, the number of lines of code from 3 to 5 and the number of statements from 1 to 4. Other things being equal, a more concise expression is easier to understand. No doubt you would here argue that the other things aren't equal, and I agree there is some merit to that argument. But the 5-line version is primarily easier for beginners to understand, who mentally break down program text to smaller units. An experienced programmer will prefer the 1-statement version - on encountering the 4-statement version she will subconsciously remark "do I have to go through all this verbiage _again_?". > Suggested reading: > Refactoring - Improving the Design of Existing Code > by Martin Fowler, > publishing house Addison-Wesley Educational Publishers Inc. > . Don't worry! It is written in an easy-to-understand way > so that most programmers can get it. No worries! I've had a copy of this book for many years, though it's some time since I've read it. Just because one can refactor code doesn't mean it's necessarily a good thing to do. Often it is. I think it was Steve Yegge in one of his blogs who noted that the problem with refactoring is that it often bloats code size. -- Alan Mackenzie (Nuremberg, Germany).
[toc] | [prev] | [next] | [standalone]
| From | Paul N <gw7rib@aol.com> |
|---|---|
| Date | 2022-04-23 10:23 -0700 |
| Message-ID | <6295432d-6ca9-49ea-b29c-858de4b65b75n@googlegroups.com> |
| In reply to | #165713 |
On Saturday, April 16, 2022 at 3:28:00 PM UTC+1, Alan Mackenzie wrote: > Stefan Ram <r...@zedat.fu-berlin.de> wrote: > > Alan Mackenzie <a...@muc.de> writes: > >>Breaking up a complicated expression _fragments_ it > > Example for the refactor "extract variable" in pseudocode: > > > return quantity * item_price - > > max(0, quantity - 500) * item_price * 0.05 + > > min(quantity * item_price * 0.1, 100); > > > ------------------> > > > const base_price = quantity * item_price; > > const quantity_discount = > > max( 0, quantity - 500 )* item_price * 0.05; > > const shipping = min( base_price * 0.1, 100 ); > > return base_price - quantity_discount + shipping; How about a compromise? return quantity * item_price - max(0, quantity - 500) * item_price * 0.05 // quantity discount + min(quantity * item_price * 0.1, 100); // shipping
[toc] | [prev] | [next] | [standalone]
| From | Alan Mackenzie <acm@muc.de> |
|---|---|
| Date | 2022-04-25 10:21 +0000 |
| Message-ID | <t45sne$2r7r$1@news.muc.de> |
| In reply to | #165879 |
Paul N <gw7rib@aol.com> wrote: > On Saturday, April 16, 2022 at 3:28:00 PM UTC+1, Alan Mackenzie wrote: >> Stefan Ram <r...@zedat.fu-berlin.de> wrote: >> > Alan Mackenzie <a...@muc.de> writes: >> >>Breaking up a complicated expression _fragments_ it >> > Example for the refactor "extract variable" in pseudocode: >> > return quantity * item_price - >> > max(0, quantity - 500) * item_price * 0.05 + >> > min(quantity * item_price * 0.1, 100); >> > ------------------> >> > const base_price = quantity * item_price; >> > const quantity_discount = >> > max( 0, quantity - 500 )* item_price * 0.05; >> > const shipping = min( base_price * 0.1, 100 ); >> > return base_price - quantity_discount + shipping; > How about a compromise? > return quantity * item_price > - max(0, quantity - 500) * item_price * 0.05 // quantity discount > + min(quantity * item_price * 0.1, 100); // shipping I think that is the best of all! Inserting brief, meaningful comments, as above, makes the thing easy to understand without bloating the code. I wish more people would code like this. -- Alan Mackenzie (Nuremberg, Germany).
[toc] | [prev] | [next] | [standalone]
| From | Vir Campestris <vir.campestris@invalid.invalid> |
|---|---|
| Date | 2022-04-25 16:43 +0100 |
| Message-ID | <t46fih$qkr$1@dont-email.me> |
| In reply to | #165916 |
On 25/04/2022 11:21, Alan Mackenzie wrote: > I think that is the best of all! Inserting brief, meaningful comments, > as above, makes the thing easy to understand without bloating the code. > I wish more people would code like this. Absolutely. It has the great advantage that the comments say what the code is _supposed_ to do. If they disagree that's a great big alarm bell to anyone looking for bugs. "self documenting code" doesn't do that. Andy
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2022-04-26 03:02 -0700 |
| Message-ID | <fcd20f44-525f-42da-b95b-301433a22ad5n@googlegroups.com> |
| In reply to | #165921 |
On Monday, 25 April 2022 at 16:43:25 UTC+1, Vir Campestris wrote: > On 25/04/2022 11:21, Alan Mackenzie wrote: > > I think that is the best of all! Inserting brief, meaningful comments, > > as above, makes the thing easy to understand without bloating the code. > > I wish more people would code like this. > Absolutely. > > It has the great advantage that the comments say what the code is > _supposed_ to do. If they disagree that's a great big alarm bell to > anyone looking for bugs. > > "self documenting code" doesn't do that. > However code tends to change over time. Since the compiler has no way of understanding the comments, it can't warn when a comment is not updated to reflect a change in the code. If you have a "self-documenting" language or system, like Doxygen, which ties comments to code features, then you can issue such warnings.
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <480-992-1380@kylheku.com> |
|---|---|
| Date | 2022-04-26 13:58 +0000 |
| Message-ID | <20220426065706.709@kylheku.com> |
| In reply to | #165921 |
On 2022-04-25, Vir Campestris <vir.campestris@invalid.invalid> wrote: > On 25/04/2022 11:21, Alan Mackenzie wrote: >> I think that is the best of all! Inserting brief, meaningful comments, >> as above, makes the thing easy to understand without bloating the code. >> I wish more people would code like this. > > Absolutely. > > It has the great advantage that the comments say what the code is > _supposed_ to do. If they disagree that's a great big alarm bell to > anyone looking for bugs. > > "self documenting code" doesn't do that. I will take a set of test cases that break right away, over some comment that started lying 13 years ago, but nobody noticed untl now. -- TXR Programming Language: http://nongnu.org/txr Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2022-04-25 14:48 -0700 |
| Message-ID | <86pml46dhb.fsf@linuxsc.com> |
| In reply to | #165879 |
Paul N <gw7rib@aol.com> writes:
> On Saturday, April 16, 2022 at 3:28:00 PM UTC+1, Alan Mackenzie wrote:
>
>> Stefan Ram <r...@zedat.fu-berlin.de> wrote:
>>
>>> Alan Mackenzie <a...@muc.de> writes:
>>>
>>>> Breaking up a complicated expression _fragments_ it
>>>
>>> Example for the refactor "extract variable" in pseudocode:
>>>
>>> return quantity * item_price -
>>> max(0, quantity - 500) * item_price * 0.05 +
>>> min(quantity * item_price * 0.1, 100);
>>>
>>> ------------------>
>>>
>>> const base_price = quantity * item_price;
>>> const quantity_discount =
>>> max( 0, quantity - 500 )* item_price * 0.05;
>>> const shipping = min( base_price * 0.1, 100 );
>>> return base_price - quantity_discount + shipping;
>
> How about a compromise?
>
> return quantity * item_price
> - max(0, quantity - 500) * item_price * 0.05 // quantity discount
> + min(quantity * item_price * 0.1, 100); // shipping
Speaking for myself I would rather see something like this:
[...]
unsigned n = quantity;
double price = item_price;
return sale_charge( n, price ) + shipping_charge( n, price );
double
sale_charge( unsigned n, double price ){
return base_charge( n, price ) - quantity_discount( n, price );
}
double
shipping_charge( unsigned n, double price ){
return min( base_charge( n, price ) * 0.1, 100.0 );
}
double
base_charge( unsigned n, double price ){
return n * price;
}
double
quantity_discount( unsigned n, double price ){
return n > 500 ? (n-500) * price * 0.05 : 0;
}
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2022-04-25 15:16 -0700 |
| Message-ID | <86levs6c6n.fsf@linuxsc.com> |
| In reply to | #165685 |
Alan Mackenzie <acm@muc.de> writes: > Kaz Kylheku <480-992-1380@kylheku.com> wrote: > >> On 2022-04-13, Alan Mackenzie <acm@muc.de> wrote: [...] >>> Too many parentheses can make C code difficult to read. Difficult >>> to read translates to "more bugs". A knowledge of C's precedence >>> levels, at least to a moderate degree, can help avoid such bugs. I definitely agree with this. >> Too much complexity in one expression makes it hard to read. I also agree with this. >> Other >> than breaking it up into smaller expression, what can help is to >> split it into multiple lines and use indentation. Sometimes, but rarely. In most cases another choice is better. > This is a common attitude, and I'm sure it is wrong a lot of the time. > Breaking up a complicated expression _fragments_ it - it spreads it over > a greater number of source code lines, some of which may not be visible > on the screen. While each fragment may in itself be easier to read, the > entire expression has become more difficult. > >> Parenthesized expressions are much more amenable for splitting across >> lines and indenting than pure infix operator expressions. Yuck. Any expression complicated enough to need parentheses _and_ multiple lines _and_ some indication of nesting merits rewriting into simpler components. > I'm not sure I agree with this, my background being the maintainer of > Emacs's CC Mode. > > How about a real world example? In the following (from Emacs's > syntax.c): > > if (code == Sendcomment > && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style > && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ? > (nesting > 0 && --nesting == 0) : nesting < 0) > && !comment_ender_quoted (from, from_byte, syntax)) > > , which is a moderately complicated example, extra parentheses around > the operands of the &&s would clutter up the code rather than clarifying > it. Yet the whole expression being on just five lines makes it > relatively easy to understand. I'm a longtime emacs user, and definitely a fan, but this code is horrible, on several different levels. I agree that adding extra parentheses around the &&s operands would make things worse, but it's already way below threshold for any reasonable standard of code review. Just my unabashed impressions.. :)
[toc] | [prev] | [next] | [standalone]
| From | Alan Mackenzie <acm@muc.de> |
|---|---|
| Date | 2022-04-26 10:34 +0000 |
| Message-ID | <t48hs2$urk$1@news.muc.de> |
| In reply to | #165935 |
Tim Rentsch <tr.17687@z991.linuxsc.com> wrote: > Alan Mackenzie <acm@muc.de> writes: >> Kaz Kylheku <480-992-1380@kylheku.com> wrote: >>> On 2022-04-13, Alan Mackenzie <acm@muc.de> wrote: > [...] >>>> Too many parentheses can make C code difficult to read. Difficult >>>> to read translates to "more bugs". A knowledge of C's precedence >>>> levels, at least to a moderate degree, can help avoid such bugs. > I definitely agree with this. >>> Too much complexity in one expression makes it hard to read. > I also agree with this. >>> Other >>> than breaking it up into smaller expression, what can help is to >>> split it into multiple lines and use indentation. > Sometimes, but rarely. In most cases another choice is better. >> This is a common attitude, and I'm sure it is wrong a lot of the time. >> Breaking up a complicated expression _fragments_ it - it spreads it over >> a greater number of source code lines, some of which may not be visible >> on the screen. While each fragment may in itself be easier to read, the >> entire expression has become more difficult. >>> Parenthesized expressions are much more amenable for splitting across >>> lines and indenting than pure infix operator expressions. > Yuck. Any expression complicated enough to need parentheses > _and_ multiple lines _and_ some indication of nesting merits > rewriting into simpler components. That was my point. Such rewriting bloats code, making it more difficult, as a whole, to understand. >> I'm not sure I agree with this, my background being the maintainer of >> Emacs's CC Mode. >> How about a real world example? In the following (from Emacs's >> syntax.c): >> if (code == Sendcomment >> && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style >> && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ? >> (nesting > 0 && --nesting == 0) : nesting < 0) >> && !comment_ender_quoted (from, from_byte, syntax)) >> , which is a moderately complicated example, extra parentheses around >> the operands of the &&s would clutter up the code rather than >> clarifying it. Yet the whole expression being on just five lines >> makes it relatively easy to understand. > I'm a longtime emacs user, and definitely a fan, but this code > is horrible, on several different levels. I disagree. The condition being coded is "horrible", so the code cannot be "nice". That condition is testing whether an ostensible comment ender actually ends a comment. There are several things to test, namely, that we're not trying to end a // comment with */, that the comment, if nested (this can happen, for example, in Lisp or Pascal), reaches the outer level of nesting, and that the comment ender isn't quoted. > I agree that adding extra parentheses around the &&s operands would > make things worse, .... Agreed. > .... but it's already way below threshold for any reasonable standard > of code review. This is simply untrue. That piece of code has been reviewed many times, including by me, and presents no particular difficulties in understanding. I don't think it could be written better. > Just my unabashed impressions.. :) -- Alan Mackenzie (Nuremberg, Germany).
[toc] | [prev] | [next] | [standalone]
| From | Ben <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2022-04-26 13:13 +0100 |
| Message-ID | <871qxkqbyj.fsf@bsb.me.uk> |
| In reply to | #165939 |
Alan Mackenzie <acm@muc.de> writes: > Tim Rentsch <tr.17687@z991.linuxsc.com> wrote: >> Alan Mackenzie <acm@muc.de> writes: >>> How about a real world example? In the following (from Emacs's >>> syntax.c): > >>> if (code == Sendcomment >>> && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style >>> && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ? >>> (nesting > 0 && --nesting == 0) : nesting < 0) >>> && !comment_ender_quoted (from, from_byte, syntax)) > >>> , which is a moderately complicated example, extra parentheses around >>> the operands of the &&s would clutter up the code rather than >>> clarifying it. Yet the whole expression being on just five lines >>> makes it relatively easy to understand. > >> I'm a longtime emacs user, and definitely a fan, but this code >> is horrible, on several different levels. > > I disagree. The condition being coded is "horrible", so the code cannot > be "nice". That condition is testing whether an ostensible comment ender > actually ends a comment. There are several things to test, namely, > that we're not trying to end a // comment with */, that the comment, if > nested (this can happen, for example, in Lisp or Pascal), reaches the > outer level of nesting, and that the comment ender isn't quoted. > >> I agree that adding extra parentheses around the &&s operands would >> make things worse, .... > > Agreed. > >> .... but it's already way below threshold for any reasonable standard >> of code review. > > This is simply untrue. That piece of code has been reviewed many times, > including by me, and presents no particular difficulties in > understanding. > > I don't think it could be written better. One concern is that this is not a plain condition since it sometimes has side effects. I'm comfortable with trivial cases of that (while (*cp++) ... for example) but there is more to check here. For example, it's not obvious that the conditional decrement must not happen when the rather opaque condition SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style is false. And I also find myself wondering why the value of nesting is significant when SYNTAX_FLAGS_COMMENT_NESTED (syntax) is false. Is it playing some dual role? -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Alan Mackenzie <acm@muc.de> |
|---|---|
| Date | 2022-04-26 17:25 +0000 |
| Message-ID | <t499v1$13fs$2@news.muc.de> |
| In reply to | #165940 |
Ben <ben.usenet@bsb.me.uk> wrote: > Alan Mackenzie <acm@muc.de> writes: >> Tim Rentsch <tr.17687@z991.linuxsc.com> wrote: >>> Alan Mackenzie <acm@muc.de> writes: >>>> How about a real world example? In the following (from Emacs's >>>> syntax.c): >>>> if (code == Sendcomment >>>> && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style >>>> && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ? >>>> (nesting > 0 && --nesting == 0) : nesting < 0) >>>> && !comment_ender_quoted (from, from_byte, syntax)) >>>> , which is a moderately complicated example, extra parentheses around >>>> the operands of the &&s would clutter up the code rather than >>>> clarifying it. Yet the whole expression being on just five lines >>>> makes it relatively easy to understand. >>> I'm a longtime emacs user, and definitely a fan, but this code >>> is horrible, on several different levels. >> I disagree. The condition being coded is "horrible", so the code cannot >> be "nice". That condition is testing whether an ostensible comment ender >> actually ends a comment. There are several things to test, namely, >> that we're not trying to end a // comment with */, that the comment, if >> nested (this can happen, for example, in Lisp or Pascal), reaches the >> outer level of nesting, and that the comment ender isn't quoted. >>> I agree that adding extra parentheses around the &&s operands would >>> make things worse, .... >> Agreed. >>> .... but it's already way below threshold for any reasonable standard >>> of code review. >> This is simply untrue. That piece of code has been reviewed many times, >> including by me, and presents no particular difficulties in >> understanding. >> I don't think it could be written better. > One concern is that this is not a plain condition since it sometimes > has side effects. I'm comfortable with trivial cases of that (while > (*cp++) ... for example) but there is more to check here. For example, > it's not obvious that the conditional decrement must not happen when > the rather opaque condition > SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style > is false. That condition just checks that we're not trying to close a C line comment with a */, for example. > And I also find myself wondering why the value of nesting is significant > when SYNTAX_FLAGS_COMMENT_NESTED (syntax) is false. Is it playing some > dual role? Yes, unfortunately so. There's an ad-hoc convention where this variable is -1 in non-nested comments. It plays a role where there are both nested and non-nested comments in a language (such as Common Lisp). > -- > Ben. -- Alan Mackenzie (Nuremberg, Germany).
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2022-04-26 06:12 -0700 |
| Message-ID | <c170f4ee-4c90-4291-af8b-478f98862cbfn@googlegroups.com> |
| In reply to | #165939 |
On Tuesday, 26 April 2022 at 11:34:55 UTC+1, Alan Mackenzie wrote:
> Tim Rentsch <tr.1...@z991.linuxsc.com> wrote:
> > Alan Mackenzie <a...@muc.de> writes:
>
> >> Kaz Kylheku <480-99...@kylheku.com> wrote:
>
> >>> On 2022-04-13, Alan Mackenzie <a...@muc.de> wrote:
>
> > [...]
>
> >>>> Too many parentheses can make C code difficult to read. Difficult
> >>>> to read translates to "more bugs". A knowledge of C's precedence
> >>>> levels, at least to a moderate degree, can help avoid such bugs.
>
> > I definitely agree with this.
>
> >>> Too much complexity in one expression makes it hard to read.
>
> > I also agree with this.
>
> >>> Other
> >>> than breaking it up into smaller expression, what can help is to
> >>> split it into multiple lines and use indentation.
>
> > Sometimes, but rarely. In most cases another choice is better.
>
> >> This is a common attitude, and I'm sure it is wrong a lot of the time.
> >> Breaking up a complicated expression _fragments_ it - it spreads it over
> >> a greater number of source code lines, some of which may not be visible
> >> on the screen. While each fragment may in itself be easier to read, the
> >> entire expression has become more difficult.
>
> >>> Parenthesized expressions are much more amenable for splitting across
> >>> lines and indenting than pure infix operator expressions.
>
> > Yuck. Any expression complicated enough to need parentheses
> > _and_ multiple lines _and_ some indication of nesting merits
> > rewriting into simpler components.
> That was my point. Such rewriting bloats code, making it more difficult,
> as a whole, to understand.
> >> I'm not sure I agree with this, my background being the maintainer of
> >> Emacs's CC Mode.
>
> >> How about a real world example? In the following (from Emacs's
> >> syntax.c):
>
> >> if (code == Sendcomment
> >> && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style
> >> && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ?
> >> (nesting > 0 && --nesting == 0) : nesting < 0)
> >> && !comment_ender_quoted (from, from_byte, syntax))
>
> >> , which is a moderately complicated example, extra parentheses around
> >> the operands of the &&s would clutter up the code rather than
> >> clarifying it. Yet the whole expression being on just five lines
> >> makes it relatively easy to understand.
>
> > I'm a longtime emacs user, and definitely a fan, but this code
> > is horrible, on several different levels.
> I disagree. The condition being coded is "horrible", so the code cannot
> be "nice". That condition is testing whether an ostensible comment ender
> actually ends a comment. There are several things to test, namely,
> that we're not trying to end a // comment with */, that the comment, if
> nested (this can happen, for example, in Lisp or Pascal), reaches the
> outer level of nesting, and that the comment ender isn't quoted.
> > I agree that adding extra parentheses around the &&s operands would
> > make things worse, ....
>
> Agreed.
>
> > .... but it's already way below threshold for any reasonable standard
> > of code review.
>
> This is simply untrue. That piece of code has been reviewed many times,
> including by me, and presents no particular difficulties in
> understanding.
>
> I don't think it could be written better.
>
/*
Does a comment ender token actually end a comment?
Params: code - the token (e.g. Sendcomment, Receivecomment [Malcolm ??])
syntax - syntax flags for current comment style (see SYNTAX_FLAGS)
style - current comment style [Malcolm, how does this differ from syntax?]
nesting - nesting level (note can be negative [Malcolm, explain how])
from - start of comment
from_byte - [Malcolm ???]
Returns: true if the comment ends, else false.
*/
bool is_comment_ended(int code, unsigned int syntax, unsigned int style, int nesting, char *from, char from_byte)
{
if (code != Sendcomment)
return false; // Not an end comment token
if (SYNTAX_FLAGS_COMMENT_STYLE(syntax, 0) != style)
return false; // Wrong comment style
if (SYNTAX_FLAGS_COMMENT_NESTED(syntax))
{
if (nesting != 1)
return false; // in a nested comment
}
else
{
if (nesting < 0)
return false; // [Malcolm - suspect nasty hack here, why can nesting go negative?]
}
if (comment_ender_quoted(from, from_byte, syntax))
return false; // Comment ender token is in quotes, not a comment ender
// All tests passed, must be valid comment ender.
return true;
}
Now you need to fix up the decrement on the nesting flag. That should be done outside
of the test, as it is logically separate from it.
The Malcolm comments are because Malcolm, who is totally unfamilar with the code, has
dived in and tried to fix it.Naturally they should be replaced.
[toc] | [prev] | [next] | [standalone]
| From | Alan Mackenzie <acm@muc.de> |
|---|---|
| Date | 2022-04-26 17:17 +0000 |
| Message-ID | <t499fu$13fs$1@news.muc.de> |
| In reply to | #165941 |
Malcolm McLean <malcolm.arthur.mclean@gmail.com> wrote:
> On Tuesday, 26 April 2022 at 11:34:55 UTC+1, Alan Mackenzie wrote:
>> Tim Rentsch <tr.1...@z991.linuxsc.com> wrote:
>> > Alan Mackenzie <a...@muc.de> writes:
>> >> Kaz Kylheku <480-99...@kylheku.com> wrote:
>> >>> On 2022-04-13, Alan Mackenzie <a...@muc.de> wrote:
>> > [...]
>> >>>> Too many parentheses can make C code difficult to read. Difficult
>> >>>> to read translates to "more bugs". A knowledge of C's precedence
>> >>>> levels, at least to a moderate degree, can help avoid such bugs.
>> > I definitely agree with this.
>> >>> Too much complexity in one expression makes it hard to read.
>> > I also agree with this.
>> >>> Other than breaking it up into smaller expression, what can help
>> >>> is to split it into multiple lines and use indentation.
>> > Sometimes, but rarely. In most cases another choice is better.
>> >> This is a common attitude, and I'm sure it is wrong a lot of the
>> >> time. Breaking up a complicated expression _fragments_ it - it
>> >> spreads it over a greater number of source code lines, some of
>> >> which may not be visible on the screen. While each fragment may in
>> >> itself be easier to read, the entire expression has become more
>> >> difficult.
>> >>> Parenthesized expressions are much more amenable for splitting
>> >>> across lines and indenting than pure infix operator expressions.
>> > Yuck. Any expression complicated enough to need parentheses _and_
>> > multiple lines _and_ some indication of nesting merits rewriting
>> > into simpler components.
>> That was my point. Such rewriting bloats code, making it more
>> difficult, as a whole, to understand.
>> >> I'm not sure I agree with this, my background being the maintainer
>> >> of Emacs's CC Mode.
>> >> How about a real world example? In the following (from Emacs's
>> >> syntax.c):
>> >> if (code == Sendcomment
>> >> && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style
>> >> && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ?
>> >> (nesting > 0 && --nesting == 0) : nesting < 0)
>> >> && !comment_ender_quoted (from, from_byte, syntax))
>> >> , which is a moderately complicated example, extra parentheses
>> >> around the operands of the &&s would clutter up the code rather
>> >> than clarifying it. Yet the whole expression being on just five
>> >> lines makes it relatively easy to understand.
>> > I'm a longtime emacs user, and definitely a fan, but this code
>> > is horrible, on several different levels.
>> I disagree. The condition being coded is "horrible", so the code
>> cannot be "nice". That condition is testing whether an ostensible
>> comment ender actually ends a comment. There are several things to
>> test, namely, that we're not trying to end a // comment with */, that
>> the comment, if nested (this can happen, for example, in Lisp or
>> Pascal), reaches the outer level of nesting, and that the comment
>> ender isn't quoted.
>> > I agree that adding extra parentheses around the &&s operands would
>> > make things worse, ....
>> Agreed.
>> > .... but it's already way below threshold for any reasonable
>> > standard of code review.
>> This is simply untrue. That piece of code has been reviewed many
>> times, including by me, and presents no particular difficulties in
>> understanding.
>> I don't think it could be written better.
> /*
> Does a comment ender token actually end a comment?
> Params: code - the token (e.g. Sendcomment, Receivecomment [Malcolm ??])
> syntax - syntax flags for current comment style (see SYNTAX_FLAGS)
> style - current comment style [Malcolm, how does this differ from syntax?]
> nesting - nesting level (note can be negative [Malcolm, explain how])
> from - start of comment
> from_byte - [Malcolm ???]
> Returns: true if the comment ends, else false.
> */
> bool is_comment_ended(int code, unsigned int syntax, unsigned int style, int nesting, char *from, char from_byte)
> {
> if (code != Sendcomment)
> return false; // Not an end comment token
> if (SYNTAX_FLAGS_COMMENT_STYLE(syntax, 0) != style)
> return false; // Wrong comment style
> if (SYNTAX_FLAGS_COMMENT_NESTED(syntax))
> {
> if (nesting != 1)
> return false; // in a nested comment
> }
> else
> {
> if (nesting < 0)
> return false; // [Malcolm - suspect nasty hack here, why can nesting go negative?]
> }
> if (comment_ender_quoted(from, from_byte, syntax))
> return false; // Comment ender token is in quotes, not a comment ender
> // All tests passed, must be valid comment ender.
> return true;
> }
You make my point more eloquently than I could. ;-) 5 lines have become
20 non-comment lines plus comments, and several more lines will be needed
to handle the decrementation of the variable `nesting'. These 20 lines
have been fragmented from the context where they formally belonged. Or,
in plain English, you've got to keep moving backwards and forwards
between this new functiom and the calling point to understand things.
This new function is a bit like the long gentle ramp often seen at the
entrance to public buildings for the benefit of wheelchair users. It is
less effort to walk up than climbing the stairs, since each step is
gentler, but the total time and energy expended is much more. Otherwise,
able bodied people would walk up the ramp rather than climbing the
stairs. In this analogy, the stairs correspond with the five line
original piece of code.
> Now you need to fix up the decrement on the nesting flag. That should
> be done outside of the test, as it is logically separate from it.
Perhaps, perhaps not. If one construes the 5-line original as "handle a
comment closer", then decrementing the nesting level is an integral part
of it.
> The Malcolm comments are because Malcolm, who is totally unfamilar with
> the code, has dived in and tried to fix it.Naturally they should be
> replaced.
:-)
There're quite a lot of pieces of code like my original citation in the
Emacs C code. I can't remember there ever being a call to make it less
compact.
--
Alan Mackenzie (Nuremberg, Germany).
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c
csiph-web