• Re: How About Disallowing Assignments In Expressions?

    From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Fri Feb 9 01:13:23 2024
    On 2024-02-09, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    If you want to make C a safer language, one obvious thing is to disallow using “=” in the middle of an expression. Instead of returning the value of the expression, have it return void. Or just disallow it syntactically altogether.

    Sure, you may still want to write something like

    a = b = c;

    but Python has found a way to allow that, without saying that “b = c” has to return a value.

    Python's original solution is stupid. All they had to do is to use :=
    for assignment, and leave = as a comparison.

    ... and that's what they did now, as of Python 3.8.

    There is a := assignment that can be used in the middle of an
    expression. This is given the idiotic nickname "walrus operator".

    := can be used in the middle of expressions.

    Except they can't drop the old = assignment due to backward
    compatibility.

    Walrus is what should have been assignment in the first place.
    But because Van Possum was coding Python in C, he just aped
    some C choices into the language.

    (I'm guessing that he knew that the first people to get their hands on
    Python and popularize it would be C-and-Unix people, who would
    balk at a := operator.)

    By the way, assignment in the middle of expressions comes from Lisp.
    Basically the idea that everything is an expression, even things
    that perform side effects or behave like statements. The ternary
    operator comes from Lisp: (if expr then else).

    [CLISP]
    (let ((i 0)) (list (incf i) (incf i) (incf i)))
    (1 2 3)

    You're unlikely to type setf or incf when you wanted a comparison.
    ANSI Common Lisp is strictly evaluated so the above is required
    to produce (1 2 3) and not (2 1 3) or whatever. Stuffing side
    effects into Lisp expressions is less risky than in C.

    (Not so with Scheme: in Scheme, the evaluation order of function
    arguemnts is unspecified, like in C!)

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Fri Feb 9 00:39:02 2024
    If you want to make C a safer language, one obvious thing is to disallow
    using “=” in the middle of an expression. Instead of returning the value
    of the expression, have it return void. Or just disallow it syntactically altogether.

    Sure, you may still want to write something like

    a = b = c;

    but Python has found a way to allow that, without saying that “b = c” has to return a value.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Malcolm McLean on Fri Feb 9 02:10:31 2024
    On Fri, 9 Feb 2024 00:53:42 +0000, Malcolm McLean wrote:

    while( (ch = fgetc(fp)) != EOF)

    is the idiomatic way of accessing a stream a character by character in
    C. So you would disallow this.

    Yes!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Fri Feb 9 09:27:55 2024
    On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow using “=” in the middle of an expression. Instead of returning the value of the expression, have it return void. Or just disallow it syntactically altogether.


    I think that C would have been a safer language if assignment had been a statement, not an expression (such as is the case in Pascal, for
    example). But I don't think it is remotely feasible to change this in C
    - you are fifty years too late.

    The nearest you can come to changes like this in C would be optional
    warnings or checks in compilers and static analysers.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to David Brown on Fri Feb 9 10:16:49 2024
    David Brown <david.brown@hesbynett.no> writes:

    On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow
    using “=” in the middle of an expression. Instead of returning the value >> of the expression, have it return void. Or just disallow it syntactically
    altogether.

    I think that C would have been a safer language if assignment had been a statement, not an expression

    Surely someone has studied this, no? There must be some paper
    describing bugs "in the wild"* and categorising them by what language
    features would have made them either impossible or less likely. I don't
    know of any (it was not even remotely my field) but there is such a
    large pool of data out there I can't imagine that it's not been done.

    * I mean to exclude bugs that get found early. For example, I've never
    seen a = vs. == bug that survived even the most crude tests (and most,
    like many other typo bugs, don't survive compilation without being
    picked up).

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Harnden@21:1/5 to Ben Bacarisse on Fri Feb 9 10:36:10 2024
    On 09/02/2024 10:16, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow >>> using “=” in the middle of an expression. Instead of returning the value
    of the expression, have it return void. Or just disallow it syntactically >>> altogether.

    I think that C would have been a safer language if assignment had been a
    statement, not an expression

    Surely someone has studied this, no? There must be some paper
    describing bugs "in the wild"* and categorising them by what language features would have made them either impossible or less likely. I don't
    know of any (it was not even remotely my field) but there is such a
    large pool of data out there I can't imagine that it's not been done.

    * I mean to exclude bugs that get found early. For example, I've never
    seen a = vs. == bug that survived even the most crude tests (and most,
    like many other typo bugs, don't survive compilation without being
    picked up).


    This is what ChatGPT says ...

    User
    Can you list C language bugs, categorising them by what language
    features would have made them either impossible or less likely.

    ChatGPT
    Certainly! Here are some common bugs in C categorized by language
    features that could have prevented them or made them less likely:

    Null Pointer Dereference:
    Language Feature: Safe pointer handling like in Rust or smart pointers
    in C++. Features like optional nullability annotations or language
    constructs that enforce non-null pointers can help prevent null pointer dereference bugs.

    Buffer Overflows:
    Language Feature: Bounds checking in arrays. Languages like Rust have
    built-in checks to prevent buffer overflows at compile-time.
    Safe string handling functions like those provided by libraries such as
    Safe C String Library (SCL) or SafeLib.

    Memory Leaks:
    Language Feature: Automatic memory management like garbage collection or
    smart pointers. Languages like Java, C#, and modern C++ with RAII
    (Resource Acquisition Is Initialization) significantly reduce the
    occurrence of memory leaks.

    Use After Free:
    Language Feature: Automated memory management, such as garbage
    collection, or ownership tracking systems like those found in Rust's
    ownership model.

    Uninitialized Variables:
    Language Feature: Initialization guarantees or compiler warnings for uninitialized variables. Tools like static code analyzers or compilers
    with strong type checking can help detect such issues.

    Type Safety Violations:
    Language Feature: Strong static typing. Languages like Java, C#, or Rust enforce stronger type safety, reducing the likelihood of type-related bugs.

    Race Conditions:
    Language Feature: Built-in support for concurrent programming paradigms,
    such as message passing (e.g., Erlang) or ownership model (e.g., Rust),
    or immutability (e.g., functional programming languages like Haskell).

    Integer Overflows:
    Language Feature: Safe arithmetic operations. Languages like Rust
    provide safe arithmetic operations that panic on overflow, preventing
    undefined behavior.

    Resource Management Issues (e.g., File Handles, Sockets):
    Language Feature: RAII (Resource Acquisition Is Initialization) or using constructs like "defer" in Go. Languages like Rust with its ownership
    model can enforce proper resource management.

    Unprotected Access to Shared Resources:
    Language Feature: Mechanisms for synchronization and concurrent access
    control, such as locks, semaphores, or higher-level constructs like
    channels in Go or message passing in Erlang.

    Floating Point Precision Errors:
    Language Feature: Enhanced floating-point arithmetic support or arbitrary-precision arithmetic libraries. Languages like Python or
    libraries like GNU MPFR provide arbitrary-precision arithmetic, reducing precision errors.

    Pointer Arithmetic Errors:
    Language Feature: Restricted or controlled pointer arithmetic. Safe
    pointer operations and bounds checking can prevent pointer arithmetic
    errors.

    By incorporating these language features or using languages with
    built-in protections against common programming errors, developers can significantly reduce the likelihood of encountering these bugs.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Richard Harnden on Fri Feb 9 13:17:59 2024
    Richard Harnden <richard.nospam@gmail.invalid> writes:

    On 09/02/2024 10:16, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow >>>> using “=” in the middle of an expression. Instead of returning the value
    of the expression, have it return void. Or just disallow it syntactically >>>> altogether.

    I think that C would have been a safer language if assignment had been a >>> statement, not an expression
    Surely someone has studied this, no? There must be some paper
    describing bugs "in the wild"* and categorising them by what language
    features would have made them either impossible or less likely. I don't
    know of any (it was not even remotely my field) but there is such a
    large pool of data out there I can't imagine that it's not been done.
    * I mean to exclude bugs that get found early. For example, I've never
    seen a = vs. == bug that survived even the most crude tests (and most,
    like many other typo bugs, don't survive compilation without being
    picked up).

    This is what ChatGPT says ...

    Seriously? You do know how large language models work, yes?

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Ben Bacarisse on Fri Feb 9 14:43:54 2024
    On 09/02/2024 11:16, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow >>> using “=” in the middle of an expression. Instead of returning the value
    of the expression, have it return void. Or just disallow it syntactically >>> altogether.

    I think that C would have been a safer language if assignment had been a
    statement, not an expression

    Surely someone has studied this, no? There must be some paper
    describing bugs "in the wild"* and categorising them by what language features would have made them either impossible or less likely. I don't
    know of any (it was not even remotely my field) but there is such a
    large pool of data out there I can't imagine that it's not been done.

    I think it is very difficult to get good statistics on this kind of
    thing. You can't really do a controlled study comparing one group
    programming in "C where assignment is an expression" with a group
    programming in "C where assignment is a statement". And you certainly
    can't do a double-blind placebo controlled test!

    There are plenty of coding standards which ban the use of the results of assignment expressions, and I think there is little doubt that stricter
    coding standards reduce at least some kinds of errors in code. But it
    would be impossible to isolate the effect of one particular rule.

    If someone knows about such studies, it would be great to hear about
    them - failing that, guesses and gut feelings based on personal
    experience is about as good as we can get.


    * I mean to exclude bugs that get found early. For example, I've never
    seen a = vs. == bug that survived even the most crude tests (and most,
    like many other typo bugs, don't survive compilation without being
    picked up).


    I would agree with that.

    However, I /have/ seen such bugs in code that has been written and
    deployed, precisely because even the most crude tests and static
    checking where not employed.

    Far and away the biggest steps towards "safe C" is for people to use
    good development practices, including good testing, good static error
    checking, appropriate training, code reviews, etc. The unfortunate
    reality is that there are many programmers who don't use such practices,
    or don't use them correctly. And I don't think a change to how
    assignment works would make a noticeable difference to this much larger
    and more general problem.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Harnden@21:1/5 to Ben Bacarisse on Fri Feb 9 14:08:48 2024
    On 09/02/2024 13:17, Ben Bacarisse wrote:
    Richard Harnden <richard.nospam@gmail.invalid> writes:

    On 09/02/2024 10:16, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow >>>>> using “=” in the middle of an expression. Instead of returning the value
    of the expression, have it return void. Or just disallow it syntactically >>>>> altogether.

    I think that C would have been a safer language if assignment had been a >>>> statement, not an expression
    Surely someone has studied this, no? There must be some paper
    describing bugs "in the wild"* and categorising them by what language
    features would have made them either impossible or less likely. I don't >>> know of any (it was not even remotely my field) but there is such a
    large pool of data out there I can't imagine that it's not been done.
    * I mean to exclude bugs that get found early. For example, I've never
    seen a = vs. == bug that survived even the most crude tests (and most,
    like many other typo bugs, don't survive compilation without being
    picked up).

    This is what ChatGPT says ...

    Seriously? You do know how large language models work, yes?


    Sure: It has read the entire internet - especially the the bit about
    how Rust is better than C, apparently - and regurgitates the same.

    Considering my five seconds of effort; I didn't think it was /that/ bad
    of a list.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Lawrence D'Oliveiro on Fri Feb 9 15:43:55 2024
    On 09/02/2024 00:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow using “=” in the middle of an expression. Instead of returning the value of the expression, have it return void. Or just disallow it syntactically altogether.

    Sure, you may still want to write something like

    a = b = c;

    but Python has found a way to allow that, without saying that “b = c” has to return a value.


    I suspect that quite a number of existing programs will become invalid.

    But what is the problem with 'a = b = c'? The real problems with
    assignments inside expressions is when you accidentally use '=' instead
    of '=='. That's due to a poor choice of syntax.

    What I wouldn't care about banning however is this:

    a += b += c;

    Because it's just confusing. If you don't think so, consider a, b, c all
    having different numerical types.

    (It's also a bit of a pain when implementing a language that allows it.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to bart on Fri Feb 9 16:57:15 2024
    On 09/02/2024 16:43, bart wrote:
    On 09/02/2024 00:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow
    using “=” in the middle of an expression. Instead of returning the value >> of the expression, have it return void. Or just disallow it syntactically
    altogether.

    Sure, you may still want to write something like

         a = b = c;

    but Python has found a way to allow that, without saying that “b = c” has
    to return a value.


    I suspect that quite a number of existing programs will become invalid.

    Yes. It's not used often IME, and would be easy to fix, but you only
    need it once in a program to make such a suggestion a breaking change.


    But what is the problem with 'a = b = c'?

    My preference is to do one thing at a time - then it's clear what is
    going on. I think it is rare that you could make use of such chained assignment, and even rarer where you could reasonably argue that it is
    clearer than simply writing two separate lines. (And when you use a
    "declare variables when you are ready to initialise them" style, it is
    much more natural to use two lines.)

    About the only time when I think you might say that chained assignment
    is clearer is for very closely related variables set to zero :

    int x, y, z;
    x = y = z = 0;

    I would probably be happy to throw that clear usage out in order to stop
    people making unclear usage of chained assignment.

    The real problems with
    assignments inside expressions is when you accidentally use '=' instead
    of '=='. That's due to a poor choice of syntax.


    That's a non-issue for anyone who can use a compiler with static error checking, because it is almost always easy to spot automatically.

    What I wouldn't care about banning however is this:

        a += b += c;

    Because it's just confusing. If you don't think so, consider a, b, c all having different numerical types.

    Agreed 100%.

    (I hope that didn't shock you too much!)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to David Brown on Fri Feb 9 16:35:45 2024
    On 2024-02-09, David Brown <david.brown@hesbynett.no> wrote:
    On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow
    using “=” in the middle of an expression. Instead of returning the value >> of the expression, have it return void. Or just disallow it syntactically
    altogether.


    I think that C would have been a safer language if assignment had been a statement, not an expression (such as is the case in Pascal, for
    example). But I don't think it is remotely feasible to change this in C
    - you are fifty years too late.

    It was probably Lisp that introduced the idea of assignment being an
    expression (due to everything being an expression). It's a safe
    language, and not less safe on that account. This is because you are vanishingly unlikely to accidentally write (setq a b) when you intended
    (eq a b), and if that were to happen, another pair of reviewing eyes
    would likely not gloss over it.

    Python has now reintroduced a form of assignment you can use
    in the middle of an expression; the token is := which is unlikely
    to be used by mistake instead of an equality test or whatnot.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Keith Thompson on Fri Feb 9 17:38:07 2024
    On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    I suggest that the bug of using "=" where "==" was intended occurs
    almost exclusively among inexperienced C programmers, particularly those
    who are inexperienced with programming in general.

    Almost exclusively. I've had this sneak upon me maybe once or twice in
    the past 15 years. GCC warns well in most situations in which the typo
    is made, so it doesn't easily sneak through.

    This is in the bug category of "used to be menacing before we had better diagnostics", along with forgetting to include <stdlib.h> before using
    malloc.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Malcolm McLean on Fri Feb 9 18:02:34 2024
    On 09/02/2024 17:22, Malcolm McLean wrote:
    On 09/02/2024 17:09, Keith Thompson wrote:

    (It's possible I'm overgeneralizing.  For example, a programmer who
    commonly switches between C and other languages might still mix up "="
    and "==" occasionally.)


    I had do to my PhD in Fortran, for my sins. It's := for assignment and =
    for comparison, and when I switched back to C, I was always writing "="
    for "==".

    Fortran must have changed considerably since I last used it.

    It was "=" to assign, and ".EQ." for equality.

    I assume you mean another language. My normal one does use := and = like
    that, and switching to/from C gives problems: you write = in C instead
    of ==, and in mine I'd write = instead of :=. However:

    a = b

    was a no-op in my language (or rather, it compared then discarded the
    result), leading to puzzling bugs. Now I usually detect such statements.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Kaz Kylheku on Fri Feb 9 18:04:41 2024
    On 09/02/2024 17:38, Kaz Kylheku wrote:
    On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    I suggest that the bug of using "=" where "==" was intended occurs
    almost exclusively among inexperienced C programmers, particularly those
    who are inexperienced with programming in general.

    Almost exclusively. I've had this sneak upon me maybe once or twice in
    the past 15 years. GCC warns well in most situations in which the typo
    is made, so it doesn't easily sneak through.

    This is in the bug category of "used to be menacing before we had better diagnostics", along with forgetting to include <stdlib.h> before using malloc.


    How does gcc know whether 'if (a = b)' is meant to be an assignment or comparison?

    Simply warning on the possibility is not going to be helpful, because
    you will be swamped with output that may hide more important matters.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fir@21:1/5 to bart on Fri Feb 9 19:46:09 2024
    bart wrote:
    On 09/02/2024 17:22, Malcolm McLean wrote:
    On 09/02/2024 17:09, Keith Thompson wrote:

    (It's possible I'm overgeneralizing. For example, a programmer who
    commonly switches between C and other languages might still mix up "="
    and "==" occasionally.)


    I had do to my PhD in Fortran, for my sins. It's := for assignment and
    = for comparison, and when I switched back to C, I was always writing
    "=" for "==".

    Fortran must have changed considerably since I last used it.

    It was "=" to assign, and ".EQ." for equality.

    I assume you mean another language. My normal one does use := and = like that, and switching to/from C gives problems: you write = in C instead
    of ==, and in mine I'd write = instead of :=. However:

    a = b

    was a no-op in my language (or rather, it compared then discarded the result), leading to puzzling bugs. Now I usually detect such statements.

    as some maybe know im from time to time write my compiler on c based
    langage and also i hardly think how to simplify and expand syntax and construction

    as to this problem how ewentually replace = and == at present time i
    just found this problem unresolvable :c


    what i think = coud eventually stay though it also could have
    alternative.. == is in turn clearly wrong but one would need unicode
    sign for this i guess.. there is need for some sign like = with a small
    "?" above it

    ≟ possibly

    a≟b

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to bart on Fri Feb 9 18:52:35 2024
    On 2024-02-09, bart <bc@freeuk.com> wrote:
    On 09/02/2024 17:38, Kaz Kylheku wrote:
    On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    I suggest that the bug of using "=" where "==" was intended occurs
    almost exclusively among inexperienced C programmers, particularly those >>> who are inexperienced with programming in general.

    Almost exclusively. I've had this sneak upon me maybe once or twice in
    the past 15 years. GCC warns well in most situations in which the typo
    is made, so it doesn't easily sneak through.

    This is in the bug category of "used to be menacing before we had better
    diagnostics", along with forgetting to include <stdlib.h> before using
    malloc.


    How does gcc know whether 'if (a = b)' is meant to be an assignment or comparison?

    The point is that this is not knowable; it is ambiguous. (Perhaps
    the current maintainer of the code doesn't even know).

    That's why it deserves a diagnostic.

    Someone will have to look at it and figure out whether it should
    be the assignment or comparison.

    Simply warning on the possibility is not going to be helpful, because
    you will be swamped with output that may hide more important matters.

    So you might suspect, but that turns out to be wrong.

    GCC assumes that this is a mistake and warns about it, suggesting
    that parentheses be put around the assignment if it is intended.

    warning: suggest parentheses around assignment used as truth value
    [-Wparentheses]

    This -Wparentheses is included in -Wall. Thus:

    if (a = b) // warns

    if ((a = b)) // shuts up

    this heuristic turns out to be good. The diagnostic rarely occurs in the
    first place, and the fix is trivial.

    Parentheses normally disambiguate associativity/precedence. So by a kind
    of metaphor, here they are used to fix a psychological rather than
    grammatical ambiguity.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Keith Thompson on Fri Feb 9 20:20:42 2024
    On 09/02/2024 18:09, Keith Thompson wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow >>> using “=” in the middle of an expression. Instead of returning the value
    of the expression, have it return void. Or just disallow it syntactically >>> altogether.

    I think that C would have been a safer language if assignment had been
    a statement, not an expression (such as is the case in Pascal, for
    example). But I don't think it is remotely feasible to change this in
    C - you are fifty years too late.

    The nearest you can come to changes like this in C would be optional
    warnings or checks in compilers and static analysers.

    I suggest that the bug of using "=" where "==" was intended occurs
    almost exclusively among inexperienced C programmers, particularly those
    who are inexperienced with programming in general.

    It can also happen accidentally - even experienced programmers can make
    typos which they don't spot immediately. But experienced programmers
    will normally be using tools that will find such mistakes very quickly.



    It's a mistake that's made because the programmer assumes that "="
    is a comparison operator, as it is in mathematics and in some other programming languages. It's an easy and understandable mistake
    to make, but any reasonably experienced C programmer will have
    internalized the fact that "=" means assignment, not comparison.
    To a newbie, `if (x = y)` *looks like* a comparison. To an
    experienced C programmer it doesn't.

    (It's possible I'm overgeneralizing. For example, a programmer who
    commonly switches between C and other languages might still mix up "="
    and "==" occasionally.)

    If C had used ":=" for assignment and "=" for comparison (and "=="
    probably not used for anything), the problem would never have come up, because ":=" doesn't look like a comparison even to a newbie. But it's
    far too late to fix that in any language called "C".


    Yes.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Blue-Maned_Hawk@21:1/5 to All on Fri Feb 9 19:47:45 2024
    There are too many situations where assignment being an expression is a
    useful facet of the language; i am not willing to sacrifice that for an ill-defined ideal of “safety”.



    --
    Blue-Maned_Hawk│shortens to Hawk│/ blu.mɛin.dʰak/ │he/him/his/himself/Mr. blue-maned_hawk.srht.site
    It cost 53 million pounds just to cancel.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fir@21:1/5 to fir on Fri Feb 9 21:48:57 2024
    fir wrote:
    bart wrote:
    On 09/02/2024 17:22, Malcolm McLean wrote:
    On 09/02/2024 17:09, Keith Thompson wrote:

    (It's possible I'm overgeneralizing. For example, a programmer who
    commonly switches between C and other languages might still mix up "=" >>>> and "==" occasionally.)


    I had do to my PhD in Fortran, for my sins. It's := for assignment and
    = for comparison, and when I switched back to C, I was always writing
    "=" for "==".

    Fortran must have changed considerably since I last used it.

    It was "=" to assign, and ".EQ." for equality.

    I assume you mean another language. My normal one does use := and = like
    that, and switching to/from C gives problems: you write = in C instead
    of ==, and in mine I'd write = instead of :=. However:

    a = b

    was a no-op in my language (or rather, it compared then discarded the
    result), leading to puzzling bugs. Now I usually detect such statements.

    as some maybe know im from time to time write my compiler on c based
    langage and also i hardly think how to simplify and expand syntax and construction

    as to this problem how ewentually replace = and == at present time i
    just found this problem unresolvable :c


    what i think = coud eventually stay though it also could have
    alternative.. == is in turn clearly wrong but one would need unicode
    sign for this i guess.. there is need for some sign like = with a small
    "?" above it

    ≟ possibly

    a≟b

    in fact i could conclude:

    a=b assigment should be something that resembles "=" but in the
    direction of <- or something like that
    a==b comparsion should be something that resembles "=" but in the
    direction of something like comparsion sign

    bioth obviously should be one sign..in asci there is no way to resolve
    that i guess

    i guess even = could be for comparsion but yopu would need another =
    more in direction like <- (but not quite) for assigments

    in asci that cont be done properly (i think)
    in asci you only can have some aproximation of this, and i probably
    would hold a=b for assigment and use a?=b for comparison (but only as approximation and use unicode for full 'version')

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fir@21:1/5 to Keith Thompson on Fri Feb 9 23:11:16 2024
    Keith Thompson wrote:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    [...]
    If C had used ":=" for assignment and "=" for comparison (and "=="
    probably not used for anything), the problem would never have come up,
    because ":=" doesn't look like a comparison even to a newbie. But it's
    far too late to fix that in any language called "C".

    If I were designing a new language, I'd consider using ":=" for
    assignment, "==" for equality, and not using "=" for anything.

    In (nearly?) all languages I'm aware of, ":=" either doesn't exist or
    means assignment, and "==" either doesn't exist or means equality. I'd
    avoid "=" because it's ambiguous across languages (and that's almost
    entirely C's fault, inherited from B).

    Historically, C's predecessor B used "=" for assignment and "==" for equality, while B's predecessor BCPL used ":=" for assignment and "="
    for equality.



    it io not in the spirit of c (and c design intentions) SO
    people like you or the guy who want to consider to remove
    assigments in expressions dont understand c
    (i understand it at least better, question is if fully)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Keith Thompson on Fri Feb 9 22:14:19 2024
    On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    [...]
    If C had used ":=" for assignment and "=" for comparison (and "=="
    probably not used for anything), the problem would never have come up,
    because ":=" doesn't look like a comparison even to a newbie. But it's
    far too late to fix that in any language called "C".

    If I were designing a new language, I'd consider using ":=" for
    assignment, "==" for equality, and not using "=" for anything.

    In (nearly?) all languages I'm aware of, ":=" either doesn't exist or
    means assignment, and "==" either doesn't exist or means equality. I'd
    avoid "=" because it's ambiguous across languages (and that's almost
    entirely C's fault, inherited from B).

    Some of the credit must go to classic BASIC!

    I seem to remember than in classic, line-numbered BASICs on 8 bit
    micros, the = token was used both for assignment and comparison!

    300 I = I + 1
    310 IF I = 10 GOTO 340

    If you have a dedicated assignment statement, you can pull this kind
    of stunt. Just like C can distinguish initialization from assignment.


    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Fri Feb 9 21:31:18 2024
    On Fri, 9 Feb 2024 19:47:45 -0000 (UTC), Blue-Maned_Hawk wrote:

    There are too many situations where assignment being an expression is a useful facet of the language; i am not willing to sacrifice that for an ill-defined ideal of “safety”.

    If you consider it “ill-defined”, consider the number of people who have developed the habit of writing

    if (NULL == p) ...

    instead of the more natural

    if (p == NULL) ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to David Brown on Fri Feb 9 22:43:08 2024
    David Brown <david.brown@hesbynett.no> writes:

    On 09/02/2024 11:16, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow >>>> using “=” in the middle of an expression. Instead of returning the value
    of the expression, have it return void. Or just disallow it syntactically >>>> altogether.

    I think that C would have been a safer language if assignment had been a >>> statement, not an expression
    Surely someone has studied this, no? There must be some paper
    describing bugs "in the wild"* and categorising them by what language
    features would have made them either impossible or less likely. I don't
    know of any (it was not even remotely my field) but there is such a
    large pool of data out there I can't imagine that it's not been done.

    I think it is very difficult to get good statistics on this kind of thing. You can't really do a controlled study comparing one group programming in
    "C where assignment is an expression" with a group programming in "C where assignment is a statement". And you certainly can't do a double-blind placebo controlled test!

    True. But there are literally thousands of significant bugs logged
    every day in key systems components. A retrospective analysis of these
    would, I think, be very interesting.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Richard Harnden on Fri Feb 9 22:41:03 2024
    Richard Harnden <richard.nospam@gmail.invalid> writes:

    On 09/02/2024 13:17, Ben Bacarisse wrote:
    Richard Harnden <richard.nospam@gmail.invalid> writes:

    On 09/02/2024 10:16, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow >>>>>> using “=” in the middle of an expression. Instead of returning the value
    of the expression, have it return void. Or just disallow it syntactically
    altogether.

    I think that C would have been a safer language if assignment had been a >>>>> statement, not an expression
    Surely someone has studied this, no? There must be some paper
    describing bugs "in the wild"* and categorising them by what language
    features would have made them either impossible or less likely. I don't >>>> know of any (it was not even remotely my field) but there is such a
    large pool of data out there I can't imagine that it's not been done.
    * I mean to exclude bugs that get found early. For example, I've never >>>> seen a = vs. == bug that survived even the most crude tests (and most, >>>> like many other typo bugs, don't survive compilation without being
    picked up).

    This is what ChatGPT says ...
    Seriously? You do know how large language models work, yes?


    Sure: It has read the entire internet - especially the the bit about how Rust is better than C, apparently - and regurgitates the same.

    Considering my five seconds of effort; I didn't think it was /that/ bad of
    a list.

    Yes, it's a good summary of what passes for "common knowledge". But I
    was talking about something else altogether -- actual bugs found in real
    code, maybe taken from an analysis of security advisories. How many can
    (to take one example) be attributed, in whole or in part, for using
    assignment in a larger expression?

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Sat Feb 10 03:06:48 2024
    On 2024-02-10, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:

    But it's far too late to fix that in any language called "C".

    I had a look at the MISRA specs, and they say “assignment operators shall not be used in expressions that yield a boolean value”.

    I skimmed through MISRA some years ago and wasn't very impressed by it, actually.

    It's full the kind of coding rules that you might want to enforce
    if you have to produce a bunch of C, and the only people you are given
    are ones who shouldn't even remotely be doing such a thing.

    We might call those coders Les MISRAbles. :)

    The rules are not suitable for people who know what they are doing
    (and use tools effectively) and detrimental to the code.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Sat Feb 10 02:37:30 2024
    On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:

    But it's far too late to fix that in any language called "C".

    I had a look at the MISRA specs, and they say “assignment operators shall
    not be used in expressions that yield a boolean value”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Blue-Maned_Hawk@21:1/5 to Lawrence D'Oliveiro on Sat Feb 10 08:05:53 2024
    Lawrence D'Oliveiro wrote:

    On Fri, 9 Feb 2024 19:47:45 -0000 (UTC), Blue-Maned_Hawk wrote:

    There are too many situations where assignment being an expression is a
    useful facet of the language; i am not willing to sacrifice that for an
    ill-defined ideal of “safety”.

    If you consider it “ill-defined”, consider the number of people who have developed the habit of writing

    if (NULL == p) ...

    instead of the more natural

    if (p == NULL) ...

    Y'know, there's some coding style guide that explicitly states _not_ to do those kinds of “yoda comparisons”, but i've never seen any code that actually uses them.



    --
    Blue-Maned_Hawk│shortens to Hawk│/ blu.mɛin.dʰak/ │he/him/his/himself/Mr. blue-maned_hawk.srht.site
    LOCAL MAN'S SPEECH ENTIRELY INCONSEQUENTIAL

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Lawrence D'Oliveiro on Sat Feb 10 13:06:13 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:

    But it's far too late to fix that in any language called "C".

    I had a look at the MISRA specs, and they say “assignment operators shall not be used in expressions that yield a boolean value”.

    Oddly worded. They can't mean what they say.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Malcolm McLean on Sat Feb 10 13:03:20 2024
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

    On 09/02/2024 22:41, Ben Bacarisse wrote:
    ...
    Yes, it's a good summary of what passes for "common knowledge". But I
    was talking about something else altogether -- actual bugs found in real
    code, maybe taken from an analysis of security advisories. How many can
    (to take one example) be attributed, in whole or in part, for using
    assignment in a larger expression?

    I did have an example recently in my own code recently (shipped,
    commercial, tested, supposedly bug free code). There was an assignment in a if expression which somehow slipped through. But it's only one
    example.

    Can you post a link to the post? I know you've switch readers, so it
    may not be obvious how to do that, but I'd appreciate it.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Ben Bacarisse on Sat Feb 10 14:42:28 2024
    On 09/02/2024 23:43, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 09/02/2024 11:16, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
    If you want to make C a safer language, one obvious thing is to disallow >>>>> using “=” in the middle of an expression. Instead of returning the value
    of the expression, have it return void. Or just disallow it syntactically >>>>> altogether.

    I think that C would have been a safer language if assignment had been a >>>> statement, not an expression
    Surely someone has studied this, no? There must be some paper
    describing bugs "in the wild"* and categorising them by what language
    features would have made them either impossible or less likely. I don't >>> know of any (it was not even remotely my field) but there is such a
    large pool of data out there I can't imagine that it's not been done.

    I think it is very difficult to get good statistics on this kind of thing. >> You can't really do a controlled study comparing one group programming in
    "C where assignment is an expression" with a group programming in "C where >> assignment is a statement". And you certainly can't do a double-blind
    placebo controlled test!

    True. But there are literally thousands of significant bugs logged
    every day in key systems components. A retrospective analysis of these would, I think, be very interesting.


    That would be interesting, yes. It sounds like a good task for a
    postgraduate student thesis.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Kaz Kylheku on Sat Feb 10 15:02:30 2024
    On 10/02/2024 04:06, Kaz Kylheku wrote:
    On 2024-02-10, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:

    But it's far too late to fix that in any language called "C".

    I had a look at the MISRA specs, and they say “assignment operators shall >> not be used in expressions that yield a boolean value”.

    I skimmed through MISRA some years ago and wasn't very impressed by it, actually.

    It's full the kind of coding rules that you might want to enforce
    if you have to produce a bunch of C, and the only people you are given
    are ones who shouldn't even remotely be doing such a thing.

    We might call those coders Les MISRAbles. :)

    The rules are not suitable for people who know what they are doing
    (and use tools effectively) and detrimental to the code.


    The MISRA rules are a mixed bag. Some of them are definitely things
    that should be considered obvious - such as "don't rely on the results
    of undefined behaviour". And some are also more appropriate for people
    using poorer tools (or who don't know how to use their tools well).
    Some are directly unhelpful - it talks about an "effective type" system
    that is, as I recall, subtly wrong.

    It is worth remembering the target audience, especially for older
    versions of MISRA (their rules have been updated several times). It
    used to be the norm that compilers for microcontrollers were a bit odd -
    they could be very poor at optimising (leading to people doing dangerous tricks, or at least unclear code, to get faster results), and poor at
    warnings. They often had lots of extensions, and non-conforming
    features. (I've seen an 8-bit sort-of-C compiler that intentionally
    does not promote 8-bit types to "int" as required - and that was a big
    name, big price toolchain.) These tools also change slowly - many did
    not have decent C99 support until perhaps fifteen years ago, so you
    couldn't use the newer and better C version. And the tools can have
    more bugs than more popular toolchains with wider audiences.

    A fair proportion of people programming for small embedded systems are primarily electronics engineers and other hardware people that have
    moved into software. They often lack significant formal education in programming or in C. So guidelines here can match that.

    All in all, this means MISRA can be useful and appropriate in some
    cases, and inappropriate in other cases - they are certainly not
    something you'd use for all C programming.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Ben Bacarisse on Sat Feb 10 16:58:01 2024
    On 10/02/2024 14:06, Ben Bacarisse wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:

    But it's far too late to fix that in any language called "C".

    I had a look at the MISRA specs, and they say “assignment operators shall >> not be used in expressions that yield a boolean value”.

    Oddly worded. They can't mean what they say.


    It says "Assignment operators shall not be used in expressions which
    return Boolean values", at least in my copy of MISRA 1998. Of course,
    the use of "return" just makes it worse.

    They explain with examples:

    """
    For example write:

    x = y;
    if ( x != 0 )
    {
    foo();
    }

    and not:

    if ( ( x = y ) != 0 )
    {
    foo();
    }

    or even worse:

    if ( x = y )
    {
    foo();
    }

    This helps to avoid getting ‘=’and ‘==’confused, and assists the static detection of mistakes.
    """

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Keith Thompson on Sat Feb 10 16:53:39 2024
    On 10/02/2024 05:17, Keith Thompson wrote:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:
    But it's far too late to fix that in any language called "C".

    I had a look at the MISRA specs, and they say “assignment operators shall >>> not be used in expressions that yield a boolean value”.

    I presume they mean expressions used as conditions, but unless they
    define what they the phrase "boolean value" somwhere, that's not what
    they wrote.

    Editing error.

    I presume they mean expressions used as conditions, but unless they
    define what they *mean by* the phrase "boolean value" somwhere, that's
    not what they wrote.


    In MISRA 1998, the explanation for that rule includes:

    """
    Strictly speaking, in C, there is no Boolean type, but there is a
    conceptual difference between expressions which return a numeric value
    and expressions which return a Boolean value.

    If assignments are required then they must be performed separately
    outside of any expressions which are effectively of Boolean type.
    """

    MISRA regularly uses its own terms that are different from the Standard
    C terms, which IMHO is needlessly confusing and inaccurate. Sometimes
    these terms are defined, sometimes not. "Boolean" and "Effectively
    Boolean value" are not defined anywhere in MISRA 1998.

    (And in MISRA 2012 there is the extraordinary, messy, vague and badly
    defined idea of "the essential type model" which seems to be what the
    MISRA authors wished C had for its types, operators and conversions, but
    which is at odds with what C really has.)


    In MISRA C 2012, the assignment rule is simpler : "The result of an
    assignment operator should not be used".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to All on Sat Feb 10 17:06:41 2024
    On 10/02/2024 09:05, Blue-Maned_Hawk wrote:
    Lawrence D'Oliveiro wrote:

    On Fri, 9 Feb 2024 19:47:45 -0000 (UTC), Blue-Maned_Hawk wrote:

    There are too many situations where assignment being an expression is a
    useful facet of the language; i am not willing to sacrifice that for an
    ill-defined ideal of “safety”.

    If you consider it “ill-defined”, consider the number of people who have >> developed the habit of writing

    if (NULL == p) ...

    instead of the more natural

    if (p == NULL) ...

    Y'know, there's some coding style guide that explicitly states _not_ to do those kinds of “yoda comparisons”, but i've never seen any code that actually uses them.


    I have seen them all over the place. They are very common in code
    written to MISRA, even though they are not required by the standard. It
    is also common in code written by people who have been taught that C is "dangerous" and you need to write "safe" C like :

    if (42 == x) ...

    or

    if (TRUE == (x < y)) ...

    (I'm not making this up.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Lawrence D'Oliveiro on Sat Feb 10 07:31:38 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Fri, 9 Feb 2024 00:53:42 +0000, Malcolm McLean wrote:

    while( (ch = fgetc(fp)) != EOF)

    is the idiomatic way of accessing a stream a character by character in
    C. So you would disallow this.

    Yes!

    What code would you write to accomplish the same thing, under the
    assumption that what you're proposing is adopted?

    As long as I'm asking, how would you write it in C as it is now?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Sat Feb 10 21:46:24 2024
    On Sat, 10 Feb 2024 15:02:30 +0100, David Brown wrote:

    All in all, this means MISRA can be useful and appropriate in some
    cases, and inappropriate in other cases - they are certainly not
    something you'd use for all C programming.

    Nevertheless, they are based on real-world experience with certain all- too-common errors with C programming, are they not.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Ben Bacarisse on Sat Feb 10 21:48:01 2024
    On Sat, 10 Feb 2024 13:06:13 +0000, Ben Bacarisse wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    I had a look at the MISRA specs, and they say “assignment operators
    shall not be used in expressions that yield a boolean value”.

    Oddly worded. They can't mean what they say.

    It is cleverly worded. The idea is obviously to allow chained assignments, while disallowing doing a test on the value being assigned. The examples
    make this clear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Sat Feb 10 21:49:33 2024
    On Sat, 10 Feb 2024 16:53:39 +0100, David Brown wrote:

    In MISRA C 2012, the assignment rule is simpler : "The result of an assignment operator should not be used".

    Interesting. So no more chained assignments?

    Python manages to allow these, without allowing assignments to actually
    have a value as such.

    Of course, Python has its own pitfalls, such as

    a = b = []

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Lawrence D'Oliveiro on Sat Feb 10 22:47:01 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sat, 10 Feb 2024 13:06:13 +0000, Ben Bacarisse wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    I had a look at the MISRA specs, and they say “assignment operators
    shall not be used in expressions that yield a boolean value”.

    Oddly worded. They can't mean what they say.

    It is cleverly worded. The idea is obviously to allow chained assignments, while disallowing doing a test on the value being assigned. The examples
    make this clear.

    See my (corrected) reply to David Brown for why their examples make it
    clear that they don't mean what they say.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to David Brown on Sat Feb 10 22:45:01 2024
    David Brown <david.brown@hesbynett.no> writes:

    On 10/02/2024 14:06, Ben Bacarisse wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:

    But it's far too late to fix that in any language called "C".

    I had a look at the MISRA specs, and they say “assignment operators shall >>> not be used in expressions that yield a boolean value”.
    Oddly worded. They can't mean what they say.

    It says "Assignment operators shall not be used in expressions which return Boolean values", at least in my copy of MISRA 1998. Of course, the use of "return" just makes it worse.

    They explain with examples:

    """
    For example write:

    x = y;
    if ( x != 0 )
    {
    foo();
    }

    and not:

    if ( ( x = y ) != 0 )

    x = y is an expression that yields a value of the type of x (after
    lvalue conversion). This is unlikely to be _Bool which (even if they
    mean _Bool instead of Boolean) is why I say they can't mean what they
    say.

    Your later post in reply to someone else explains that they don't mean
    what they say though, even a few minutes after reading it, I can't
    remember what the clarification was.

    {
    foo();
    }

    or even worse:

    if ( x = y )
    {
    foo();
    }

    This helps to avoid getting ‘=’and ‘==’confused, and assists the static
    detection of mistakes.
    """

    These sorts of guides often use silly examples like this. What is the
    MIRSA preferred why to write

    while ((x = get_the_next_x(...)) != NO_MORE_Xs) {
    ... use x ...
    }

    ? Presumably they want people to duplicate the call:

    x = get_the_next_x(...);
    while (x != NO_MORE_Xs) {
    ... use x ...
    x - get_the_next_y(...);
    }

    or maybe use break:

    while (1) {
    x = get_the_next_x(...);
    if (x != NO_MORE_Xs) break;
    ... use x ...
    }

    Neither looks good to me.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Ben Bacarisse on Sat Feb 10 22:49:26 2024
    Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

    David Brown <david.brown@hesbynett.no> writes:

    On 10/02/2024 14:06, Ben Bacarisse wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:

    But it's far too late to fix that in any language called "C".

    I had a look at the MISRA specs, and they say “assignment operators shall
    not be used in expressions that yield a boolean value”.
    Oddly worded. They can't mean what they say.

    It says "Assignment operators shall not be used in expressions which return >> Boolean values", at least in my copy of MISRA 1998. Of course, the use of >> "return" just makes it worse.

    They explain with examples:

    """
    For example write:

    x = y;
    if ( x != 0 )
    {
    foo();
    }

    and not:

    if ( ( x = y ) != 0 )

    x = y is an expression that yields a value of the type of x (after
    lvalue conversion). This is unlikely to be _Bool which (even if they
    mean _Bool instead of Boolean) is why I say they can't mean what they
    say.

    I need to correct this because (though I am guessing) they probably mean
    that the value of the assignment can't be used in the integer-valued
    expression whose operator is !=.

    Your later post in reply to someone else explains that they don't mean
    what they say though, even a few minutes after reading it, I can't
    remember what the clarification was.

    {
    foo();
    }

    or even worse:

    if ( x = y )
    {
    foo();
    }

    This helps to avoid getting ‘=’and ‘==’confused, and assists the static
    detection of mistakes.
    """

    These sorts of guides often use silly examples like this. What is the
    MIRSA preferred why to write

    while ((x = get_the_next_x(...)) != NO_MORE_Xs) {
    ... use x ...
    }

    ? Presumably they want people to duplicate the call:

    x = get_the_next_x(...);
    while (x != NO_MORE_Xs) {
    ... use x ...
    x - get_the_next_y(...);
    }

    or maybe use break:

    while (1) {
    x = get_the_next_x(...);
    if (x != NO_MORE_Xs) break;
    ... use x ...
    }

    Neither looks good to me.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Ben Bacarisse on Sun Feb 11 00:11:22 2024
    On 10/02/2024 22:45, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 10/02/2024 14:06, Ben Bacarisse wrote:

    This helps to avoid getting ‘=’and ‘==’confused, and assists the static
    detection of mistakes.
    """

    These sorts of guides often use silly examples like this. What is the
    MIRSA preferred why to write

    while ((x = get_the_next_x(...)) != NO_MORE_Xs) {
    ... use x ...
    }

    ? Presumably they want people to duplicate the call:

    x = get_the_next_x(...);
    while (x != NO_MORE_Xs) {
    ... use x ...
    x - get_the_next_y(...);
    }

    or maybe use break:

    while (1) {
    x = get_the_next_x(...);
    if (x != NO_MORE_Xs) break;
    ... use x ...
    }

    Neither looks good to me.

    Another way is the use the gnu extension to put two statements inside
    the condition, although when I tried it now it didn't like it:

    while ({x = get_the_next_x(...); x != NO_MORE_Xs;}) {...}

    I doubt that would cut any ice with MISRA. You're not technically using
    the result of an assignment in an expression, but you're instead putting
    entire statements in there!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Sun Feb 11 00:17:06 2024
    On Sat, 10 Feb 2024 16:58:01 +0100, David Brown wrote:

    It says "Assignment operators shall not be used in expressions which
    return Boolean values", at least in my copy of MISRA 1998.

    One thing with that wording, it would disallow chained assignments in such innocuous cases as

    a = b = c == d;

    since, after all, the expression is returning a boolean.

    But this point is moot, since the later revision disallows assignment
    chaining completely, anyway.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Ben Bacarisse on Sun Feb 11 00:15:25 2024
    On Sat, 10 Feb 2024 22:45:01 +0000, Ben Bacarisse wrote:

    or maybe use break:

    while (1) {
    x = get_the_next_x(...);
    if (x != NO_MORE_Xs) break;
    ... use x ...
    }

    This is the best approach, though in C I generally use “for (;;)” to indicate “loop forever”. The nice thing is it gracefully generalizes to more code before (and after) the break, and multiple exits from the loop.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Lawrence D'Oliveiro on Sun Feb 11 01:08:51 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sat, 10 Feb 2024 16:58:01 +0100, David Brown wrote:

    It says "Assignment operators shall not be used in expressions which
    return Boolean values", at least in my copy of MISRA 1998.

    One thing with that wording, it would disallow chained assignments in such innocuous cases as

    a = b = c == d;

    since, after all, the expression is returning a boolean.

    The type of c == d is int, but the value will be either 0 or 1. Is that
    what you mean by an expression "returning a boolean" -- an expression of
    type in with either 0 or 1 as the value? If so you could have written

    a = b = 1;

    and made the same claim.

    But this point is moot, since the later revision disallows assignment chaining completely, anyway.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Ben Bacarisse on Sun Feb 11 01:18:38 2024
    On Sun, 11 Feb 2024 01:08:51 +0000, Ben Bacarisse wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sat, 10 Feb 2024 16:58:01 +0100, David Brown wrote:

    It says "Assignment operators shall not be used in expressions which
    return Boolean values", at least in my copy of MISRA 1998.

    One thing with that wording, it would disallow chained assignments in
    such innocuous cases as

    a = b = c == d;

    since, after all, the expression is returning a boolean.

    The type of c == d is int, but the value will be either 0 or 1.

    That is the only kind of “boolean” C has.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Sun Feb 11 01:42:14 2024
    On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sun, 11 Feb 2024 01:08:51 +0000, Ben Bacarisse wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sat, 10 Feb 2024 16:58:01 +0100, David Brown wrote:

    It says "Assignment operators shall not be used in expressions which >>>>> return Boolean values", at least in my copy of MISRA 1998.

    One thing with that wording, it would disallow chained assignments in
    such innocuous cases as

    a = b = c == d;

    since, after all, the expression is returning a boolean.

    The type of c == d is int, but the value will be either 0 or 1.

    That is the only kind of “boolean” C has.

    No it isn't. C99 added _Bool, which can be called bool if you include <stdbool.h>. C23 (not yet released) will make bool a keyword, with
    _Bool as an alternative spelling.

    But the equality and relational operators still yield results of type
    int with value 0 or 1.

    All just new, different names for what I said: still the only kind of “boolean” C has.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Sun Feb 11 05:30:31 2024
    On Sat, 10 Feb 2024 18:00:57 -0800, Keith Thompson wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Sun, 11 Feb 2024 01:08:51 +0000, Ben Bacarisse wrote:
    [...]
    The type of c == d is int, but the value will be either 0 or 1.

    That is the only kind of “boolean” C has.

    No it isn't. C99 added _Bool, which can be called bool if you include
    <stdbool.h>. C23 (not yet released) will make bool a keyword, with
    _Bool as an alternative spelling.


    All just new, different names for what I said: still the only kind of
    “boolean” C has.

    I can imagine that you're trying to express something that's correct,
    but I honestly have no idea what it might be.

    C has a boolean type, called "_Bool" or "bool", added in C99. _Bool is
    a distinct type, not the same as or compatible with any other type.

    No, it is not:

    But the equality and relational operators still yield results of type
    int with value 0 or 1.

    See, no “distinct boolean type”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fir@21:1/5 to bart on Sun Feb 11 12:09:21 2024
    bart wrote:
    On 09/02/2024 17:22, Malcolm McLean wrote:
    On 09/02/2024 17:09, Keith Thompson wrote:

    (It's possible I'm overgeneralizing. For example, a programmer who
    commonly switches between C and other languages might still mix up "="
    and "==" occasionally.)


    I had do to my PhD in Fortran, for my sins. It's := for assignment and
    = for comparison, and when I switched back to C, I was always writing
    "=" for "==".

    Fortran must have changed considerably since I last used it.

    It was "=" to assign, and ".EQ." for equality.

    I assume you mean another language. My normal one does use := and = like that, and switching to/from C gives problems: you write = in C instead
    of ==, and in mine I'd write = instead of :=. However:

    a = b

    was a no-op in my language (or rather, it compared then discarded the result), leading to puzzling bugs. Now I usually detect such statements.

    it seem clear by me that if someone want upbild c-liek language
    (and many people want including me) unicode is needed...
    as i previously said yopu need one sign for == and one sign for = (or :=)

    this conclusion comes from my study of what is needed and what
    could be replaced...this basic set of operators/signs in ansi is to
    natrrow and yet those wighs come from outside computer world

    imo such operation as assigment is kinda computer specific and = dont
    wuite fits

    watching the unicode signs and tryin slightly (initially, spending few
    minutes on it as for now)

    https://en.wikipedia.org/wiki/List_of_Unicode_characters

    i didnt find what would fit and what fits best

    temporarely i put empty square as example

    x▭100, y▭200, z▭x+y

    definitelly assuming that i need to drop ansi and find in unicode is
    some kind of decision (step up)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fir@21:1/5 to fir on Sun Feb 11 12:23:53 2024
    fir wrote:
    bart wrote:
    On 09/02/2024 17:22, Malcolm McLean wrote:
    On 09/02/2024 17:09, Keith Thompson wrote:

    (It's possible I'm overgeneralizing. For example, a programmer who
    commonly switches between C and other languages might still mix up "=" >>>> and "==" occasionally.)


    I had do to my PhD in Fortran, for my sins. It's := for assignment and
    = for comparison, and when I switched back to C, I was always writing
    "=" for "==".

    Fortran must have changed considerably since I last used it.

    It was "=" to assign, and ".EQ." for equality.

    I assume you mean another language. My normal one does use := and = like
    that, and switching to/from C gives problems: you write = in C instead
    of ==, and in mine I'd write = instead of :=. However:

    a = b

    was a no-op in my language (or rather, it compared then discarded the
    result), leading to puzzling bugs. Now I usually detect such statements.

    it seem clear by me that if someone want upbild c-liek language
    (and many people want including me) unicode is needed...
    as i previously said yopu need one sign for == and one sign for = (or :=)

    this conclusion comes from my study of what is needed and what
    could be replaced...this basic set of operators/signs in ansi is to
    natrrow and yet those wighs come from outside computer world

    imo such operation as assigment is kinda computer specific and = dont
    wuite fits

    watching the unicode signs and tryin slightly (initially, spending few minutes on it as for now)

    https://en.wikipedia.org/wiki/List_of_Unicode_characters

    i didnt find what would fit and what fits best

    temporarely i put empty square as example

    x▭100, y▭200, z▭x+y

    definitelly assuming that i need to drop ansi and find in unicode is
    some kind of decision (step up)





    in fact i also think that more then one sign for asigments is needed

    for example this x = foo(y) is something other than this x = y
    and it is specially seen when using things liek

    x y = foo(a,b,c)
    becouse if i want to drep thsi gothic decorators as i name them you got

    x y foo a b c

    and you could want to denote optionally what is variables ina and
    what is variables out and if so the = would look like

    x= y= foo <-a <-b <-c thus output of the function probably should be
    noted by differnt sign then assigment as it would increase readibility

    x' y' foo "a "b "c

    i dont knov hovever what signs it should be and there should be find a
    way what can be optional

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fir@21:1/5 to fir on Sun Feb 11 12:37:55 2024
    fir wrote:
    fir wrote:
    bart wrote:
    On 09/02/2024 17:22, Malcolm McLean wrote:
    On 09/02/2024 17:09, Keith Thompson wrote:

    (It's possible I'm overgeneralizing. For example, a programmer who
    commonly switches between C and other languages might still mix up "=" >>>>> and "==" occasionally.)


    I had do to my PhD in Fortran, for my sins. It's := for assignment and >>>> = for comparison, and when I switched back to C, I was always writing
    "=" for "==".

    Fortran must have changed considerably since I last used it.

    It was "=" to assign, and ".EQ." for equality.

    I assume you mean another language. My normal one does use := and = like >>> that, and switching to/from C gives problems: you write = in C instead
    of ==, and in mine I'd write = instead of :=. However:

    a = b

    was a no-op in my language (or rather, it compared then discarded the
    result), leading to puzzling bugs. Now I usually detect such statements.

    it seem clear by me that if someone want upbild c-liek language
    (and many people want including me) unicode is needed...
    as i previously said yopu need one sign for == and one sign for = (or :=)

    this conclusion comes from my study of what is needed and what
    could be replaced...this basic set of operators/signs in ansi is to
    natrrow and yet those wighs come from outside computer world

    imo such operation as assigment is kinda computer specific and = dont
    wuite fits

    watching the unicode signs and tryin slightly (initially, spending few
    minutes on it as for now)

    https://en.wikipedia.org/wiki/List_of_Unicode_characters

    i didnt find what would fit and what fits best

    temporarely i put empty square as example

    x▭100, y▭200, z▭x+y

    definitelly assuming that i need to drop ansi and find in unicode is
    some kind of decision (step up)





    in fact i also think that more then one sign for asigments is needed

    for example this x = foo(y) is something other than this x = y
    and it is specially seen when using things liek

    x y = foo(a,b,c)
    becouse if i want to drep thsi gothic decorators as i name them you got

    x y foo a b c

    and you could want to denote optionally what is variables ina and
    what is variables out and if so the = would look like

    x= y= foo <-a <-b <-c thus output of the function probably should be
    noted by differnt sign then assigment as it would increase readibility

    x' y' foo "a "b "c

    i dont knov hovever what signs it should be and there should be find a
    way what can be optional


    the decision just to open up unicode can simplify things

    for exampel i was wondering back than herdly if

    a b c = d e f

    should be a 3 element 'vector' or 5 element vector..decision to take
    unicode just allow to take one = for 1-element scalar assigment
    and soem other sign resembling = for n-element vector assigment
    ..without it there is some more hard way i probably will even not explore

    (and i probably resolved the trouble of what to do with comma "'"

    a b, c d e, f

    comam should be separator something liek ";" today
    those "tuples" separated by space should be vectors, or
    particles/particules as i neme them

    im presently not sure if some suitable 2-element particules not reserve
    for assigments liek

    x 1, y 2

    means x=1, y=2 but x 1 2 or foo x 1 are 3-element vectors, but im not
    sure if this will not break something as it "przeslania" (forget an
    englis word, covers?) the 2-element vector syntax i maybe would need


    hovever this pure vectors laying in white emptiness of context
    of much nothing maybe are worth to cover by something more usable

    as some could say this context is wasted

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fir@21:1/5 to fir on Sun Feb 11 12:46:29 2024
    fir wrote:
    fir wrote:
    bart wrote:
    On 09/02/2024 17:22, Malcolm McLean wrote:
    On 09/02/2024 17:09, Keith Thompson wrote:

    (It's possible I'm overgeneralizing. For example, a programmer who
    commonly switches between C and other languages might still mix up "=" >>>>> and "==" occasionally.)


    I had do to my PhD in Fortran, for my sins. It's := for assignment and >>>> = for comparison, and when I switched back to C, I was always writing
    "=" for "==".

    Fortran must have changed considerably since I last used it.

    It was "=" to assign, and ".EQ." for equality.

    I assume you mean another language. My normal one does use := and = like >>> that, and switching to/from C gives problems: you write = in C instead
    of ==, and in mine I'd write = instead of :=. However:

    a = b

    was a no-op in my language (or rather, it compared then discarded the
    result), leading to puzzling bugs. Now I usually detect such statements.

    it seem clear by me that if someone want upbild c-liek language
    (and many people want including me) unicode is needed...
    as i previously said yopu need one sign for == and one sign for = (or :=)

    this conclusion comes from my study of what is needed and what
    could be replaced...this basic set of operators/signs in ansi is to
    natrrow and yet those wighs come from outside computer world

    imo such operation as assigment is kinda computer specific and = dont
    wuite fits

    watching the unicode signs and tryin slightly (initially, spending few
    minutes on it as for now)

    https://en.wikipedia.org/wiki/List_of_Unicode_characters

    i didnt find what would fit and what fits best

    temporarely i put empty square as example

    x▭100, y▭200, z▭x+y

    definitelly assuming that i need to drop ansi and find in unicode is
    some kind of decision (step up)





    in fact i also think that more then one sign for asigments is needed

    for example this x = foo(y) is something other than this x = y
    and it is specially seen when using things liek

    x y = foo(a,b,c)
    becouse if i want to drep thsi gothic decorators as i name them you got

    x y foo a b c

    and you could want to denote optionally what is variables ina and
    what is variables out and if so the = would look like

    x= y= foo <-a <-b <-c thus output of the function probably should be
    noted by differnt sign then assigment as it would increase readibility

    x' y' foo "a "b "c

    i dont knov hovever what signs it should be and there should be find a
    way what can be optional



    x y foo a b c

    optional is not bed also clever editir sein such particles could
    set output variables as one color input as another and bold teh function
    call name

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Sun Feb 11 13:36:48 2024
    On 10/02/2024 22:49, Lawrence D'Oliveiro wrote:
    On Sat, 10 Feb 2024 16:53:39 +0100, David Brown wrote:

    In MISRA C 2012, the assignment rule is simpler : "The result of an
    assignment operator should not be used".

    Interesting. So no more chained assignments?


    Correct.

    Chained assignments are used in three ways, I would say :

    1. Inappropriately grouping things that are logically separate :

    index = sum = 0;

    Splitting these makes code clearer.

    2. Grouping things to save lines using old-style "declare variables at
    the top of the function" code:

    int a, b;
    ...
    a = b = 0;

    Rather write:

    int a = 0;
    int b = 0;

    3. Cases where grouping really does make sense :

    x = y = z = initial_value;


    I don't see a problem with case 3, but these are so rare that it is not
    a problem if a coding style disallows them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Ben Bacarisse on Sun Feb 11 13:52:49 2024
    On 11/02/2024 02:08, Ben Bacarisse wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sat, 10 Feb 2024 16:58:01 +0100, David Brown wrote:

    It says "Assignment operators shall not be used in expressions which
    return Boolean values", at least in my copy of MISRA 1998.

    One thing with that wording, it would disallow chained assignments in such >> innocuous cases as

    a = b = c == d;

    since, after all, the expression is returning a boolean.

    The type of c == d is int, but the value will be either 0 or 1. Is that
    what you mean by an expression "returning a boolean" -- an expression of
    type in with either 0 or 1 as the value?

    I think that is what MISRA means when they talk about "essentially
    boolean" - but as I mentioned before, they don't define the term at all.
    (MISRA 2012 supports C99, and also appears to consider _Bool as
    "essentially boolean", despite not defining it.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to bart on Sun Feb 11 13:50:31 2024
    On 11/02/2024 01:11, bart wrote:
    On 10/02/2024 22:45, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 10/02/2024 14:06, Ben Bacarisse wrote:

    This helps to avoid getting ‘=’and ‘==’confused, and assists the static
    detection of mistakes.
    """

    These sorts of guides often use silly examples like this.  What is the
    MIRSA preferred why to write

       while ((x = get_the_next_x(...)) != NO_MORE_Xs) {
           ... use x ...
       }

    ?  Presumably they want people to duplicate the call:

       x = get_the_next_x(...);
       while (x != NO_MORE_Xs) {
          ... use x ...
          x - get_the_next_y(...);
       }

    or maybe use break:

       while (1) {
          x = get_the_next_x(...);
          if (x != NO_MORE_Xs) break;
          ... use x ...
       }

    Neither looks good to me.

    Another way is the use the gnu extension to put two statements inside
    the condition, although when I tried it now it didn't like it:

        while ({x = get_the_next_x(...); x != NO_MORE_Xs;}) {...}

    I doubt that would cut any ice with MISRA. You're not technically using
    the result of an assignment in an expression, but you're instead putting entire statements in there!

    MISRA disallows extensions, despite most compilers used by people
    writing MISRA code /requiring/ extensions to do the job.

    MISRA 1998 starts with these rules :

    1. All code shall conform to ISO 9899 standard C, with no extensions
    permitted.

    2. Code written in languages other than C should only be used if
    there is a defined interface standard for object code to which the compilers/assemblers for both languages conform.

    3. Assembly language functions that are called from C should be
    written as C functions containing only in-line assembly language,
    and in-line assembly language should not be embedded in normal
    C code.

    So you are only allowed to use C for your code, conforming to standard
    C90, without extensions. But you are allowed to use code in other
    languages. And you can't use extensions for your compiler, but if you
    use assembly functions, they must be in C inline assembly - which
    necessitates extensions.

    Did I mention that I thought MISRA was a bit mixed up?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Ben Bacarisse on Sun Feb 11 13:45:22 2024
    On 10/02/2024 23:45, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 10/02/2024 14:06, Ben Bacarisse wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:

    But it's far too late to fix that in any language called "C".

    I had a look at the MISRA specs, and they say “assignment operators shall
    not be used in expressions that yield a boolean value”.
    Oddly worded. They can't mean what they say.

    It says "Assignment operators shall not be used in expressions which return >> Boolean values", at least in my copy of MISRA 1998. Of course, the use of >> "return" just makes it worse.

    They explain with examples:

    """
    For example write:

    x = y;
    if ( x != 0 )
    {
    foo();
    }

    and not:

    if ( ( x = y ) != 0 )

    x = y is an expression that yields a value of the type of x (after
    lvalue conversion). This is unlikely to be _Bool which (even if they
    mean _Bool instead of Boolean) is why I say they can't mean what they
    say.


    To be clear - I am quoting MISRA here, not saying I think it is
    necessarily a good idea, or that the MISRA standards explain it well.

    (They don't mean "_Bool" here, because that was MISRA 1998, which
    considered only C90.)

    Your later post in reply to someone else explains that they don't mean
    what they say though, even a few minutes after reading it, I can't
    remember what the clarification was.

    {
    foo();
    }

    or even worse:

    if ( x = y )
    {
    foo();
    }

    This helps to avoid getting ‘=’and ‘==’confused, and assists the static
    detection of mistakes.
    """

    These sorts of guides often use silly examples like this.

    Agreed.

    What is the
    MIRSA preferred why to write

    while ((x = get_the_next_x(...)) != NO_MORE_Xs) {
    ... use x ...
    }

    ? Presumably they want people to duplicate the call:

    x = get_the_next_x(...);
    while (x != NO_MORE_Xs) {
    ... use x ...
    x - get_the_next_y(...);
    }

    or maybe use break:

    while (1) {
    x = get_the_next_x(...);
    if (x != NO_MORE_Xs) break;
    ... use x ...
    }

    Neither looks good to me.


    That's the issue with almost any rule - there are almost always cases
    where breaking the rule leads to clearer code (possibly clearer simply
    because it is idiomatic, and therefore familiar).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Sun Feb 11 13:57:23 2024
    On 10/02/2024 22:48, Lawrence D'Oliveiro wrote:
    On Sat, 10 Feb 2024 13:06:13 +0000, Ben Bacarisse wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    I had a look at the MISRA specs, and they say “assignment operators
    shall not be used in expressions that yield a boolean value”.

    Oddly worded. They can't mean what they say.

    It is cleverly worded. The idea is obviously to allow chained assignments, while disallowing doing a test on the value being assigned. The examples
    make this clear.

    No. It was badly worded. They had been trying to rule out "if (x = y)"
    and requiring it to be written "x = y; if (x != 0) ...".

    They did not intend to allow chained assignments - they simply didn't
    think to rule them out in MISRA 1998. In MISRA 2012, they changed that
    to explicitly rule out /any/ use of the value of an assignment expression.


    You are attributing a level of sophistication and forethought to the
    MISRA authors that they simply did not have.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Sun Feb 11 18:05:08 2024
    On 11/02/2024 17:55, Malcolm McLean wrote:
    On 11/02/2024 02:00, Keith Thompson wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Sun, 11 Feb 2024 01:08:51 +0000, Ben Bacarisse wrote:
    [...]
    The type of c == d is int, but the value will be either 0 or 1.

    That is the only kind of “boolean” C has.

    No it isn't.  C99 added _Bool, which can be called bool if you include >>>> <stdbool.h>.  C23 (not yet released) will make bool a keyword, with
    _Bool as an alternative spelling.

    But the equality and relational operators still yield results of type
    int with value 0 or 1.

    All just new, different names for what I said: still the only kind of
    “boolean” C has.

    I can imagine that you're trying to express something that's correct,
    but I honestly have no idea what it might be.

    C has a boolean type, called "_Bool" or "bool", added in C99.  _Bool is
    a distinct type, not the same as or compatible with any other type.

    Equality and relational operators yield results of type int, not _Bool.

    An expression of any scalar type (which includes integer,
    floating-point, and pointer types) can be used as a condition.

    Assuming you agree with all that, I have no idea what you mean by "the
    only kind of “boolean” C has".

    Other lanaguages were designed with a "boolean" type which had special
    rules (bool + bool would either be disallowed or yield 1
     if both were true), and was intended to be used wherever a value was logically either true or false. C didn't and used a int with just
    happened to be 1 or 0 for this purpose, and whilst booleans have now
    been added, the old system cannot be entirely eliminated and remains.

    Yes, we all know that. (Well, everyone who has learned a bit of C99
    knows that.) It's very difficult to change things in a language that
    has as much use as C - changing the type of the value of expressions
    like "x == y" would have been a breaking change. When C++ was forked
    from C, it was able to make such breaking changes - thus "x == y" gives
    a bool in C++. But for C, it was too late.

    You can achieve most of the benefits of a boolean type by aliasing "int'
    to "bool" and defining "true" and "false", and a lot of C installations
    do exactly this.


    No, you can't. That gives you the worst of all worlds.

    Use type "bool" when you want a boolean. It is /not/ the same as an
    int, or an enumerated type, or an unsigned char, or anything else that
    might be used as a "home-made boolean" - it has important additional characteristics. "Home-made boolean" types might be considered useful
    in C90, but not in C99. Recommending them now is bad advice, and
    recommending that you do so using the names "bool", "true" and "false"
    which conflict with C's real boolean type is extraordinarily silly.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Kettlewell@21:1/5 to Lawrence D'Oliveiro on Sun Feb 11 17:21:27 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    If you want to make C a safer language, one obvious thing is to disallow using “=” in the middle of an expression. Instead of returning the value of the expression, have it return void. Or just disallow it syntactically altogether.

    Possibly you’re suggesting that with hindsight, C should have always
    worked like that. If it had been then we’d have fewer bugs and the
    status quo bias would mean little or no pressure to allow assignment expressions in a wider set of contexts.

    Alternatively, you’re suggesting it as a future change. That leads to a couple of questions. First are you envisaging it as a new rule in a
    future version of standard C, or a new language which differs from C in
    this one detail (call it C prime, perhaps)? The second is how you
    envisage it being deployed, given the huge body of code that depends
    (wisely or not) on the existing rules, and would need to be modified to
    follow the new rules without any change to its meaning.

    --
    https://www.greenend.org.uk/rjk/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Thiago Adams on Mon Feb 12 01:13:33 2024
    On Sun, 11 Feb 2024 16:12:25 -0300, Thiago Adams wrote:

    The approach I am doing in cake (https://github.com/thradams/cake) is
    require "bool" in conditional expression.

    if (expression) ...
    expression must be bool type.

    BUT...
    In C, a == b are of type int.

    But boolean is a subtype of int anyway, so what’s the harm in redefining conditional expressions to return bool instead?

    One type represents the type used by the language (int in this case) the second type is something like "working as bool" .
    So the expression a == b has the "type int" working as "bool"

    If bool is a subtype of (unsigned?) int, then you are allowed to pass bool where int is wanted, but not the other way round.

    The other situation where two types are used are enumerators
    enum E {A }
    In C A is "int" but the second type is "working as enum E".
    This allows me to check usage of different enumerators.

    Again, enums can be considered to be subtypes of int (or even unsigned
    int). You can think of bool as a special case of a predefined enum.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Mon Feb 12 01:14:21 2024
    On Sun, 11 Feb 2024 13:57:23 +0100, David Brown wrote:

    You are attributing a level of sophistication and forethought to the
    MISRA authors that they simply did not have.

    Fair enough. ;)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Mon Feb 12 01:16:13 2024
    On Sat, 10 Feb 2024 21:37:26 -0800, Keith Thompson wrote:

    _Bool is a distinct type. Equality and relational operators yield
    results of type int, which is not type _Bool.

    There is no place where one type can be used, but the other cannot.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Mon Feb 12 01:17:45 2024
    On Sun, 11 Feb 2024 18:05:08 +0100, David Brown wrote:

    Use type "bool" when you want a boolean. It is /not/ the same as an
    int ...

    You seem to be saying that something like

    bool a = b == c;

    should not be allowed.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Mon Feb 12 03:47:56 2024
    On Sun, 11 Feb 2024 19:12:35 -0800, Keith Thompson wrote:

    int main(void) {
    _Bool b;
    int i;
    _Bool *ptr = &i;
    // constraint violation because _Bool and int are not compatible
    }

    Do you understand that int and _Bool are distinct and incompatible
    types ...

    No more so than, say, int and short int.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Keith Thompson on Mon Feb 12 12:26:32 2024
    On 12/02/2024 04:34, Keith Thompson wrote:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Sat, 10 Feb 2024 21:37:26 -0800, Keith Thompson wrote:
    _Bool is a distinct type. Equality and relational operators yield
    results of type int, which is not type _Bool.

    There is no place where one type can be used, but the other cannot.

    Incorrect.

    int main(void) {
    _Bool b;
    int i;
    _Bool *ptr = &i;
    // constraint violation because _Bool and int are not compatible
    }

    Do you understand that int and _Bool are distinct and incompatible
    types, and that neither is a "subtype" of the other?

    Oh, and conversion from any scalar type to _Bool yields either (_Bool)0
    or (_Bool)1, a major difference between _Bool and all other scalar
    types.


    Absolutely. There is a /massive/ difference between:

    int * p;

    _Bool b = p;

    and

    int x = p;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to David Brown on Mon Feb 12 11:38:09 2024
    On 12/02/2024 11:26, David Brown wrote:
    On 12/02/2024 04:34, Keith Thompson wrote:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Sat, 10 Feb 2024 21:37:26 -0800, Keith Thompson wrote:
    _Bool is a distinct type.  Equality and relational operators yield
    results of type int, which is not type _Bool.

    There is no place where one type can be used, but the other cannot.

    Incorrect.

    int main(void) {
         _Bool b;
         int i;
         _Bool *ptr = &i;
         // constraint violation because _Bool and int are not compatible >>> }

    Do you understand that int and _Bool are distinct and incompatible
    types, and that neither is a "subtype" of the other?

    Oh, and conversion from any scalar type to _Bool yields either (_Bool)0
    or (_Bool)1, a major difference between _Bool and all other scalar
    types.


    Absolutely.  There is a /massive/ difference between:

        int * p;

    I assume the * is a typo?

        _Bool b = p;

    and

        int x = p;



    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Mon Feb 12 12:23:35 2024
    On 12/02/2024 04:47, Lawrence D'Oliveiro wrote:
    On Sun, 11 Feb 2024 19:12:35 -0800, Keith Thompson wrote:

    int main(void) {
    _Bool b;
    int i;
    _Bool *ptr = &i;
    // constraint violation because _Bool and int are not compatible
    }

    Do you understand that int and _Bool are distinct and incompatible
    types ...

    No more so than, say, int and short int.

    These are indeed distinct and incompatible types. That applies even if
    they happen to be the same size.

    Do you know what "incompatible types" are, and what they mean? Do you
    realise that they cannot be swapped around as you suggest?

    As an example, look at the code generated for this with gcc for the
    msp430 (a 16-bit target, where "int" and "short int" are the same size,
    and where the assembly is simple enough to understand).

    <https://godbolt.org/z/81cE5YThz>

    int sizeof_short = sizeof(short int);
    int sizeof_int = sizeof(int);

    int foo1(int * p, short int * q) {
    *p = 10;
    *q += 1;
    return *p;
    }

    int foo2(int * p, int * q) {
    *p = 10;
    *q += 1;
    return *p;
    }


    foo1:
    MOV.W #10, @R12
    ADD.W #1, @R13
    MOV.B #10, R12
    RET
    foo2:
    MOV.W #10, @R12
    ADD.W #1, @R13
    MOV.W @R12, R12
    RET
    sizeof_int:
    .short 2
    sizeof_short:
    .short 2



    The compiler knows that in "foo1", "p" and "q" cannot point to the same
    thing, because they are incompatible types. For "foo2", when swapping
    "short int" for "int", the code is less efficient - it needs an extra
    read from memory.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Mon Feb 12 12:40:24 2024
    On 11/02/2024 19:00, Malcolm McLean wrote:
    On 11/02/2024 17:05, David Brown wrote:
    On 11/02/2024 17:55, Malcolm McLean wrote:
    On 11/02/2024 02:00, Keith Thompson wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Sun, 11 Feb 2024 01:08:51 +0000, Ben Bacarisse wrote:
    [...]
    The type of c == d is int, but the value will be either 0 or 1. >>>>>>>
    That is the only kind of “boolean” C has.

    No it isn't.  C99 added _Bool, which can be called bool if you
    include
    <stdbool.h>.  C23 (not yet released) will make bool a keyword, with >>>>>> _Bool as an alternative spelling.

    But the equality and relational operators still yield results of type >>>>>> int with value 0 or 1.

    All just new, different names for what I said: still the only kind of >>>>> “boolean” C has.

    I can imagine that you're trying to express something that's correct,
    but I honestly have no idea what it might be.

    C has a boolean type, called "_Bool" or "bool", added in C99.  _Bool is >>>> a distinct type, not the same as or compatible with any other type.

    Equality and relational operators yield results of type int, not _Bool. >>>>
    An expression of any scalar type (which includes integer,
    floating-point, and pointer types) can be used as a condition.

    Assuming you agree with all that, I have no idea what you mean by "the >>>> only kind of “boolean” C has".

    Other lanaguages were designed with a "boolean" type which had
    special rules (bool + bool would either be disallowed or yield 1
      if both were true), and was intended to be used wherever a value
    was logically either true or false. C didn't and used a int with just
    happened to be 1 or 0 for this purpose, and whilst booleans have now
    been added, the old system cannot be entirely eliminated and remains.

    Yes, we all know that.  (Well, everyone who has learned a bit of C99
    knows that.)  It's very difficult to change things in a language that
    has as much use as C - changing the type of the value of expressions
    like "x == y" would have been a breaking change.  When C++ was forked
    from C, it was able to make such breaking changes - thus "x == y"
    gives a bool in C++.  But for C, it was too late.

    So in fact it should be pretty obvious what LDO is getting at.

    I agree - it is fairly obvious what he means. It is equally obvious
    that he is wrong.


    You can achieve most of the benefits of a boolean type by aliasing
    "int' to "bool" and defining "true" and "false", and a lot of C
    installations do exactly this.


    No, you can't.  That gives you the worst of all worlds.

    Use type "bool" when you want a boolean.  It is /not/ the same as an
    int, or an enumerated type, or an unsigned char, or anything else that
    might be used as a "home-made boolean" - it has important additional
    characteristics.  "Home-made boolean" types might be considered useful
    in C90, but not in C99.  Recommending them now is bad advice, and
    recommending that you do so using the names "bool", "true" and "false"
    which conflict with C's real boolean type is extraordinarily silly.

    I used to say "bool breaks libraries" and this is exactly the problem.

    That is why C99 calls the type "_Bool", and you need to include
    <stdbool.h> to get the nicer name "bool". Now with C23, the C standards committee feel confident that the proportion of code that used "bool"
    for their own types is small enough that it is safe to make "bool",
    "true" and "false" keywords.

    And it is why it is insane to suggest that it is a good idea to make
    your own pseudo-boolean type in C and call it "bool". It was a
    questionable idea in the late nineties when C99 was known to be coming
    soon, a bad idea in the early naughties when it had been published and
    compiler support was gaining, and is certainly not an acceptable idea now.

    A
    simple typedef bool "bool" to "int" and definiing "true" and "false"
    creates problems because there are no namespaces, you export the
    symbols, and either they clash or they create mismash of subtly
    different Boolean types.

    Correct.

    So I am not recommending it in user code.

    Then what were you doing when you wrote this?

    """
    You can achieve most of the benefits of a boolean type by aliasing
    "int' to "bool" and defining "true" and "false", and a lot of C
    installations do exactly this.
    """

    However I am saying that it does achieve most of the benefits of having
    a boolean type, and therefore people who do this are not entirely
    stupid. But I'm talking about the C installation, so normally the person
    who provides the compiler, not the user code.


    And what is a "C installation" ? Do you mean a "C /implementation/" ?
    Do you mean your own modification to headers or libraries after you have installed a toolchain? Do you mean a company's standard additional
    libraries?

    Or do you mean that C implementations simply put "typedef int bool;" as
    their <stdbool.h> implementation? That would, of course, be utter nonsense.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Mon Feb 12 12:42:12 2024
    On 12/02/2024 02:17, Lawrence D'Oliveiro wrote:
    On Sun, 11 Feb 2024 18:05:08 +0100, David Brown wrote:

    Use type "bool" when you want a boolean. It is /not/ the same as an
    int ...

    You seem to be saying that something like

    bool a = b == c;

    should not be allowed.

    No, I don't seem to be saying that at all. An "int" value can
    implicitly be converted to a _Bool.

    That does not mean that "int" and "_Bool" are the same thing.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Keith Thompson on Mon Feb 12 12:49:06 2024
    On 11/02/2024 22:15, Keith Thompson wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 11/02/2024 02:08, Ben Bacarisse wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Sat, 10 Feb 2024 16:58:01 +0100, David Brown wrote:
    It says "Assignment operators shall not be used in expressions which >>>>> return Boolean values", at least in my copy of MISRA 1998.

    One thing with that wording, it would disallow chained assignments in such >>>> innocuous cases as

    a = b = c == d;

    since, after all, the expression is returning a boolean.
    The type of c == d is int, but the value will be either 0 or 1. Is
    that
    what you mean by an expression "returning a boolean" -- an expression of >>> type in with either 0 or 1 as the value?

    I think that is what MISRA means when they talk about "essentially
    boolean" - but as I mentioned before, they don't define the term at
    all. (MISRA 2012 supports C99, and also appears to consider _Bool as
    "essentially boolean", despite not defining it.)

    I'll note that the requirement "Assignment operators shall not be used
    in expressions which return Boolean values" doesn't use the (undefined)
    term "essentially Boolean".

    Correct - the term "essentially boolean" is from MISRA 2012, while the
    rule you quote there is from MISRA 1998. There are several versions of
    MISRA C (1998, 2004, 2012, 2016, and 2023) - I have been referring to
    1998 and 2012, since these are the versions I have available. (I should probably buy a copy of the latest version some time.)

    The "essential type" system is in MISRA 2012, but not MISRA 1998. (I
    don't know about 2004.)

    I would say that MISRA 1998 should also define the term "Boolean value",
    but it does not.


    If it's intended to refer to "essentially Boolean" values, and if it
    means what you suggest, then the guideline would permit this:

    char c = ...;
    int uc;
    if (uc = isupper(c)) ...

    since isupper() is specified to return zero or non-zero, not zero or
    one. (It would be disallowed by the later version of MISRA which bans
    any use of the result of an assignment expression.)

    The only way the term "boolean" or "essentially Boolean" makes sense is
    if it refers to *conditions*.


    I think you are searching for consistency and meaning where there is
    none to be found. IMHO the standard is vague and woolly about this kind
    of thing, and it is extremely simple to think of examples that don't fit
    neatly with their rules.

    MISRA 2012 is bad, but less bad than MISRA 1998. Perhaps by MISRA 2023
    (which is the third revision of MISRA 2012), they've done better.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to David Brown on Mon Feb 12 13:57:31 2024
    On 12/02/2024 13:36, David Brown wrote:
    On 12/02/2024 12:38, bart wrote:
    On 12/02/2024 11:26, David Brown wrote:

    Absolutely.  There is a /massive/ difference between:

         int * p;

    I assume the * is a typo?

    No.


         _Bool b = p;

    This is equivalent to "b = (p != NULL);" and does not elicit a warning
    from gcc (-Wall -Wextra -Wpedantic -std=C11).

    (You might feel that there /should/ be a warning about it - that's
    another matter.  I'm saying what gcc does here, not what I think it
    should do.)


    and

         int x = p;


    This will set "x" to an integer value based on the pointer's address. It
    is almost certainly not something the programmer wanted, and elicits a warning from gcc even without any options.


    OK, at least one of them was wrong! I saw the warning for this one from
    gcc; my compiler rejects both assignments.


    The point is, "_Bool" and "int" are not only different in theory (as
    Keith has said several times, they are different incompatible types),
    but they are different in practice.

    (I don't know if your compiler has support for _Bool at all.)

    My C compiler has a _Bool type but it is just an alias for 'char'. (I
    think done when 'char' was an alias for 'unsigned char', I later changed
    it to 'signed char'.)

    So it doesn't have any special properties; assigning p to it is an error
    (it will need !!p), and assigning *p will copy the bottom 8 bits.

    (However, if I do the same test in my systems language, there it works
    as expected:

    ref void p:=nil, q:=&p
    bool b:=p, c:=q
    println b, c, int(c)

    It prints 'False True 1', which was a surprise as I must have forgotten
    I'd done that support. I never use 'bool', it's more of an internal
    type. But it means I could port some of this to the C compiler.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to bart on Mon Feb 12 14:36:03 2024
    On 12/02/2024 12:38, bart wrote:
    On 12/02/2024 11:26, David Brown wrote:
    On 12/02/2024 04:34, Keith Thompson wrote:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Sat, 10 Feb 2024 21:37:26 -0800, Keith Thompson wrote:
    _Bool is a distinct type.  Equality and relational operators yield >>>>>> results of type int, which is not type _Bool.

    There is no place where one type can be used, but the other cannot.

    Incorrect.

    int main(void) {
         _Bool b;
         int i;
         _Bool *ptr = &i;
         // constraint violation because _Bool and int are not compatible >>>> }

    Do you understand that int and _Bool are distinct and incompatible
    types, and that neither is a "subtype" of the other?

    Oh, and conversion from any scalar type to _Bool yields either (_Bool)0
    or (_Bool)1, a major difference between _Bool and all other scalar
    types.


    Absolutely.  There is a /massive/ difference between:

         int * p;

    I assume the * is a typo?

    No.


         _Bool b = p;

    This is equivalent to "b = (p != NULL);" and does not elicit a warning
    from gcc (-Wall -Wextra -Wpedantic -std=C11).

    (You might feel that there /should/ be a warning about it - that's
    another matter. I'm saying what gcc does here, not what I think it
    should do.)


    and

         int x = p;


    This will set "x" to an integer value based on the pointer's address.
    It is almost certainly not something the programmer wanted, and elicits
    a warning from gcc even without any options.


    The point is, "_Bool" and "int" are not only different in theory (as
    Keith has said several times, they are different incompatible types),
    but they are different in practice.

    (I don't know if your compiler has support for _Bool at all.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to bart on Mon Feb 12 16:04:40 2024
    On 12/02/2024 14:57, bart wrote:
    On 12/02/2024 13:36, David Brown wrote:
    On 12/02/2024 12:38, bart wrote:
    On 12/02/2024 11:26, David Brown wrote:

    Absolutely.  There is a /massive/ difference between:

         int * p;

    I assume the * is a typo?

    No.


         _Bool b = p;

    This is equivalent to "b = (p != NULL);" and does not elicit a warning
    from gcc (-Wall -Wextra -Wpedantic -std=C11).

    (You might feel that there /should/ be a warning about it - that's
    another matter.  I'm saying what gcc does here, not what I think it
    should do.)


    and

         int x = p;


    This will set "x" to an integer value based on the pointer's address.
    It is almost certainly not something the programmer wanted, and
    elicits a warning from gcc even without any options.


    OK, at least one of them was wrong! I saw the warning for this one from
    gcc; my compiler rejects both assignments.


    Conversions of a pointer to "int" or to "_Bool" are both allowed by the
    C standards. So a conforming C compiler has to accept them and generate appropriate code for them.

    If the pointer's value cannot be represented in the target type when
    converting to an integer type, then it is undefined behaviour - but the compiler usually can't know that for sure at compile time. Thus it has
    to generate code that accepts this and will work if the address happens
    to be small enough. The compiler can, however, issue a warning that the programmer is probably doing something silly.

    Conversion of any scaler (including pointers) to _Bool is done by
    comparison to 0. And since that is often a sensible thing to do, there
    is no warning in gcc - it would give too many false positives.


    The point is, "_Bool" and "int" are not only different in theory (as
    Keith has said several times, they are different incompatible types),
    but they are different in practice.

    (I don't know if your compiler has support for _Bool at all.)

    My C compiler has a _Bool type but it is just an alias for 'char'. (I
    think done when 'char' was an alias for 'unsigned char', I later changed
    it to 'signed char'.)

    So it doesn't have any special properties; assigning p to it is an error
    (it will need !!p), and assigning *p will copy the bottom 8 bits.


    You really should remove it, or fix it. Having a type that is called
    _Bool but does not act like _Bool is likely to be confusing and unhelpful.

    The key properties of _Bool are :

    1. It is a standard /unsigned/ integer type, big enough to hold 0 or 1.

    2. Conversion of any scaler to _Bool is done by comparison to 0, not by truncation, and it can only ever have a value of 0 or 1. (The padding
    bits can have any value.)

    Since assignment is done by conversion, that also means that something
    like "_Bool b = 2;" is implemented as "_Bool b = (2 != 0);", thus
    setting "b" to 1.

    (However, if I do the same test in my systems language, there it works
    as expected:

          ref void p:=nil, q:=&p
          bool b:=p, c:=q
          println b, c, int(c)

    It prints 'False True 1', which was a surprise as I must have forgotten
    I'd done that support. I never use 'bool', it's more of an internal
    type. But it means I could port some of this to the C compiler.)


    I would recommend that your _Bool in C works as required by the C99
    standards, or is removed entirely. I know you are not aiming for any
    kind of strict conformance, but it's still not a good idea to have such inconsistencies.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Keith Thompson on Mon Feb 12 17:43:22 2024
    On 12/02/2024 17:13, Keith Thompson wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 12/02/2024 12:38, bart wrote:
    On 12/02/2024 11:26, David Brown wrote:
    On 12/02/2024 04:34, Keith Thompson wrote:
    Oh, and conversion from any scalar type to _Bool yields either (_Bool)0 >>>>> or (_Bool)1, a major difference between _Bool and all other scalar
    types.

    Absolutely.  There is a /massive/ difference between:

         int * p;
    I assume the * is a typo?

    No.


         _Bool b = p;

    This is equivalent to "b = (p != NULL);" and does not elicit a warning
    from gcc (-Wall -Wextra -Wpedantic -std=C11).

    (You might feel that there /should/ be a warning about it - that's
    another matter. I'm saying what gcc does here, not what I think it
    should do.)

    and

         int x = p;


    This will set "x" to an integer value based on the pointer's
    address. It is almost certainly not something the programmer wanted,
    and elicits a warning from gcc even without any options.

    This is a constraint violation. A compiler that doesn't reject it
    *might* generate code that behaves as you suggest.


    You are (unsurprisingly) correct. I was only paying attention to the
    rules for the conversion itself.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Tue Feb 13 09:07:29 2024
    On 12/02/2024 21:27, Malcolm McLean wrote:
    On 12/02/2024 11:40, David Brown wrote:
    On 11/02/2024 19:00, Malcolm McLean wrote:

    That is why C99 calls the type "_Bool", and you need to include
    <stdbool.h> to get the nicer name "bool".  Now with C23, the C
    standards committee feel confident that the proportion of code that
    used "bool" for their own types is small enough that it is safe to
    make "bool", "true" and "false" keywords.

    And it is why it is insane to suggest that it is a good idea to make
    your own pseudo-boolean type in C and call it "bool".  It was a
    questionable idea in the late nineties when C99 was known to be coming
    soon, a bad idea in the early naughties when it had been published and
    compiler support was gaining, and is certainly not an acceptable idea
    now.

    A simple typedef bool "bool" to "int" and definiing "true" and
    "false" creates problems because there are no namespaces, you export
    the symbols, and either they clash or they create mismash of subtly
    different Boolean types.

    Correct.

    So I am not recommending it in user code.

    Then what were you doing when you wrote this?

    """
         You can achieve most of the benefits of a boolean type by aliasing >>      "int' to "bool" and defining "true" and "false", and a lot of C
         installations do exactly this.
    """

    However I am saying that it does achieve most of the benefits of
    having a boolean type, and therefore people who do this are not
    entirely stupid. But I'm talking about the C installation, so
    normally the person who provides the compiler, not the user code.


    And what is a "C installation" ?  Do you mean a "C /implementation/" ?
    Do you mean your own modification to headers or libraries after you
    have installed a toolchain?  Do you mean a company's standard
    additional libraries?

    Or do you mean that C implementations simply put "typedef int bool;"
    as their <stdbool.h> implementation?  That would, of course, be utter
    nonsense.


    The "C installation " is not a rigorously defined concept and can be
    thought of as a fuzzy set. But basically it means someone who provides
    both the compiler and a library which must be used on that platform, and therefore has a similar status to the standard library, but just for
    that platform.

    That would be the "C implementation", and it /is/ a well-established
    term. It would be helpful if you used the standard terms here.

    So for example Mircrosoft provide a file called "windef.h" which
    contains the following declarations.

    typedef int                 BOOL;

    #ifndef FALSE
    #define FALSE               0
    #endif

    #ifndef TRUE
    #define TRUE                1
    #endif


    None of that defines "bool", "true" or "false". This is /very/ different.

    It is a typical pre-C99 pseudo-boolean, and made sense before C99. The "windef.h" file needs to keep these for compatibility, especially in
    light of MS's notoriously poor and late C99 support, but no one should
    consider using them for anything now except as required for
    compatibility with external code that has them. (For example, if you
    are calling a function that takes a "BOOL *" pointer, you can't replace
    that with a "bool *" pointer.)

    They use upper case. But otherwise it's exactly as I stated.

    And the upper case makes all the difference. As far as C is concerned,
    and as far as any trained C programmer is concerned, the difference is perfectly clear. Windows has a convention in its API and windef.h and windows.h headers of using all-caps names for locally defined type names
    that are specific and consistent for all Windows versions, and don't
    change according to the processor type - things like BYTE and LONG have
    existed from 16-bit Windows, through 32-bit and 64-bit Windows. They
    are not easily mistaken for the C standard types.

    In my view
    this is reasonable. But it wouldn't be reasonable in a libarary designed
    to do fast Fiurier transforms, for example. It's reasonable because
    windef.h is part of the "C installation".


    I agree that this was a reasonable practice from MS, prior to C99. I
    wish they had moved over to C99 types like "bool" and the sized integer
    types (int32_t, etc.) as soon as these were standardised, keeping the
    old all-caps types only for compatibility with old code, and deprecating
    them as soon as reasonably possible. But prior to C99 they couldn't
    really have done much better. And I agree that a major C
    implementation, and the nearest Windows has to standard platform
    headers, can reasonably claim generic names like BOOL.

    It is normal for C90 libraries to have their own types for things like booleans, but they should be named with prefixes like the rest of the
    library - so you might have "fft_Boolean". Of course, anything this
    century should be in at least C99 and use standard types, but this kind
    of thing still hangs around because some code stretches back to last
    century.

    But these types are /not/ a substitute for standard C bool. They don't
    do the same thing. They are not as good. They are not as standard.
    They were the best be had a generation ago, but there is no reason to
    use them now except for interfacing with old code, and certainly no
    reason to consider defining a new home-made boolean.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Tue Feb 13 11:36:46 2024
    On 13/02/2024 10:35, Malcolm McLean wrote:
    On 13/02/2024 08:07, David Brown wrote:
    On 12/02/2024 21:27, Malcolm McLean wrote:

    The "C installation " is not a rigorously defined concept and can be
    thought of as a fuzzy set. But basically it means someone who
    provides both the compiler and a library which must be used on that
    platform, and therefore has a similar status to the standard library,
    but just for that platform.

    That would be the "C implementation", and it /is/ a well-established
    term.  It would be helpful if you used the standard terms here.


    The "C implentation" would be be the program created by the person who
    writes the complier.

    No, that would be the compiler.

    The "C implementation" includes the compiler, associated tools like
    assemblers and linkers, headers, the standard C library, and parts of
    the target system that are needed in order to execute the program.

    The "C installation" the system set up by the
    person who provides the compiler.

    I am trying to understand what you mean by this - as usual, it is not
    easy as you insist on using your own invented terms in your own way, and
    have great difficultly explaining them to others.

    Maybe you are talking about what others might refer to as a "toolchain",
    which typically includes the non-compiler parts of the C implementation
    (like an assembler, linker, and standard library), as well as additional
    useful tools such as objcopy, make, a debugger, and perhaps an editor or
    IDE, and common platform-specific headers and libraries. MSVC is a
    toolchain, and comes with windef.h (amongst many other things). You
    might also refer to TDM as a Windows-hosted gcc toolchain.

    But you might also be talking about a customised setup, either done by
    an individual on their own systems, or by a company wanting all their developers to have the same development environment.


    Often one and the same, but not
    necessarily. You can have a compiler written by someone else and an API written by someone else, put them together, and say "this shall be what
    we use to create C programs for this platform". So you have set up the C installation, but you are not the implementor.


    The term "C implementation" is not connected to who makes the compiler, library, installation packages or anything else. It's a /thing/, not a
    person or group, and it is the characteristics of the C implementation
    that are important, not where it came from.


    So for example Mircrosoft provide a file called "windef.h" which
    contains the following declarations.

    typedef int                 BOOL;

    #ifndef FALSE
    #define FALSE               0
    #endif

    #ifndef TRUE
    #define TRUE                1
    #endif


    None of that defines "bool", "true" or "false".  This is /very/
    different.

    It is a typical pre-C99 pseudo-boolean, and made sense before C99.
    The "windef.h" file needs to keep these for compatibility, especially
    in light of MS's notoriously poor and late C99 support, but no one
    should consider using them for anything now except as required for
    compatibility with external code that has them.  (For example, if you
    are calling a function that takes a "BOOL *" pointer, you can't
    replace that with a "bool *" pointer.)

    They use upper case. But otherwise it's exactly as I stated.

    And the upper case makes all the difference.  As far as C is
    concerned, and as far as any trained C programmer is concerned, the
    difference is perfectly clear.  Windows has a convention in its API
    and windef.h and windows.h headers of using all-caps names for locally
    defined type names that are specific and consistent for all Windows
    versions, and don't change according to the processor type - things
    like BYTE and LONG have existed from 16-bit Windows, through 32-bit
    and 64-bit Windows.  They are not easily mistaken for the C standard
    types.

    In my view this is reasonable. But it wouldn't be reasonable in a
    libarary designed to do fast Fiurier transforms, for example. It's
    reasonable because windef.h is part of the "C installation".


    I agree that this was a reasonable practice from MS, prior to C99.  I
    wish they had moved over to C99 types like "bool" and the sized
    integer types (int32_t, etc.) as soon as these were standardised,
    keeping the old all-caps types only for compatibility with old code,
    and deprecating them as soon as reasonably possible.  But prior to C99
    they couldn't really have done much better.  And I agree that a major
    C implementation, and the nearest Windows has to standard platform
    headers, can reasonably claim generic names like BOOL.

    It is normal for C90 libraries to have their own types for things like
    booleans, but they should be named with prefixes like the rest of the
    library - so you might have "fft_Boolean".  Of course, anything this
    century should be in at least C99 and use standard types, but this
    kind of thing still hangs around because some code stretches back to
    last century.

    Yes, and it's a nightmare, because whilst it's obvious that an
    fft_boolean is a variable which is meant to represent "true" or "false",
    it's not so obvious where code which calls but does not implement the
    Fourier transforms should use it, and it might not even be binary
    compatible with other types in the program designed to do the same
    thing. A standrd atype is blessing, and all you really need for that is
    a simple standard header declaring "bool" as a type, and "true" and
    "false" as constants. Now "false" must be zero, But should "true" be 1
    or -1?

    Have you been living under a rock for the last 25 years? Do you write
    code for the OCCC, or are you aiming for a "featured article" in the
    Daily WTF?

    <https://thedailywtf.com/articles/what_is_truth_0x3f_> <https://thedailywtf.com/articles/Extra-Boolean>

    Yes, a standard boolean type is an extremely important feature in a
    programming language. The fact that C did not have one until C99 has
    resulted in a great deal of inconvenience and wasted effort. Then in
    1999, we got a standard boolean type in C. Use it! No, it is not
    sufficient to have a "typedef int bool" in a header to make a /good/
    boolean type. No, "true" should not be -1. No, you should never define
    your own type "bool".



    But these types are /not/ a substitute for standard C bool.  They
    don't do the same thing.  They are not as good.  They are not as
    standard. They were the best be had a generation ago, but there is no
    reason to use them now except for interfacing with old code, and
    certainly no reason to consider defining a new home-made boolean.

    I discussed using Pico C to implement a build system recently. Now I
    have't checked, but it's not fully featured and I don't think it
    supports coercing a boolean to be 1 or 0. But by providing a trivial
    header we could get most C source which uses "bool" to interpret
    correctly. And that would be a lot easier than trying to modify the interpeter. Of course

    char *ptr = something();
    bool flag = (bool) ptr;
    if (flag == true)

    will not be interpreted correctly. But we can live with that.

    We can live with all kinds of things - that does not mean we /should/
    live with it.

    Pico C appears to be a dead project. And it was never intended to be
    more than a tiny handler for a subset of C - of unspecified version, and without any attempt at conformance. It's broken version of <stdbool.h>
    is dangerously wrong and has no place in anything that claims to call
    itself "C" or "C-like". It should be either fixed, or removed entirely.
    But as it is a dead project there is little point in reporting the error.



    The Pico C would be our "C installation" by the way.

    Or, to use the correct term, the "C implementation". Or perhaps the
    "Sort-of C implementation".

    We wouldn't claim
    to be the implenters. Not every word has to have been used before in
    exactly the same context to be used correctly, as you seem to think.


    Do you have any reason or purpose behind your deliberate and continuous
    misuse of terms and your insistence on making up your own language? I
    can appreciate that you are often ignorant about the C language, the C standards, and the terms used there. Ignorance is not a problem - it's
    easily cured by someone giving you the missing knowledge or correcting mistakes. This is part of what we do in this group - helping each other understand more about C. But when you have been told the correct terms,
    please use them.

    (Now let's start a flame war because I did English at Oxford whilst you didn't).

    Let's not.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to David Brown on Tue Feb 13 12:32:17 2024
    On 13/02/2024 10:36, David Brown wrote:
    On 13/02/2024 10:35, Malcolm McLean wrote:
    On 13/02/2024 08:07, David Brown wrote:

    The "C implentation" would be be the program created by the person who
    writes the complier.

    No, that would be the compiler.

    The "C implementation" includes the compiler, associated tools like assemblers and linkers, headers, the standard C library, and parts of
    the target system that are needed in order to execute the program.

    The "C installation" the system set up by the person who provides the
    compiler.

    I am trying to understand what you mean by this - as usual, it is not
    easy as you insist on using your own invented terms in your own way, and
    have great difficultly explaining them to others.

    Maybe you are talking about what others might refer to as a "toolchain",


    It seems clear to me what the difference is between installation and implementation.

    A factory implements a washing machine, and somebody else decides where
    to install it in their house and how and to what it is hooked up.

    There might be have two or more installations.

    My original C compiler had one of the simplest possible installations:
    just run the EXE from wherever it happens to be. Yet even there, you
    need to know /where/ it is installed, even if it's just to add that
    location to a set of search paths.

    Installing two gcc versions on Windows is problematical because gcc
    invokes other binaries. Because rather than using paths relative to the
    gcc.exe that was run, it uses system PATH settings, so that when it
    invokes ld.exe for example, it may end up with ld.exe belonging to the
    other installation.

    This is little to do with implementation (other than the implementation
    is buggy IMO).


    Often one and the same, but not necessarily. You can have a compiler
    written by someone else and an API written by someone else, put them
    together, and say "this shall be what we use to create C programs for
    this platform". So you have set up the C installation, but you are not
    the implementor.


    The term "C implementation" is not connected to who makes the compiler, library, installation packages or anything else.  It's a /thing/, not a person or group, and it is the characteristics of the C implementation
    that are important, not where it came from.

    So it just 'exists' without anyone having created it?


    Yes, a standard boolean type is an extremely important feature in a programming language.  The fact that C did not have one until C99 has resulted in a great deal of inconvenience and wasted effort.  Then in
    1999, we got a standard boolean type in C.  Use it!  No, it is not sufficient to have a "typedef int bool" in a header to make a /good/
    boolean type.  No, "true" should not be -1.  No, you should never define your own type "bool".

    It's not /that/ important. The concept is more important than having a dedicated type.

    I added a proper boolean type to my scripting language at one point.
    Then I streamlined it and got rid of it.

    There is an `integer` type which can represent a million different kinds
    of things; why make a special type for a thing that has the values of 0
    or 1?

    (In dynamic code, extra types mean spending longer doing runtime type checking.)

    A proper _Bool type gives the possibility of arrays of _Bools that
    occupy one bit per element. However that doesn't happen here:

    _Bool A[1024];
    printf("%zu\n", sizeof(A));

    I get '1024' with gcc -O3, not 128. (My scripting language, despite not
    having Bool, does have 1-bit arrays. Those can be more useful.)

    will not be interpreted correctly. But we can live with that.

    We can live with all kinds of things - that does not mean we /should/
    live with it.

    Pico C appears to be a dead project.  And it was never intended to be
    more than a tiny handler for a subset of C - of unspecified version, and without any attempt at conformance.  It's broken version of <stdbool.h>
    is dangerously wrong and has no place in anything that claims to call
    itself "C" or "C-like".  It should be either fixed, or removed entirely.

    You're fond of saying that.

     But as it is a dead project there is little point in reporting the error.



    The Pico C would be our "C installation" by the way.

    Or, to use the correct term, the "C implementation".  Or perhaps the "Sort-of C implementation".

    Even C++ is a 'sort-of-C' implementation.

    Suppose you have a C program that uses 85% of the features of C. You use
    a C compiler which only implements that same 85% subset. Your program
    works perfectly.

    But I guess you would still look down your knows at such a product?

    Some C compilers implement a subset of the language, some a superset. I
    expect a superset is fine? But neither are actually C!

    And of course, using compiler options to further customise the language
    is also acceptable.

    "PicoC is a very small C interpreter for scripting. It was originally
    written as the script language for a UAV's on-board flight system. It's
    also very suitable for other robotic, embedded and non-embedded
    applications."

    Do you object to its use of "C"?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Tue Feb 13 14:15:22 2024
    On 13/02/2024 13:12, Malcolm McLean wrote:
    On 13/02/2024 10:36, David Brown wrote:
    On 13/02/2024 10:35, Malcolm McLean wrote:

    I am trying to understand what you mean by this - as usual, it is not
    easy as you insist on using your own invented terms in your own way,
    and have great difficultly explaining them to others.

    Now this sort of thing irritates some of the others, and so I shouldn't
    have to explain and justify to some people the basics of how to use the English language.

    The way to avoid this would be to use standard terms correctly in the
    first place. And if what you intend to say is not covered by the
    standard term, explain what you mean - don't just leap in with yet
    another home-made term and expect everyone else to read your mind.


    But you might also be talking about a customised setup, either done by
    an individual on their own systems, or by a company wanting all their
    developers to have the same development environment.

    Yes, can be the second. Embedded developers talk about "toolchains" but non-embedded developers mostly don't, and it's not really relevant that
    in a typical C implemntation several programs are run to create the exectuable instead of only one. But it is relevant that all the
    developers have the same development environment. If everyone shall use "BOOL" rather than "bool" because that is the customised common header
    chosen by the company, that's exactly what I am talking about.

    Finally we are getting somewhere.



    Yes, and it's a nightmare, because whilst it's obvious that an
    fft_boolean is a variable which is meant to represent "true" or
    "false", it's not so obvious where code which calls but does not
    implement the Fourier transforms should use it, and it might not even
    be binary compatible with other types in the program designed to do
    the same thing. A standrd atype is blessing, and all you really need
    for that is a simple standard header declaring "bool" as a type, and
    "true" and "false" as constants. Now "false" must be zero, But should
    "true" be 1 or -1?

    Have you been living under a rock for the last 25 years?  Do you write
    code for the OCCC, or are you aiming for a "featured article" in the
    Daily WTF?

    <https://thedailywtf.com/articles/what_is_truth_0x3f_>
    <https://thedailywtf.com/articles/Extra-Boolean>

    "Have you stopped beating your wife?"
    True / false often isn't adequate.

    I did not expect a yes/no answer to these rhetorical questions, and did
    not in any way suggest that I was looking for one.

    I was ridiculing the idea of making more home-made booleans 25 years
    after they became unnecessary and outdated, and especially the idea of
    doing something as silly as making "true" have the value -1.



    Yes, a standard boolean type is an extremely important feature in a
    programming language.  The fact that C did not have one until C99 has
    resulted in a great deal of inconvenience and wasted effort.  Then in
    1999, we got a standard boolean type in C.  Use it!  No, it is not
    sufficient to have a "typedef int bool" in a header to make a /good/
    boolean type.  No, "true" should not be -1.  No, you should never
    define your own type "bool".

    true can be -1 in boolean logic.

    No, it cannot. Boolean logic has "true" and "false", sometimes donated
    1 and 0 for convenience. As a logic system, these 1 and 0
    representations bear no relation to the normal numbers 1 and 0 - they
    are just symbols.

    Programming language implementations always need to represent things as
    numbers in the end, since that is what computer hardware deals with.
    How the logical concepts of "true" and "false" are represented is
    arbitrary, though usually picked to be efficient to implement and
    helpful to programmers if the language supports conversion from boolean
    types to number types. Some languages use -1 for "true" in this sense,
    others treat all non-zero values as "true". It is most common, I
    believe, to see 1 as the canonical representation of "true". Some,
    however, will use 0 for "true" and 1 for "false", or 'T' for true and
    'F' for false, or other values.

    The relevant language here is C. And C99 _Bool uses 1 for true. In all versions of C, the relational operators and logical operators yield 1
    for true, and 0 for false. Picking a value for a constant called "true"
    such that "(true == true) != true" is considered "true" by the language
    would be insane.

    The real reason is that -1 is all bits
    set, so ~true == false. But of course a one bit number is either -1 or 0
    in two;s complement notation.
    However someone has to take decsion on this and there should be one
    standard, I totally agree.

    That decision was taken 50+ years ago when C was conceived.


    Pico C appears to be a dead project.  And it was never intended to be
    more than a tiny handler for a subset of C - of unspecified version,
    and without any attempt at conformance.  It's broken version of
    <stdbool.h> is dangerously wrong and has no place in anything that
    claims to call itself "C" or "C-like".  It should be either fixed, or
    removed entirely.   But as it is a dead project there is little point
    in reporting the error.

    There aren't that many open source, free to use C intepreters hanging
    around.

    That does not make Pico C any less of a dead project, or mean that it
    handles anything other than a vaguely defined language based on a subset
    of some unspecified version of C with dangerous (or at least unhelpful) additions that differ pointlessly from standard C.

    It might still be a useful tool. Just don't treat it as anything it is
    not, and do not use it as some kind of justification for
    misunderstanding "bool" in C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to bart on Tue Feb 13 13:56:12 2024
    bart <bc@freeuk.com> writes:

    On 13/02/2024 10:36, David Brown wrote:
    On 13/02/2024 10:35, Malcolm McLean wrote:
    On 13/02/2024 08:07, David Brown wrote:

    The "C implentation" would be be the program created by the person who
    writes the complier.
    No, that would be the compiler.
    The "C implementation" includes the compiler, associated tools like
    assemblers and linkers, headers, the standard C library, and parts of the
    target system that are needed in order to execute the program.

    The "C installation" the system set up by the person who provides the
    compiler.
    I am trying to understand what you mean by this - as usual, it is not
    easy as you insist on using your own invented terms in your own way, and
    have great difficultly explaining them to others.
    Maybe you are talking about what others might refer to as a "toolchain",

    It seems clear to me what the difference is between installation and implementation.

    And yet I don't think you have understood what Malcolm means.

    A factory implements a washing machine, and somebody else decides where to install it in their house and how and to what it is hooked up.

    But that can be you or I, and Malcolm has at last explained that the key
    point (at least for him) is one of authority: the "installer" has the
    authority (or maybe just the commercial clout) to insist on "the
    installation" having a Boolean type, maybe even a non-standard one.

    The person who "sets things up" (the "installer" of the "installation")
    in Malcolm's world is Microsoft or Nintendo, not the person who
    typically installs software on a single user machine. It could (I am
    sure) be your employer, as they have the authority to insist you use
    some specific Boolean type, so it is certainly not the same as a "C implantation" in the sense used by the C standard.

    Comp.lang.c has become so polarised that I can see how you want to be "on Malcolm's side" here, but until just now he had not explained how he was
    using the vague term "C installation". It's fine to avoid jargon, but
    you do then have to explain what you mean, and it's still not 100% clear.

    Ironically, an authority, the WG14 committee, has indeed decreed that "C installations" should have a Boolean type spelled "bool" with "true" and "false" as keywords.

    It would have been so much simpler had he said, right off the bat, that
    some entities (Microsoft, the WG14 committee, your employer) have the
    clout to get away with insisting on a Boolean type, but library authors
    do not. We could disagree with that, but at least we'd all be on the
    same page to start with.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to bart on Tue Feb 13 15:10:03 2024
    On 13/02/2024 13:32, bart wrote:
    On 13/02/2024 10:36, David Brown wrote:
    On 13/02/2024 10:35, Malcolm McLean wrote:
    On 13/02/2024 08:07, David Brown wrote:

    The "C implentation" would be be the program created by the person
    who writes the complier.

    No, that would be the compiler.

    The "C implementation" includes the compiler, associated tools like
    assemblers and linkers, headers, the standard C library, and parts of
    the target system that are needed in order to execute the program.

    The "C installation" the system set up by the person who provides the
    compiler.

    I am trying to understand what you mean by this - as usual, it is not
    easy as you insist on using your own invented terms in your own way,
    and have great difficultly explaining them to others.

    Maybe you are talking about what others might refer to as a "toolchain",


    It seems clear to me what the difference is between installation and implementation.

    A factory implements a washing machine, and somebody else decides where
    to install it in their house and how and to what it is hooked up.

    I would agree with that difference (and the distinction you made below,
    which I snipped for brevity).

    But it is not, apparently, what Malcolm is talking about.

    However, I am pretty sure that that discussion is going nowhere, and
    Malcolm will continue in his Humpty-Dumpty quest to use words to mean
    exactly what /he/ thinks they mean, rather than trying to communicate
    sensibly with others. And I am also fairly sure that it doesn't affect
    the issues with booleans.


    Often one and the same, but not necessarily. You can have a compiler
    written by someone else and an API written by someone else, put them
    together, and say "this shall be what we use to create C programs for
    this platform". So you have set up the C installation, but you are
    not the implementor.


    The term "C implementation" is not connected to who makes the
    compiler, library, installation packages or anything else.  It's a
    /thing/, not a person or group, and it is the characteristics of the C
    implementation that are important, not where it came from.

    So it just 'exists' without anyone having created it?


    No. But the creator is irrelevant. A car is a "car" because of how it
    works and what you can do with it. It doesn't matter if you built it
    yourself or bought one pre-built.


    Yes, a standard boolean type is an extremely important feature in a
    programming language.  The fact that C did not have one until C99 has
    resulted in a great deal of inconvenience and wasted effort.  Then in
    1999, we got a standard boolean type in C.  Use it!  No, it is not
    sufficient to have a "typedef int bool" in a header to make a /good/
    boolean type.  No, "true" should not be -1.  No, you should never
    define your own type "bool".

    It's not /that/ important. The concept is more important than having a dedicated type.

    The concept is made a lot clearer by having a dedicated type.


    I added a proper boolean type to my scripting language at one point.
    Then I streamlined it and got rid of it.

    There is an `integer` type which can represent a million different kinds
    of things; why make a special type for a thing that has the values of 0
    or 1?

    The special type should hold values of true and false - it is the
    restriction of the values that makes it special, and makes it suitable
    for the concept of a boolean truth value. The restriction of values is key.


    (In dynamic code, extra types mean spending longer doing runtime type checking.)

    A proper _Bool type gives the possibility of arrays of _Bools that
    occupy one bit per element. However that doesn't happen here:

        _Bool A[1024];
        printf("%zu\n", sizeof(A));

    I get '1024' with gcc -O3, not 128. (My scripting language, despite not having Bool, does have 1-bit arrays. Those can be more useful.)

    C's concepts of objects and arrays disallow such compact arrays. This
    is both a limitation and a feature. On the one hand, it means you can't conveniently have space-saving bit/bool arrays. On the other hand, it
    means that if "xs" is an array, you can always access different elements independently, all objects have unique addresses (within their
    lifetimes), underlying representations of objects can copied with
    memcpy(), every object has a "sizeof" size in bytes, and so on. Compact bit/bool arrays are a useful concept, but would not fit as normal arrays
    in C.


    will not be interpreted correctly. But we can live with that.

    We can live with all kinds of things - that does not mean we /should/
    live with it.

    Pico C appears to be a dead project.  And it was never intended to be
    more than a tiny handler for a subset of C - of unspecified version,
    and without any attempt at conformance.  It's broken version of
    <stdbool.h> is dangerously wrong and has no place in anything that
    claims to call itself "C" or "C-like".  It should be either fixed, or
    removed entirely.

    You're fond of saying that.

    I think it is important.

    I'm fine with compilers (or other C tools) handling only a subset of C,
    or only an older version of the language. I'm fine with them having extensions. I'm fine with them being not quite perfect, or having some limitations or missing elements. But there are three things I want
    tools to do:

    1. Document what version of the C standards they support, what
    limitations or subsets it has, and what extensions it has. Document how
    to enable or disable these.

    2. Make it clear right at the start if it really is a "C" tool, able to
    conform substantially to at least one C standard, or a "Sort-of C" tool
    that has significant and intentional deviations.

    3. Do not have features that are syntactically the same as features of
    C, but do not conform semantically to C. If there are outstanding
    reasons for this, then it must at least be clearly documented.


    Pico C breaks point 3 here, and it does so for no good reason. It could
    simply have omitted <stdbool.h> and been just as useful. There is no
    situation in which it is a good idea to have a <stdbool.h> header
    defining a "bool" type that does not conform to the C99 "_Bool" type.

    I've seen other compilers break point 3 for at least somewhat good
    reasons, such as microcontroller compilers that have 32-bit "double" types.

    The problem with this is that existing correct code could appear to
    compile cleanly, but not work as expected even if the code was fully
    portable conforming C. That is never a good thing.


    I am not saying that tools that break these rules are not useful - I am
    simply saying that I want tools that do so to be clear about it and
    document it.


      But as it is a dead project there is little point in reporting the
    error.



    The Pico C would be our "C installation" by the way.

    Or, to use the correct term, the "C implementation".  Or perhaps the
    "Sort-of C implementation".

    Even C++ is a 'sort-of-C' implementation.

    You could certainly consider it as having a sort-of C subset, yes.


    Suppose you have a C program that uses 85% of the features of C. You use
    a C compiler which only implements that same 85% subset. Your program
    works perfectly.

    But I guess you would still look down your knows at such a product?


    If it implements a useful 85% subset of C (of some standard), and
    /documents/ its missing features, that's fine.

    I am fine with an implementation that says it implements C99 except for
    complex numbers, wide characters and VLAs. No problem.

    I am not fine an implementation that says it implements C99, and
    provides <complex.h> where functions like ccos() were implement as a
    simple "return" assembly instruction.

    Do you see the difference?


    Some C compilers implement a subset of the language, some a superset. I expect a superset is fine? But neither are actually C!


    Supersets are also fine, as long as they don't conflict with conforming
    C. (It's okay if there are documented ways to enable or disable them.
    A compiler could have "asm" statements as an extension, but should have
    a flag to disable this for code that uses "asm" as an identifier.) And
    to be useful, they should be documented.

    And of course, using compiler options to further customise the language
    is also acceptable.

    Yes, when documented.


    "PicoC is a very small C interpreter for scripting. It was originally
    written as the script language for a UAV's on-board flight system. It's
    also very suitable for other robotic, embedded and non-embedded applications."

    Do you object to its use of "C"?


    I don't know if it is close enough to some version of C for it to be
    reasonable to call it a "C compiler" (or "C interpreter") without qualification. I haven't looked at it in any kind of detail. But I
    /do/ know it has a <stdbool.h> header that most certainly does not
    define a C "bool" type, and I see that as a problem. In particular, it
    is a pointless problem - it serves no purpose, but could cause subtle
    problems when used with code that is correct and conforming C, tested
    and debugged with other implementations.

    That does not mean that it is not a useful tool. But it would, IMHO, be
    a /better/ tool if that header were simply omitted entirely.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Keith Thompson on Tue Feb 13 16:52:56 2024
    On 09.02.2024 18:09, Keith Thompson wrote:

    I suggest that the bug of using "=" where "==" was intended occurs
    almost exclusively among inexperienced C programmers, particularly those
    who are inexperienced with programming in general.

    This opinion doesn't reflect reality.

    Or only if by "inexperienced C programmers" you mean folks that
    just haven't learned the C language - and have nonetheless been
    assigned C tasks? - but such folks are no "C programmers" in the
    first place.


    It's a mistake that's made because the programmer assumes that "="
    is a comparison operator, as it is in mathematics and in some other programming languages.

    A precondition to be a programmer is that they know the language
    (or otherwise first learn it); they certainly don't "assume" what
    the syntax and basic semantics is. If you let folks ignorant of C
    program your task you have a lot more problems than the assignment
    operator.

    It's an easy and understandable mistake
    to make, but any reasonably experienced C programmer will have
    internalized the fact that "=" means assignment, not comparison.
    To a newbie, `if (x = y)` *looks like* a comparison. To an
    experienced C programmer it doesn't.

    (It's possible I'm overgeneralizing. For example, a programmer who
    commonly switches between C and other languages might still mix up "="
    and "==" occasionally.)

    Yes, this is the case. Another case is where people still have the
    mathematical notation in mind and refusing (=don't get used to) the
    fact that "Reality" is "C". And sometimes it's just a typo.


    If C had used ":=" for assignment and "=" for comparison (and "=="
    probably not used for anything), the problem would never have come up, because ":=" doesn't look like a comparison even to a newbie. But it's
    far too late to fix that in any language called "C".

    Indeed.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Tue Feb 13 16:54:38 2024
    On 09.02.2024 14:43, David Brown wrote:
    [...]

    There are plenty of coding standards which ban the use of the results of assignment expressions, and I think there is little doubt that stricter coding standards reduce at least some kinds of errors in code. But it
    would be impossible to isolate the effect of one particular rule.

    If someone knows about such studies, it would be great to hear about
    them - failing that, guesses and gut feelings based on personal
    experience is about as good as we can get.

    In the contexts I was working I never experienced (own or others')
    real problems with cascading assignments. The only problems arose
    with the if-assignment cases; to detect these errors at that time
    time was lost (unnecessarily). (A price we had to pay when using
    C/C++.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Tue Feb 13 16:55:02 2024
    On 10.02.2024 16:53, David Brown wrote:

    In MISRA 1998, the explanation for that rule includes:

    """
    Strictly speaking, in C, there is no Boolean type, but there is a
    conceptual difference between expressions which return a numeric value
    and expressions which return a Boolean value.

    If assignments are required then they must be performed separately
    outside of any expressions which are effectively of Boolean type.
    """

    MISRA regularly uses its own terms that are different from the Standard
    C terms, which IMHO is needlessly confusing and inaccurate. Sometimes
    these terms are defined, sometimes not. "Boolean" and "Effectively
    Boolean value" are not defined anywhere in MISRA 1998.

    I don't know MISRA, but to me the two terms are quite clear in this
    context; they are referring to the differentiation in the preceding
    paragraph.

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Tue Feb 13 17:00:00 2024
    On 12.02.2024 02:17, Lawrence D'Oliveiro wrote:

    You seem to be saying that something like

    bool a = b == c;

    should not be allowed.

    I have the habit to write such specific expressions with parenthesis

    a = (b == c);

    for own convenience or better maintainability. (Just BTW.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Keith Thompson on Tue Feb 13 17:09:48 2024
    On 13.02.2024 00:33, Keith Thompson wrote:
    "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:

    https://www.stroustrup.com/JSF-AV-rules.pdf

    Yes, and?

    I suppose it meant to use coding standards to prevent the worst and
    make programmers aware of potential issues and pitfalls.


    That's a 141-page PDF document with rules for C++. Did you want to say something about it?

    My first thought was: "How long will project start be delayed until
    every project member will have read (and understood) that document?"

    We used in the past also standards; one 80 page document (don't recall
    its name, but it was internationally well established in the 1990's),
    and an own one of much smaller size.

    Of course it depends on the language. Well designed better languages
    might need less standards that languages with lots of pitfalls (and
    options).

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Tue Feb 13 17:13:23 2024
    On 13/02/2024 16:55, Janis Papanagnou wrote:
    On 11.02.2024 18:05, David Brown wrote:

    Yes, we all know that. (Well, everyone who has learned a bit of C99
    knows that.) It's very difficult to change things in a language that
    has as much use as C - changing the type of the value of expressions
    like "x == y" would have been a breaking change. When C++ was forked
    from C, it was able to make such breaking changes - thus "x == y" gives
    a bool in C++. But for C, it was too late.

    You are mistaken; C++ had no 'bool' type initially. It had been added
    later.


    It was there from the first standard version of C++. At that point, it
    was still possible to make breaking changes - such as changing the type
    of the result of comparison operators. But you are correct that it did
    not exist in early drafts of C++ prior to standardisation.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Janis Papanagnou on Tue Feb 13 18:11:58 2024
    On Tue, 13 Feb 2024 16:55:32 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 11.02.2024 18:05, David Brown wrote:

    Yes, we all know that. (Well, everyone who has learned a bit of C99
    knows that.) It's very difficult to change things in a language
    that has as much use as C - changing the type of the value of
    expressions like "x == y" would have been a breaking change. When
    C++ was forked from C, it was able to make such breaking changes -
    thus "x == y" gives a bool in C++. But for C, it was too late.

    You are mistaken; C++ had no 'bool' type initially. It had been added
    later.

    Janis


    Pre-history vs history.
    As far as I am concerned, 'initially' == it presents in in the first
    edition of "The C++ Programming Language".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Tue Feb 13 17:14:29 2024
    On 11.02.2024 13:57, David Brown wrote:

    [...] They had been trying to rule out "if (x = y)"
    and requiring it to be written "x = y; if (x != 0) ...".

    One could of course also have written it as

    if (x = y) // this is intentionally an assignment!

    Sometimes a comment is better than asking to rewrite the code.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to All on Tue Feb 13 17:29:43 2024
    On 09/02/2024 16:43, bart wrote:
    What I wouldn't care about banning however is this:

    a += b += c;

    Because it's just confusing. If you don't think so, consider a, b, c
    all having different numerical types.

    To *ban* something because it is confusing to you?
    Thus adding inconsistencies to the language?

    What is it that confuses you? - I am assuming you know the operator
    precedence rules, and that x += y like x = y returns a value?

    Does using parenthesis to sort things maybe help you?

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Keith Thompson on Tue Feb 13 18:23:31 2024
    On Fri, 09 Feb 2024 09:09:41 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:


    If C had used ":=" for assignment and "=" for comparison (and "=="
    probably not used for anything), the problem would never have come up, because ":=" doesn't look like a comparison even to a newbie. But
    it's far too late to fix that in any language called "C".


    If DMR ever considered := for assignment then it probably lasted no
    longer than it took him to pay attention that in order to type ':' on
    the standard keyboard one has to press shift.
    But I think that he didn't consider it at all, due to reasoning that in
    most programs assignments are far more common than comparisons for
    equality. So, given his attitude,it was obvious to him which one of
    the two has to be single character and which one can afford longer
    form.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Tue Feb 13 17:34:31 2024
    On 13/02/2024 17:14, Janis Papanagnou wrote:
    On 11.02.2024 13:57, David Brown wrote:

    [...] They had been trying to rule out "if (x = y)"
    and requiring it to be written "x = y; if (x != 0) ...".

    One could of course also have written it as

    if (x = y) // this is intentionally an assignment!

    Sometimes a comment is better than asking to rewrite the code.


    That is sometimes the case, but not here.

    It is better to write the code clearly than to have a comment explaining
    why you have written code that looks odd.

    If the re-written code looked odd or was unclear, then you would have a
    point.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Tue Feb 13 17:30:47 2024
    On 13/02/2024 16:20, Malcolm McLean wrote:
    On 13/02/2024 14:10, David Brown wrote:
    On 13/02/2024 13:32, bart wrote:


    "PicoC is a very small C interpreter for scripting. It was originally
    written as the script language for a UAV's on-board flight system.
    It's also very suitable for other robotic, embedded and non-embedded
    applications."

    Do you object to its use of "C"?


    I don't know if it is close enough to some version of C for it to be
    reasonable to call it a "C compiler" (or "C interpreter") without
    qualification.  I haven't looked at it in any kind of detail.  But I
    /do/ know it has a <stdbool.h> header that most certainly does not
    define a C "bool" type, and I see that as a problem.  In particular,
    it is a pointless problem - it serves no purpose, but could cause
    subtle problems when used with code that is correct and conforming C,
    tested and debugged with other implementations.

    So this is how they do it.

    By "they", you mean "the Pico C source code" rather than any users of
    Pico C, or anyone else.


    /* string.h library for large systems - small embedded systems use
    clibrary.c instead */
    #include "../interpreter.h"

    #ifndef BUILTIN_MINI_STDLIB

    static int trueValue = 1;
    static int falseValue = 0;


    /* structure definitions */
    const char StdboolDefs[] = "typedef int bool;";

    /* creates various system-dependent definitions */
    void StdboolSetupFunc(Picoc *pc)
    {
        /* defines */
        VariableDefinePlatformVar(pc, NULL, "true", &pc->IntType, (union AnyValue *)&trueValue, FALSE);
        VariableDefinePlatformVar(pc, NULL, "false", &pc->IntType, (union AnyValue *)&falseValue, FALSE);
        VariableDefinePlatformVar(pc, NULL,
    "__bool_true_false_are_defined", &pc->IntType, (union AnyValue
    *)&trueValue, FALSE);
    }

    #endif /* !BUILTIN_MINI_STDLIB */

    Whilst I have't actually checked, presumably the interpreter calls StdBoolSetUpFunc() when it hits "#include <stdbool.h>", and that puts variables called "true" and "false" which are ints into global scope,
    plus another int (not a boolean ironically) to flag that the function
    has been called. Somehow the typedef is picked up elsewhere.


    That does not mean that it is not a useful tool.  But it would, IMHO,
    be a /better/ tool if that header were simply omitted entirely.


    Now this means that the vast majority of code which is sanely written
    and uses "stdbool.h", but isn't written specifically for Pico C, will be interpreted correctly.

    That is not true.

    Code that relies on "bool" values being 0 or 1 is perfectly "sane", and
    will not work with the broken "bool" in Pico C.

    Code that uses "bool b = p;", where "p" is a pointer, is perfectly sane
    and may not work if Pico C correctly complains about the constraint
    error from "int b = p;".


    It is true that a lot of code that uses "bool", "true" and "false" will
    work in the face of "typedef int bool". It is also true that some will
    not - and there was nothing wrong or insane about the code. Such code
    may fail subtly with Pico C, and only in some circumstances. People
    using it will have to check their code, and change anything of the form
    "bool b = x;" into "bool b = !!x;" to be sure.



    But an tiny amount may break. And if it is
    running on a UAV which is armed with a nuclear missile, that may be a
    bit alarming. But mostly it won't be, and it will be fine.


    I am not at ease with an attitude of "There's a completely unnecessary,
    known and easily fixable mistake in this software, but hopefully you
    won't be using the tool for anything too serious and won't have many
    problems". That is simply not how a programmer should think.

    This one case rules out Pico C for me. I can agree that most uses of
    "bool" will be okay - but apparently the Pico C author couldn't care
    less about such things, and has neither the knowledge nor interest in
    finding out how C is defined, and the project has no reviewers, testers,
    bug reporters or checkers who are capable of confirming its correctness.
    I could not trust that the program is doing the right thing for
    anything else - there could be countless other small subtle things that
    would go wrong with perfectly good C code. (Looking through the issues
    for the project, it seems this is definitely the case.)

    Don't misunderstand me here - I have no reason to demand or expect that
    the Pico C author should only write quality tools that conform
    accurately to the C standards. He/she could have written a simple
    little tool, and published it for others to play with. And maybe it is
    good enough for some uses. But it is not of the quality I would want
    for a language tool - at least not without clear information and
    documentation about its limitations.

    I have filed this issue with Pico C, despite the project being dead, so
    that anyone considering using it can see the problem.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Michael S on Tue Feb 13 17:06:00 2024
    Michael S <already5chosen@yahoo.com> writes:
    On Fri, 09 Feb 2024 09:09:41 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:


    If C had used ":=" for assignment and "=" for comparison (and "=="
    probably not used for anything), the problem would never have come up,
    because ":=" doesn't look like a comparison even to a newbie. But
    it's far too late to fix that in any language called "C".


    If DMR ever considered := for assignment then it probably lasted no
    longer than it took him to pay attention that in order to type ':' on
    the standard keyboard one has to press shift.

    The keyboard DMR used when developing C did not require shift
    to type a colon.

    https://en.wikipedia.org/wiki/Teletype_Model_33#/media/File:Mappa_Teletype_ASR-33.jpg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Tue Feb 13 17:52:31 2024
    On 12.02.2024 02:13, Lawrence D'Oliveiro wrote:

    But boolean is a subtype of int anyway, so what’s the harm in redefining conditional expressions to return bool instead?

    Well, no harm, but some useful constructs would probably not work
    any more.

    Just this morning I wrote[*], for example,

    size = (size+1+shift)%3; // cycle through three sizes

    where 'shift' is actually a boolean (with possible values 0 and 1).

    We can of course argue whether that expression is anyway obscure
    or cryptic and should be avoided, but such code exists.

    And so I have to correct myself; it would be a "harm" if existing
    code would have to be rewritten.

    Janis

    [*] Actually in Javascript, but the expression is also valid in C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Tue Feb 13 17:39:40 2024
    On 09.02.2024 22:31, Lawrence D'Oliveiro wrote:
    On Fri, 9 Feb 2024 19:47:45 -0000 (UTC), Blue-Maned_Hawk wrote:

    There are too many situations where assignment being an expression is a
    useful facet of the language; i am not willing to sacrifice that for an
    ill-defined ideal of “safety”.

    If you consider it “ill-defined”, consider the number of people who have developed the habit of writing

    if (NULL == p) ...

    instead of the more natural

    if (p == NULL) ...


    I stumbled about such a suggestion first (I think) in Java.

    But this suggestion is actually a fallacy.

    If you have to _think_ about re-writing the "natural"
    'compare whether variable has value' then you are already
    _thinking_ about the theoretical issue and can also just
    take care to use '==' instead of '='.

    Besides that general issue with that suggestion it's also
    only applicable if comparing variables to constants.
    if (q = p) isn't better than if (p = q)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Janis Papanagnou on Tue Feb 13 19:22:57 2024
    On Tue, 13 Feb 2024 17:29:43 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 09/02/2024 16:43, bart wrote:
    What I wouldn't care about banning however is this:

    a += b += c;

    Because it's just confusing. If you don't think so, consider a, b,
    c all having different numerical types.

    To *ban* something because it is confusing to you?
    Thus adding inconsistencies to the language?

    What is it that confuses you? - I am assuming you know the operator precedence rules, and that x += y like x = y returns a value?

    Does using parenthesis to sort things maybe help you?

    Janis


    It's actually highly confusing for me as well.
    For reasons I am not fully understand, it is interpreted as
    a += (b += c)
    which is obviously legal.
    I don't understand why it isn't interpreted as
    (a += b) += c
    which is [a little less obviously] illegal.
    Seems like += associates from right to left, same like =.
    IMHO, it would have been more natural if it was associating from left
    to right, like + most other operators.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Michael S on Tue Feb 13 17:30:09 2024
    On 2024-02-13, Michael S <already5chosen@yahoo.com> wrote:
    On Tue, 13 Feb 2024 17:29:43 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 09/02/2024 16:43, bart wrote:
    What I wouldn't care about banning however is this:

    a += b += c;

    Because it's just confusing. If you don't think so, consider a, b,
    c all having different numerical types.

    To *ban* something because it is confusing to you?
    Thus adding inconsistencies to the language?

    What is it that confuses you? - I am assuming you know the operator
    precedence rules, and that x += y like x = y returns a value?

    Does using parenthesis to sort things maybe help you?

    Janis


    It's actually highly confusing for me as well.
    For reasons I am not fully understand, it is interpreted as
    a += (b += c)
    which is obviously legal.

    What's there not to fully understand? Assignment operators
    have right to left associativity so that this works:

    i = j = k = 0

    The arithmetic assignment operators follow suit.

    I don't understand why it isn't interpreted as
    (a += b) += c
    which is [a little less obviously] illegal.

    It is much more obviously illegal: (a += b) isn't an lvalue,
    and may not be assigned.

    Because assignment requires an lvalue, and this interpretation ensures
    that the left side of all but the leftmost assignment will not be an
    lvalue.

    Now we could allow (a += b) to be an lvalue. For instance,
    it could denote the same location as a. Would that be good?

    Now (a += b) += c modifies a twice, without any sequencing
    in between! Unless we make other adjustments in the language,
    we have undefined behavior.

    If your intent is to increment a by b and c, you can just do:

    a += (b + c)

    though of course it has a different overflow and conversion
    profile compared to a += b; a += c;

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Michael S on Tue Feb 13 17:33:00 2024
    On Tue, 13 Feb 2024 19:22:57 +0200, Michael S wrote:

    On Tue, 13 Feb 2024 17:29:43 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 09/02/2024 16:43, bart wrote:
    What I wouldn't care about banning however is this:

    a += b += c;

    Because it's just confusing. If you don't think so, consider a, b,
    c all having different numerical types.

    To *ban* something because it is confusing to you?
    Thus adding inconsistencies to the language?

    What is it that confuses you? - I am assuming you know the operator
    precedence rules, and that x += y like x = y returns a value?

    Does using parenthesis to sort things maybe help you?

    Janis


    It's actually highly confusing for me as well.
    For reasons I am not fully understand, it is interpreted as
    a += (b += c)
    which is obviously legal.
    I don't understand why it isn't interpreted as
    (a += b) += c
    which is [a little less obviously] illegal.

    In C, all the assignment operators are defined to associate
    right to left. That's why
    a += b += c;
    evaluates as if it were expressed as
    a += (b += c);


    Seems like += associates from right to left, same like =.
    IMHO, it would have been more natural if it was associating from left
    to right, like + most other operators.

    But, += is an assignment operator, not an operator in the (+ -) group.
    And, you want /assignments/ to associate right to left, otherwise
    a = b;
    would assign the value of a to the lval b





    --
    Lew Pitcher
    "In Skills We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Scott Lurndal on Tue Feb 13 19:41:14 2024
    On Tue, 13 Feb 2024 17:06:00 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Michael S <already5chosen@yahoo.com> writes:
    On Fri, 09 Feb 2024 09:09:41 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:


    If C had used ":=" for assignment and "=" for comparison (and "=="
    probably not used for anything), the problem would never have come
    up, because ":=" doesn't look like a comparison even to a newbie.
    But it's far too late to fix that in any language called "C".


    If DMR ever considered := for assignment then it probably lasted no
    longer than it took him to pay attention that in order to type ':' on
    the standard keyboard one has to press shift.

    The keyboard DMR used when developing C did not require shift
    to type a colon.

    https://en.wikipedia.org/wiki/Teletype_Model_33#/media/File:Mappa_Teletype_ASR-33.jpg

    WOW, that's extremely surprising for me.
    Not a ':' but that they developed C and Unix with keyboard that can't
    even type lower case characters.
    Actually, it's so surprising that worth clarification from somebody
    that was around there. Do you have relevant contacts?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Lew Pitcher on Tue Feb 13 19:49:28 2024
    On Tue, 13 Feb 2024 17:33:00 -0000 (UTC)
    Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:

    On Tue, 13 Feb 2024 19:22:57 +0200, Michael S wrote:

    On Tue, 13 Feb 2024 17:29:43 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 09/02/2024 16:43, bart wrote:
    What I wouldn't care about banning however is this:

    a += b += c;

    Because it's just confusing. If you don't think so, consider a,
    b, c all having different numerical types.

    To *ban* something because it is confusing to you?
    Thus adding inconsistencies to the language?

    What is it that confuses you? - I am assuming you know the operator
    precedence rules, and that x += y like x = y returns a value?

    Does using parenthesis to sort things maybe help you?

    Janis


    It's actually highly confusing for me as well.
    For reasons I am not fully understand, it is interpreted as
    a += (b += c)
    which is obviously legal.
    I don't understand why it isn't interpreted as
    (a += b) += c
    which is [a little less obviously] illegal.

    In C, all the assignment operators are defined to associate
    right to left. That's why
    a += b += c;
    evaluates as if it were expressed as
    a += (b += c);


    Seems like += associates from right to left, same like =.
    IMHO, it would have been more natural if it was associating from
    left to right, like + most other operators.

    But, += is an assignment operator, not an operator in the (+ -) group.
    And, you want /assignments/ to associate right to left, otherwise
    a = b;
    would assign the value of a to the lval b





    Yes, I want simple assignment operator to associate right to left.
    But I'd rather prefer for it to be an only exception to left to right
    rule. I.e. IMHO C would not be less consistent (and more safe) language
    if combined assignments we defined as associating from left to right.

    Of course, I don't suggest a change. It's 50 years too late.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Michael S on Tue Feb 13 18:01:31 2024
    On Tue, 13 Feb 2024 19:49:28 +0200, Michael S wrote:

    On Tue, 13 Feb 2024 17:33:00 -0000 (UTC)
    Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:

    On Tue, 13 Feb 2024 19:22:57 +0200, Michael S wrote:
    [snip]
    Seems like += associates from right to left, same like =.
    IMHO, it would have been more natural if it was associating from
    left to right, like + most other operators.

    But, += is an assignment operator, not an operator in the (+ -) group.
    And, you want /assignments/ to associate right to left, otherwise
    a = b;
    would assign the value of a to the lval b


    Yes, I want simple assignment operator to associate right to left.
    But I'd rather prefer for it to be an only exception to left to right
    rule.

    Then you would eliminate the unary operators (! ~ ++ -- and others) then?
    If not, how would you handle them, as they also associate right-to-left.

    --
    Lew Pitcher
    "In Skills We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Tue Feb 13 19:02:38 2024
    On 13/02/2024 18:22, Michael S wrote:
    On Tue, 13 Feb 2024 17:29:43 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 09/02/2024 16:43, bart wrote:
    What I wouldn't care about banning however is this:

    a += b += c;

    Because it's just confusing. If you don't think so, consider a, b,
    c all having different numerical types.

    To *ban* something because it is confusing to you?
    Thus adding inconsistencies to the language?

    What is it that confuses you? - I am assuming you know the operator
    precedence rules, and that x += y like x = y returns a value?

    Does using parenthesis to sort things maybe help you?

    Janis


    It's actually highly confusing for me as well.
    For reasons I am not fully understand, it is interpreted as
    a += (b += c)
    which is obviously legal.
    I don't understand why it isn't interpreted as
    (a += b) += c
    which is [a little less obviously] illegal.
    Seems like += associates from right to left, same like =.
    IMHO, it would have been more natural if it was associating from left
    to right, like + most other operators.


    Assignment operators are right-associative in C. This falls out of the
    grammar of C in the standards - though it would be nice if the standards
    had given a reader-friendly summary table. Still, it's not difficult to
    find one online.

    <https://en.cppreference.com/w/c/language/operator_precedence>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Tue Feb 13 18:58:45 2024
    On 13/02/2024 18:35, Malcolm McLean wrote:
    On 13/02/2024 16:30, David Brown wrote:
    On 13/02/2024 16:20, Malcolm McLean wrote:



    Now this means that the vast majority of code which is sanely written
    and uses "stdbool.h", but isn't written specifically for Pico C, will
    be interpreted correctly.

    That is not true.

    Code that relies on "bool" values being 0 or 1 is perfectly "sane",
    and will not work with the broken "bool" in Pico C.

    Pico C won't coerce a boolean to 1 or 0. Whilst it's easy t devise
    perfectly legal C code where this matters, it's less easy to think of an example which could also be defended as "sane".

    inline bool majority_of_three(bool a, bool b, bool c) {
    return (a + b + c) >= 2;
    }

    This can be used with arguments of any scaler type. That relies both on
    the constraints and semantics of converting to bool which "int" does not
    share, and on the bool values being 0 or 1.

    I can certainly tell you that I have written code that relies on bool's
    being 0 or 1, and that I only write "sane" code. I can't be bothered
    searching projects for real examples.

    I am not claiming it is common, but it certainly exists.


    Code that uses "bool b = p;", where "p" is a pointer, is perfectly
    sane and may not work if Pico C correctly complains about the
    constraint error from "int b = p;".

    Though that is an exception. A null pointer is conventionally "not
    there", and so it's reasonable for null / not null to be boolean.
    However bool b = p; still isn't very good. It should be bool b = p ?
    true : false; to make it explicit.>

    Why? It is common to write "if (p) ...", or "while (p) ...". If I
    thought it would be clearer, I would consider "bool b = (bool) p;".

    It is true that a lot of code that uses "bool", "true" and "false"
    will work in the face of "typedef int bool".  It is also true that
    some will not - and there was nothing wrong or insane about the code.
    Such code may fail subtly with Pico C, and only in some
    circumstances.  People using it will have to check their code, and
    change anything of the form "bool b = x;" into "bool b = !!x;" to be
    sure.
    And if we rip out stdbool.h support, none of the code wll work. However
    it won;t fail subty an donly in some circumstances.

    Hard failures are better than subtle and invisible failures.

    Pico C is does not, AFAIK, support C99 in general - there is no reason
    to suppose it will work with code that uses <stdbool.h>.



    But an tiny amount may break. And if it is running on a UAV which is
    armed with a nuclear missile, that may be a bit alarming. But mostly
    it won't be, and it will be fine.


    I am not at ease with an attitude of "There's a completely
    unnecessary, known and easily fixable mistake in this software, but
    hopefully you won't be using the tool for anything too serious and
    won't have many problems".  That is simply not how a programmer should
    think.

    Well you don't seem to understand the realities of it. I'm sure I've the skills to patch Pico C to have a real boolean type which only has one
    bit. But I can't do that quickly or easily. And Pico C is not under
    active development, and they say it is frozen and they want to keep it
    small. It's likely that no-one will accept the pull request. So now our
    Pico C has diverged from the trunk, and that causes issues. And a lot of programs are not too serious, or the costs of bugs are not too high.

    I am not blaming /you/ for mistakes in Pico C. I am blaming the author
    of Pico C for them, and for not documenting the limitations and non-conformities.

    I am blaming /you/ for your statements defending blatantly incorrect
    code and saying "it will be fine".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Malcolm McLean on Tue Feb 13 18:27:35 2024
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    On 13/02/2024 16:30, David Brown wrote:
    The Baby
    X resource compiler needs a way of converting a pixel value to an
    arbitrary output format, and my current answer to that is "you are a C >programmer,

    Mine answer would be to use netpbm rather than reinventing the wheel
    for the Nth time.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Lew Pitcher on Tue Feb 13 20:19:26 2024
    On Tue, 13 Feb 2024 18:01:31 -0000 (UTC)
    Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:

    On Tue, 13 Feb 2024 19:49:28 +0200, Michael S wrote:

    On Tue, 13 Feb 2024 17:33:00 -0000 (UTC)
    Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:

    On Tue, 13 Feb 2024 19:22:57 +0200, Michael S wrote:
    [snip]
    Seems like += associates from right to left, same like =.
    IMHO, it would have been more natural if it was associating from
    left to right, like + most other operators.

    But, += is an assignment operator, not an operator in the (+ -)
    group. And, you want /assignments/ to associate right to left,
    otherwise a = b;
    would assign the value of a to the lval b


    Yes, I want simple assignment operator to associate right to left.
    But I'd rather prefer for it to be an only exception to left to
    right rule.

    Then you would eliminate the unary operators (! ~ ++ -- and others)
    then? If not, how would you handle them, as they also associate right-to-left.


    Of course I am talking about binary.
    Unary rules are intuitive except for arbitrary, but still not
    necessarily non-intuitive precedence of post-fix over pre-fix.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Michael S on Tue Feb 13 18:31:01 2024
    Michael S <already5chosen@yahoo.com> writes:
    On Tue, 13 Feb 2024 17:06:00 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Michael S <already5chosen@yahoo.com> writes:
    On Fri, 09 Feb 2024 09:09:41 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:


    If C had used ":=" for assignment and "=" for comparison (and "=="
    probably not used for anything), the problem would never have come
    up, because ":=" doesn't look like a comparison even to a newbie.
    But it's far too late to fix that in any language called "C".


    If DMR ever considered := for assignment then it probably lasted no
    longer than it took him to pay attention that in order to type ':' on
    the standard keyboard one has to press shift.

    The keyboard DMR used when developing C did not require shift
    to type a colon.

    https://en.wikipedia.org/wiki/Teletype_Model_33#/media/File:Mappa_Teletype_ASR-33.jpg

    WOW, that's extremely surprising for me.
    Not a ':' but that they developed C and Unix with keyboard that can't
    even type lower case characters.

    Even today, the login command still detects logging in
    using all uppercase and switches the terminal to -olcuc
    automatically (see stty/termios).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Michael S on Tue Feb 13 18:34:28 2024
    Michael S <already5chosen@yahoo.com> writes:
    On Tue, 13 Feb 2024 17:06:00 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    https://en.wikipedia.org/wiki/Teletype_Model_33#/media/File:Mappa_Teletype_ASR-33.jpg

    WOW, that's extremely surprising for me.
    Not a ':' but that they developed C and Unix with keyboard that can't
    even type lower case characters.
    Actually, it's so surprising that worth clarification from somebody
    that was around there. Do you have relevant contacts?

    I programmed unix (wrote a terminal driver) on a PDP-11/34
    using a teletype in 1979. It was all uppercase. No vi(1), only ed(1). So was the PDP-8 (running TSS/8.24) in 1976 (initially via teletype, later
    via a Decwriter LA-120, which did support lowercase).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Michael S on Tue Feb 13 18:40:20 2024
    On Tue, 13 Feb 2024 19:41:14 +0200, Michael S wrote:

    On Tue, 13 Feb 2024 17:06:00 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:
    [snip]
    The keyboard DMR used when developing C did not require shift
    to type a colon.

    https://en.wikipedia.org/wiki/Teletype_Model_33#/media/File:Mappa_Teletype_ASR-33.jpg

    WOW, that's extremely surprising for me.
    Not a ':' but that they developed C and Unix with keyboard that can't
    even type lower case characters.

    Oh, the ASR33 could indeed type lower case characters; it just couldn't print them.

    (Speaking from first hand knowledge; when I got my Cromemco Z2 CP/M-based computer,
    back in the day, I purchased a used ASR33 (with tractor feed, no less) to use as a
    terminal and print device. I used that beast for many years before I finally passed
    it on to another lucky fellow.)


    Actually, it's so surprising that worth clarification from somebody
    that was around there. Do you have relevant contacts?




    --
    Lew Pitcher
    "In Skills We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Malcolm McLean on Tue Feb 13 21:08:55 2024
    On 13/02/2024 19:54, Malcolm McLean wrote:
    On 13/02/2024 18:27, Scott Lurndal wrote:
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    On 13/02/2024 16:30, David Brown wrote:
    The Baby
    X resource compiler needs a way of converting a pixel value to an
    arbitrary output format, and my current answer to that is "you are a C
    programmer,

    Mine answer would be to use netpbm rather than reinventing the wheel
    for the Nth time.

    I checked that out.
    This is the relevant program.

    https://netpbm.sourceforge.net/doc/ppmtoarbtxt.html

    No, that's not Linux-centric at all!

    I looked at the sources, and it's the usual story. At least, the
    configure file here only runs a Perl script, which is a bit different.

    I tried just compiling one sample program, but it's missing pm_config, presumably creating during some elaborate configuration process.

    You'd have thought that image-processing, translating one file to
    another, is among the most portable of tasks. More so even than language
    tools as there is no target platform involved.

    So why can't it 'just work'? Provide some default pm_config.h if necessary.

    This is why reinventing the wheel can be fruitful. Here, just
    incorporating someone else's wheels is hard.

    (There are binaries of these for Windows that I saw, dated 2005, but
    there are 300 small programs; an unwieldy set of dependencies.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Tue Feb 13 22:10:41 2024
    On Tue, 13 Feb 2024 17:00:00 +0100, Janis Papanagnou wrote:

    I have the habit to write such specific expressions with parenthesis

    a = (b == c);

    for own convenience or better maintainability. (Just BTW.)

    Parenthesis clutter seems to be a common affliction among C programmers.
    Why not just keep the docs handy, so you can check the precedences if in
    doubt?

    dstval =
    ((uint32_t *)dstrow)[col]
    &
    ~((1 << dst.bitwidth) - 1 << dst.shiftoffset)
    |
    srcval << dst.shiftoffset;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to bart on Tue Feb 13 21:15:58 2024
    bart <bc@freeuk.com> writes:
    On 13/02/2024 19:54, Malcolm McLean wrote:
    On 13/02/2024 18:27, Scott Lurndal wrote:
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    On 13/02/2024 16:30, David Brown wrote:
    The Baby
    X resource compiler needs a way of converting a pixel value to an
    arbitrary output format, and my current answer to that is "you are a C >>>> programmer,

    Mine answer would be to use netpbm rather than reinventing the wheel
    for the Nth time.

    I checked that out.
    This is the relevant program.

    https://netpbm.sourceforge.net/doc/ppmtoarbtxt.html

    No, that's not Linux-centric at all!

    It predates linux and ran on dozens of unix variants.

    <deleted another bart rant>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Lawrence D'Oliveiro on Tue Feb 13 22:20:28 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Tue, 13 Feb 2024 17:00:00 +0100, Janis Papanagnou wrote:

    I have the habit to write such specific expressions with parenthesis

    a = (b == c);

    for own convenience or better maintainability. (Just BTW.)

    Parenthesis clutter seems to be a common affliction among C programmers.
    Why not just keep the docs handy, so you can check the precedences if in >doubt?

    dstval =
    ((uint32_t *)dstrow)[col]
    &
    ~((1 << dst.bitwidth) - 1 << dst.shiftoffset)
    |
    srcval << dst.shiftoffset;

    Why do you care?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Scott Lurndal on Tue Feb 13 22:50:40 2024
    On 13/02/2024 21:15, Scott Lurndal wrote:
    bart <bc@freeuk.com> writes:
    On 13/02/2024 19:54, Malcolm McLean wrote:
    On 13/02/2024 18:27, Scott Lurndal wrote:
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    On 13/02/2024 16:30, David Brown wrote:
    The Baby
    X resource compiler needs a way of converting a pixel value to an
    arbitrary output format, and my current answer to that is "you are a C >>>>> programmer,

    Mine answer would be to use netpbm rather than reinventing the wheel
    for the Nth time.

    I checked that out.
    This is the relevant program.

    https://netpbm.sourceforge.net/doc/ppmtoarbtxt.html

    No, that's not Linux-centric at all!

    It predates linux and ran on dozens of unix variants.

    <deleted another bart rant>

    Some observations suggesting why there might be good reasons for
    reinventing wheels.

    You don't see it because you permanently live in a Unix-shaped box and everything you deal with is designed for that box.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Michael S on Wed Feb 14 00:36:21 2024
    On 13.02.2024 17:11, Michael S wrote:
    On Tue, 13 Feb 2024 16:55:32 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    You are mistaken; C++ had no 'bool' type initially. It had been added
    later.

    Pre-history vs history.
    As far as I am concerned, 'initially' == it presents in in the first
    edition of "The C++ Programming Language".

    I've learned C++ from that (1st ed.) book and don't recall that it had described the bool type. (But I don't have it anymore so cannot confirm
    or falsify your statement. Newer editions of that book certainly do
    mention bool.)
    But I still have "The Design and Evolution of C++" which explains that
    later "the ANSI/ISO accepted this argument so 'bool' is now a dedicated integral type in C++ with literals 'true' and 'false'.".
    The commercial C++ compilers we had used in the 1990's of course also
    didn't support that type; we provided (as so many did these days) our
    own Cpp 'bool' macros.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Wed Feb 14 00:18:50 2024
    On 13.02.2024 23:10, Lawrence D'Oliveiro wrote:
    On Tue, 13 Feb 2024 17:00:00 +0100, Janis Papanagnou wrote:

    I have the habit to write such specific expressions with parenthesis

    a = (b == c);

    for own convenience or better maintainability. (Just BTW.)

    Parenthesis clutter seems to be a common affliction among C programmers.

    It's not an affliction, it's mindfulness for specific constructs that
    own experience had shown to may become an issue (e.g. if someone else
    maintains such code). It provides in the given example certainty about
    the intention and that operator usage not having been a typo.

    It's not (not necessarily) about knowledge of precedence. But illogical precedence rules may of course be another reason to add parenthesis.
    Though most precedence rules in C make parenthesis usually unnecessary
    and expressions rarely need parenthesis to provide that certainty. The operators ==, =, &, |, etc. get thus some special attention from me.

    Calling that "affliction" and "clutter" is far off.

    And here again, the parentheses are also already part of the design of
    the C language, given that you *have* to use them even in if(), for(),
    while(), etc. constructs.

    With type safe booleans and with semantical chosen identifiers above
    boolean assignment should not be a problem. So your formulation that
    it's related to "C programmers", which rather should mean to the "C
    language", is insofar correct.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Wed Feb 14 00:44:44 2024
    On 13.02.2024 17:13, David Brown wrote:
    On 13/02/2024 16:55, Janis Papanagnou wrote:
    On 11.02.2024 18:05, David Brown wrote:

    Yes, we all know that. (Well, everyone who has learned a bit of C99
    knows that.) It's very difficult to change things in a language that
    has as much use as C - changing the type of the value of expressions
    like "x == y" would have been a breaking change. When C++ was forked
    from C, it was able to make such breaking changes - thus "x == y" gives
    a bool in C++. But for C, it was too late.

    You are mistaken; C++ had no 'bool' type initially. It had been added
    later.

    It was there from the first standard version of C++.

    And when was the first standard; 1998 - was it ISO/IEC 14882:1998 ?
    Rather late. (I've had my professional C++ the decade before that.)

    [...] But you are correct that it did
    not exist in early drafts of C++ prior to standardisation.

    More importantly it wasn't available in commercial C++ implementations.
    Bool and other useful features came rather late, unfortunately.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Janis Papanagnou on Wed Feb 14 01:11:42 2024
    On 14.02.2024 00:55, Janis Papanagnou wrote:
    On 14.02.2024 00:36, Janis Papanagnou wrote:
    On 13.02.2024 17:11, Michael S wrote:

    As far as I am concerned, 'initially' == it presents in in the first
    edition of "The C++ Programming Language".

    [...] don't recall that it had described the bool type. [...]

    Can anyone confirm or falsify whether the 'bool' type was already
    part of the 1st (1985) and/or the 2nd (1991) edition? - Thanks.

    Through Google Books I could search for 'bool' in the 1st ed. and
    could find just one match: "enum bool { lalse, true };"
    This is an indication that there was no 'bool' type part of the
    language or described in the first editions of his books. (CMIIW)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Janis Papanagnou on Wed Feb 14 00:55:34 2024
    On 14.02.2024 00:36, Janis Papanagnou wrote:
    On 13.02.2024 17:11, Michael S wrote:

    As far as I am concerned, 'initially' == it presents in in the first
    edition of "The C++ Programming Language".

    [...] don't recall that it had described the bool type. [...]

    Can anyone confirm or falsify whether the 'bool' type was already
    part of the 1st (1985) and/or the 2nd (1991) edition? - Thanks.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Wed Feb 14 01:21:36 2024
    On 13.02.2024 17:34, David Brown wrote:
    On 13/02/2024 17:14, Janis Papanagnou wrote:
    On 11.02.2024 13:57, David Brown wrote:

    [...] They had been trying to rule out "if (x = y)"
    and requiring it to be written "x = y; if (x != 0) ...".

    One could of course also have written it as

    if (x = y) // this is intentionally an assignment!

    Sometimes a comment is better than asking to rewrite the code.


    That is sometimes the case, but not here.

    It is better to write the code clearly than to have a comment explaining
    why you have written code that looks odd.

    Is it odd? - After all it's a common code pattern.

    But, yes. If in doubt you should choose some means to make
    it clear. And if it's the separation for you, that's fine.

    Myself I observed me using all three variants (separating,
    idiomatic, and commenting), depending on the context.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Janis Papanagnou on Wed Feb 14 02:19:09 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 14.02.2024 00:36, Janis Papanagnou wrote:
    On 13.02.2024 17:11, Michael S wrote:

    As far as I am concerned, 'initially' == it presents in in the first
    edition of "The C++ Programming Language".

    [...] don't recall that it had described the bool type. [...]

    Can anyone confirm or falsify whether the 'bool' type was already
    part of the 1st (1985) and/or the 2nd (1991) edition? - Thanks.

    I have the 2nd edition and there is no mention of a built-in bool type. Relational expressions (those involving <, > etc.) have type int and
    yield either 0 or 1.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Janis Papanagnou on Wed Feb 14 03:02:53 2024
    On 2024-02-13, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 14.02.2024 00:36, Janis Papanagnou wrote:
    On 13.02.2024 17:11, Michael S wrote:

    As far as I am concerned, 'initially' == it presents in in the first
    edition of "The C++ Programming Language".

    [...] don't recall that it had described the bool type. [...]

    Can anyone confirm or falsify whether the 'bool' type was already
    part of the 1st (1985) and/or the 2nd (1991) edition? - Thanks.

    Some data points.

    I'm looking at 1989 sources for Cfront. There is no bool, except
    in the implemnentation of an early version of templates, which
    defines a bool for itself as: enum bool { true, false }.

    Cfront 3.0.3 from around 1996 has a header like this:

    source/incl-master/const-headers/std_bool.h

    in which this is found:

    typedef int bool;
    const bool false = 0;
    const bool true = 1;

    So no built-in bool type distinct from int in the last Cfront for which
    you can find source code.

    Your memory is basically right about bool not having existed in
    a substantial way back in the day.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Wed Feb 14 09:46:38 2024
    On 14/02/2024 00:44, Janis Papanagnou wrote:
    On 13.02.2024 17:13, David Brown wrote:
    On 13/02/2024 16:55, Janis Papanagnou wrote:
    On 11.02.2024 18:05, David Brown wrote:

    Yes, we all know that. (Well, everyone who has learned a bit of C99
    knows that.) It's very difficult to change things in a language that
    has as much use as C - changing the type of the value of expressions
    like "x == y" would have been a breaking change. When C++ was forked
    from C, it was able to make such breaking changes - thus "x == y" gives >>>> a bool in C++. But for C, it was too late.

    You are mistaken; C++ had no 'bool' type initially. It had been added
    later.

    It was there from the first standard version of C++.

    And when was the first standard; 1998 - was it ISO/IEC 14882:1998 ?

    Yes.

    Rather late. (I've had my professional C++ the decade before that.)

    I hadn't done much with C++ before then. At that time, most of my
    professional programming was in assembly (on small microcontrollers) and Pascal, with only some C.


    [...] But you are correct that it did
    not exist in early drafts of C++ prior to standardisation.

    More importantly it wasn't available in commercial C++ implementations.
    Bool and other useful features came rather late, unfortunately.


    That's always the trouble with languages like C and C++. And backwards compatibility means that new, better features can't replace the old
    features - you have to keep the old stuff too. (C++ is "braver" than C
    at making breaking changes.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Wed Feb 14 09:35:04 2024
    On 13/02/2024 23:56, Malcolm McLean wrote:
    On 13/02/2024 20:58, Keith Thompson wrote:
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    [...]
    Now this means that the vast majority of code which is sanely written
    and uses "stdbool.h", but isn't written specifically for Pico C, will
    be interpreted correctly. But an tiny amount may break. And if it is
    running on a UAV which is armed with a nuclear missile, that may be a
    bit alarming. But mostly it won't be, and it will be fine.

    You're suggesting that correctness doesn't matter unless the software
    controls nuclear missiles.

    No.  Even if that was hyperbole -- no.

    But if software is running on a UAV which carries nuclear missiles and something goes wrong, millions of people might be killed. Whilst if the software that I write for a living goes wrong the worst thing that can
    happen on any plausible scenario is that an artist's drawing gets ruined
    and my company's liability for that is limited to a hundred and twenty dollars. You do see the difference.


    You seem to be conflating the /risk/ of errors with the /consequences/
    of errors. It is quite clear that if the consequences of an error are
    people getting killed, you need to handle things differently than if the consequences are image glitches in a frame of a computer game.

    Risk analysis involves considering the risks and consequences, and
    comparing it to the cost of finding and fixing errors. And the
    conclusion might be that you know your software has bugs, but it is not
    worth the cost trying to fix them - it is more economically viable to
    work around them or avoid them.

    Here we are talking about /known/ issues. The author of Pico C knows
    the <stdbool.h> implementation is wrong. (He also knows that his
    handling of integer promotions is wrong - and that's a error with far
    bigger effects.)

    A responsible software publisher will include a list of known issues
    here. The "readme.md" should have this information right at the top.
    Then potential users can do a risk assessment - they can estimate how
    likely it is that their code will hit these bugs, and what the
    consequences of that would be, and whether they can work around the
    issues or accept that the software is useful despite the risks.

    Hiding or denying the bugs, or glossing over them with "it will be
    fine", is irresponsible. So is an attitude of "you get what you pay
    for" - it's only $120 (or free), so you can expect things to break. It
    is fine to say that your time or budget does not extend to a development process that can eliminate all bugs - very little software can be
    written in a way that provably has no errors, and generally you can only
    do the best that resources allow to reduce the risk and consequences of
    errors.

    But when you /know/ you have a bug, it's a different matter. The simple
    act of documenting it clearer reduces the users' risk and consequences
    by orders of magnitude.


    For software, the biggest unknown factor is use and re-use. Bad bools
    are very unlikely to have major consequences if Bart uses Pico-C to
    script compilation of his code. But if the project gets forked and
    re-used, and embedded in other software, and eventually it ends up as
    part of a sandbox system for emulating or interpreting security
    software, it could be a completely different matter. The Pico C
    author's careless attitude, combined with the "it will be fine"
    thoughtlessness of people like you along the way, can result in big
    problems even though at each step it all looks like a very minor issue.

    Responsible programmers aim for correctness, for everything they code,
    all the time. They don't aim to find their bugs in testing, they aim to
    write code that they /know/ is correct, by design, and by knowledge of
    the surrounding code, the language, the tools. Sometimes they make
    mistakes. Sometimes there is an error outside their control, such as in
    the specifications. Sometimes outside pressure - management, sales,
    etc., - force them to leave code that they know is buggy or has high
    risks of errors. But they are not happy about it, and they don't ignore
    clear errors with "it will be fine".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Keith Thompson on Wed Feb 14 12:02:32 2024
    On Tue, 13 Feb 2024 16:59:38 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 13.02.2024 17:34, David Brown wrote:
    On 13/02/2024 17:14, Janis Papanagnou wrote:
    On 11.02.2024 13:57, David Brown wrote:

    [...] They had been trying to rule out "if (x = y)"
    and requiring it to be written "x = y; if (x != 0) ...".

    One could of course also have written it as

    if (x = y) // this is intentionally an assignment!

    Sometimes a comment is better than asking to rewrite the code.


    That is sometimes the case, but not here.

    It is better to write the code clearly than to have a comment
    explaining why you have written code that looks odd.

    Is it odd? - After all it's a common code pattern.

    But, yes. If in doubt you should choose some means to make
    it clear. And if it's the separation for you, that's fine.

    Myself I observed me using all three variants (separating,
    idiomatic, and commenting), depending on the context.

    Another option is:

    if ((x = y))

    It's not *inherently* obvious that this is a good idea, but it's the
    idiom suggested by gcc: "warning: suggest parentheses around
    assignment used as truth value [-Wparentheses]".

    Though personally, I'd probably make the assignment the operand of a
    larger expression. I understand that
    if (foo)
    is a common idiom where foo is of any scalar type, but I personally
    prefer to write one of
    if (foo != 0)
    if (foo != '\0')
    if (foo != 0.0)
    if (foo != NULL)
    because I find it clearer (unless foo is of type bool or is otherwise appropriate to use directly as a condition).

    Thus if x and y are ints, I'd probably write:
    if ((x = y) != 0)
    (Assuming I'm not required to follow MISRA rules.)

    YMMV.


    Agreed with two small exception:
    (1) I never write '\0' myself always preferring plain 0.
    (2) I do sometimes write 0.0, but in this particular context I'd
    prefer plain 0.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Wed Feb 14 11:11:13 2024
    On 14/02/2024 10:34, Malcolm McLean wrote:
    Now I know that you think Bart should just use make. But let's say it's agreed to proceed with the system I proposed, which is a C interpeter to drive a build script. Now I suggested modifying one of Bart's own
    compilers. But that's more difficult than I thought. So my second option
    is Pico C. Now I think that is achievable. If there's sufficient
    consensus that the system is worth producing, we can hook up Pico C and thrash out a support library, with the resources we have in this
    newsgroup, from people who are likely to want to contribute.

    Now if you think we shouldn't do that because of the danger of the
    scripting system being used in a critical environment and an error in
    the boolean or other component of Pico C propagating, then how do you
    think that we should proceed?



    You do what you want here. I think your dream of getting regulars in
    this newsgroup to work together to make a C based scripting system for
    building Bart's programs is, shall we say, somewhat unrealistic. Those
    that have made any comments on the subject, other than Bart, have been
    happy with the way they build their software, and I don't think anyone
    other than you thinks C would be a good choice of scripting language.
    (Bart has his own scripting language which seems a far better choice for
    his own needs for any build system.)

    I don't think it is good that Pico C is spread around, as long as it has
    its current flaws in C conformity, unless these flaws and limitations
    are clearly documented. If you want to call it an interpreter for a
    C-like language, great. If you want to call it an interpreter for C
    with certain limitations and differences from standard C, great. I
    object to calling it a C interpreter, and promoting its use as such.

    I would prefer most of all to see its flaws and non-conformities fixed.
    It should not be particularly hard to do.

    But if you want to take Pico C and use it as it is, that's your choice.
    I doubt if its issues would be much of a problem for your use of it for
    build scripts.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Kaz Kylheku on Wed Feb 14 13:14:38 2024
    On 14.02.2024 04:02, Kaz Kylheku wrote:
    On 2024-02-13, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    Can anyone confirm or falsify whether the 'bool' type was already
    part of the 1st (1985) and/or the 2nd (1991) edition? - Thanks.

    Some data points.

    I'm looking at 1989 sources for Cfront. There is no bool, except
    in the implemnentation of an early version of templates, which
    defines a bool for itself as: enum bool { true, false }.

    Cfront 3.0.3 from around 1996 has a header like this:

    source/incl-master/const-headers/std_bool.h

    in which this is found:

    typedef int bool;
    const bool false = 0;
    const bool true = 1;

    So no built-in bool type distinct from int in the last Cfront for which
    you can find source code.

    Your memory is basically right about bool not having existed in
    a substantial way back in the day.

    Thanks for all confirmations! - I'm glad that my memory still
    works at age. :-)

    I recall we've pondered about the best way to emulate booleans;
    typedef, enum, or #define. All options had disadvantages, and
    none could substitute a real built-in first class bool type.

    Yet another well known deficiency from the C/C++ languages.
    A missing basic type is hard to fix later (without conflicts
    with own 'bool' substitutes) if not considered initially as a
    basic part of any language.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Wed Feb 14 13:32:52 2024
    On 14/02/2024 11:43, Malcolm McLean wrote:
    On 14/02/2024 10:11, David Brown wrote:
    On 14/02/2024 10:34, Malcolm McLean wrote:

    The whole point of using C s to get away from the ad hoc scripting
    language that you don't use frequently enough to remember exactly how it works, and to use something familiar. So we do want a C interpreter, not
    a "C-like interpreter" to add yet another language with its own quirks
    to the mess which Bart has so correctly identiifed.


    Please stop using the "royal we" to mean you, personally. If there were
    many people wanting C interpreters for writing scripts, there would be
    lots of C interpreters and lots of scripts written in C. The reality is
    that there is one dead project, and there's tcc's script mode - but I
    have never heard of it being used in practice. Meanwhile, there are
    vast numbers of C programmers, and vast amounts of scripts written in
    Bash, Perl, Python, TCL, and other languages suitable for scripting.
    That should be a good indication that few people feel the need for
    writing scripts in C, even if they are familiar with C.

    Scripts are, usually, fairly short and simple. It's not hard to look up examples in different languages, and get things working for your needs.
    Either this is something you do a lot, in which case you get familiar
    with enough of the language to write your scripts, or it is something
    you do rarely, in which case it is not a problem if it takes you a
    little longer to figure it out.

    So as I see it, the case for C programmers writing scripts in C is very,
    very weak.

    But by all means, work on this for a hobby project. Hobby projects
    don't need to be useful to be fun - even assuming that my opinions here
    are correct.

    I would prefer most of all to see its flaws and non-conformities
    fixed. It should not be particularly hard to do.

    And that is at least a direction. And maybe even a proposal for a hobby project.

    Good. Resurrecting Pico C and fixing it would have a lot more potential
    uses than a C-based build system.


    But if you want to take Pico C and use it as it is, that's your
    choice. I doubt if its issues would be much of a problem for your use
    of it for build scripts.

    Well you can't have it both ways. Either it is irresponsible to use Pico
    C in a build scripting system or it is not. Surely you are not
    suggesting that I would choose to act irresponsibly purely because I
    have a legal right to do so?


    It is irresponsible to promote the general use of software with known, potentially high-consequence flaws without at least making the issues
    clear and obvious to any users. It is not irresponsible to use software
    with known flaws in a way that does not trigger these flaws. Does that
    make it clearer to you?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Janis Papanagnou on Wed Feb 14 14:36:12 2024
    On Wed, 14 Feb 2024 13:26:18 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 14.02.2024 09:46, David Brown wrote:
    On 14/02/2024 00:44, Janis Papanagnou wrote:

    And when was the first standard; 1998 - was it ISO/IEC 14882:1998
    ?

    Yes.

    Rather late. (I've had my professional C++ the decade before
    that.)

    I hadn't done much with C++ before then. At that time, most of my professional programming was in assembly (on small
    microcontrollers) and Pascal, with only some C.

    I'm surprised that Pascal was in professional use back then.[*]
    Pascal had always been derided as "academic" or "toy" language.


    Standard Pascal is a toy, but multiple extended variant were useful and popular. And at least one extended variant was *hugely* popular. https://en.wikipedia.org/wiki/Turbo_Pascal

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Wed Feb 14 13:26:18 2024
    On 14.02.2024 09:46, David Brown wrote:
    On 14/02/2024 00:44, Janis Papanagnou wrote:

    And when was the first standard; 1998 - was it ISO/IEC 14882:1998 ?

    Yes.

    Rather late. (I've had my professional C++ the decade before that.)

    I hadn't done much with C++ before then. At that time, most of my professional programming was in assembly (on small microcontrollers) and Pascal, with only some C.

    I'm surprised that Pascal was in professional use back then.[*]
    Pascal had always been derided as "academic" or "toy" language.


    That's always the trouble with languages like C and C++. And backwards compatibility means that new, better features can't replace the old
    features - you have to keep the old stuff too. (C++ is "braver" than C
    at making breaking changes.)

    Yes, indeed.

    Janis

    [*] Although I've heard in those days that it had been used in
    the control unit of an atomic reprocessing plant at Wackersdorf/
    DE; but the plant never went in operation due to civil protests.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Wed Feb 14 15:29:00 2024
    On 14/02/2024 13:26, Janis Papanagnou wrote:
    On 14.02.2024 09:46, David Brown wrote:
    On 14/02/2024 00:44, Janis Papanagnou wrote:

    And when was the first standard; 1998 - was it ISO/IEC 14882:1998 ?

    Yes.

    Rather late. (I've had my professional C++ the decade before that.)

    I hadn't done much with C++ before then. At that time, most of my
    professional programming was in assembly (on small microcontrollers) and
    Pascal, with only some C.

    I'm surprised that Pascal was in professional use back then.[*]
    Pascal had always been derided as "academic" or "toy" language.


    In the DOS/Windows world, Pascal was a major language for a long time - starting with Turbo Pascal, then Borland Pascal for DOS then Windows,
    then Delphi. Delphi's descendants are still in heavy use for Windows development. (And dotnet came from Delphi and related projects.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Michael S on Wed Feb 14 15:54:09 2024
    Michael S <already5chosen@yahoo.com> writes:
    On Tue, 13 Feb 2024 16:59:38 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:



    Though personally, I'd probably make the assignment the operand of a
    larger expression. I understand that
    if (foo)
    is a common idiom where foo is of any scalar type, but I personally
    prefer to write one of
    if (foo != 0)
    if (foo != '\0')
    if (foo != 0.0)
    if (foo != NULL)
    because I find it clearer (unless foo is of type bool or is otherwise
    appropriate to use directly as a condition).

    Thus if x and y are ints, I'd probably write:
    if ((x = y) != 0)
    (Assuming I'm not required to follow MISRA rules.)

    YMMV.


    Agreed with two small exception:
    (1) I never write '\0' myself always preferring plain 0.

    I'm in Keith's camp here when working with a char type, I'll
    use '\0' rather than plain zero.

    I tend to suffix constants as well if they're not being
    used as 'int', perhaps a bit too picky?

    uint64_t v;
    ...
    if (v == 0ul) ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Keith Thompson on Wed Feb 14 15:50:21 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 13.02.2024 17:34, David Brown wrote:


    Though personally, I'd probably make the assignment the operand of a
    larger expression. I understand that
    if (foo)
    is a common idiom where foo is of any scalar type, but I personally
    prefer to write one of
    if (foo != 0)
    if (foo != '\0')
    if (foo != 0.0)
    if (foo != NULL)
    because I find it clearer (unless foo is of type bool or is otherwise >appropriate to use directly as a condition).


    Yes, that's my style as well. Make it obvious to the next person(s) who maintain or extend the code.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Malcolm McLean on Wed Feb 14 15:58:09 2024
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    On 14/02/2024 08:35, David Brown wrote:
    On 13/02/2024 23:56, Malcolm McLean wrote:
    On 13/02/2024 20:58, Keith Thompson wrote:

    Responsible programmers aim for correctness, for everything they code,
    all the time.  They don't aim to find their bugs in testing, they aim to
    write code that they /know/ is correct, by design, and by knowledge of
    the surrounding code, the language, the tools.  Sometimes they make
    mistakes.  Sometimes there is an error outside their control, such as in
    the specifications.  Sometimes outside pressure - management, sales,
    etc., - force them to leave code that they know is buggy or has high
    risks of errors.  But they are not happy about it, and they don't ignore
    clear errors with "it will be fine".


    Now I know that you think Bart should just use make.

    Nobody has said that. It's been offered as a viable alternative to
    his purported "simple" build process for projects that aren't as simple
    has his project apparently are.

    Bart is free to build his tools in any fashion he desires, just as
    everyone else is free to use make, cmake, etc.


    But let's say it's
    agreed to proceed with the system I proposed, which is a C interpeter to >drive a build script.

    I'd much rather have a shell scripting language drive a build script,
    iff make wasn't available.

    I see no benefit in a "C" interpreter - for which string handling
    is an afterthought - in any build process.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Wed Feb 14 20:51:59 2024
    On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:

    But C has a *lot* of precedence levels, and they're not all obvious.

    If I see `a | b ^ c`, I'm not likely to remember off the top of my head
    ...

    So don’t remember “off the top of your head”: keep the docs handy. That’s
    what I do.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Wed Feb 14 20:52:55 2024
    On Wed, 14 Feb 2024 00:18:50 +0100, Janis Papanagnou wrote:

    Though most precedence rules in C make parenthesis usually unnecessary
    and expressions rarely need parenthesis to provide that certainty.

    And yet you were the one who added unnecessary ones in your example, I didn’t.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Keith Thompson on Wed Feb 14 20:31:53 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:
    Michael S <already5chosen@yahoo.com> writes:
    On Tue, 13 Feb 2024 16:59:38 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Though personally, I'd probably make the assignment the operand of a
    larger expression. I understand that
    if (foo)
    is a common idiom where foo is of any scalar type, but I personally
    prefer to write one of
    if (foo != 0)
    if (foo != '\0')
    if (foo != 0.0)
    if (foo != NULL)
    because I find it clearer (unless foo is of type bool or is otherwise
    appropriate to use directly as a condition).

    Thus if x and y are ints, I'd probably write:
    if ((x = y) != 0)
    (Assuming I'm not required to follow MISRA rules.)

    YMMV.


    Agreed with two small exception:
    (1) I never write '\0' myself always preferring plain 0.

    I'm in Keith's camp here when working with a char type, I'll
    use '\0' rather than plain zero.

    I tend to suffix constants as well if they're not being
    used as 'int', perhaps a bit too picky?

    uint64_t v;
    ...
    if (v == 0ul) ...

    There's no suffix for uint64_t. 0ul is of type unsigned long, which may
    or may not be the same type as uint64_t.

    In this particular case, I'd just use 0. If for some reason I needed to
    make it explicitly of type uint64_t (say, for an argument to a variadic function), I'd write `(uint64_t)0`.

    stdint.h also provides an UINT64_C(...) macro that could be used,
    though, as you say, 0 is really all that's needed in this case.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Wed Feb 14 21:44:56 2024
    On Mon, 12 Feb 2024 12:23:35 +0100, David Brown wrote:

    Do you know what "incompatible types" are, and what they mean? Do you realise that they cannot be swapped around as you suggest?

    And yet, all the examples posted so far have involved, not the actual
    types, but pointers to them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Lawrence D'Oliveiro on Wed Feb 14 21:54:32 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:

    But C has a *lot* of precedence levels, and they're not all obvious.

    If I see `a | b ^ c`, I'm not likely to remember off the top of my head
    ...

    So don’t remember “off the top of your head”: keep the docs handy. That’s
    what I do.

    Why? The code is easier to read and maintain if the precedence is
    made explicit.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Ben Bacarisse on Wed Feb 14 21:53:37 2024
    Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:
    Michael S <already5chosen@yahoo.com> writes:
    On Tue, 13 Feb 2024 16:59:38 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Though personally, I'd probably make the assignment the operand of a >>>>> larger expression. I understand that
    if (foo)
    is a common idiom where foo is of any scalar type, but I personally
    prefer to write one of
    if (foo != 0)
    if (foo != '\0')
    if (foo != 0.0)
    if (foo != NULL)
    because I find it clearer (unless foo is of type bool or is otherwise >>>>> appropriate to use directly as a condition).

    Thus if x and y are ints, I'd probably write:
    if ((x = y) != 0)
    (Assuming I'm not required to follow MISRA rules.)

    YMMV.


    Agreed with two small exception:
    (1) I never write '\0' myself always preferring plain 0.

    I'm in Keith's camp here when working with a char type, I'll
    use '\0' rather than plain zero.

    I tend to suffix constants as well if they're not being
    used as 'int', perhaps a bit too picky?

    uint64_t v;
    ...
    if (v == 0ul) ...

    There's no suffix for uint64_t. 0ul is of type unsigned long, which may
    or may not be the same type as uint64_t.

    In this particular case, I'd just use 0. If for some reason I needed to
    make it explicitly of type uint64_t (say, for an argument to a variadic
    function), I'd write `(uint64_t)0`.

    stdint.h also provides an UINT64_C(...) macro that could be used,
    though, as you say, 0 is really all that's needed in this case.

    OTOH, all the systems the code in question run typedef uint64_t to unsigned long, so the 'ul' suffix works correctly in all forseeable usages in this application. And it's less to type than casting. Granted it's not particularly meaningful in the 0ul case, but it's a habit that does
    come in handy in expressions like

    uint64_t address;
    address = (0xcul << 44) | ((uint64_t)node << 44) | (device << 32) | register_offset;

    Yes, a cast on the constant would work as well. And yes, a good compiler
    will warn if the suffix is missing from the first constant value.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Michael S on Wed Feb 14 21:54:24 2024
    Michael S <already5chosen@yahoo.com> writes:

    [.. should 'a += b += c;' be disallowed for style reasons? ..]

    It's actually highly confusing for me as well.
    For reasons I am not fully understand, it is interpreted as
    a += (b += c)
    which is obviously legal.
    I don't understand why it isn't interpreted as
    (a += b) += c
    which is [a little less obviously] illegal.

    Here is another way to think about it.

    C (and many or most other languages) are fairly strict about what
    is allowed on the left-hand side of an assignment. For example,

    a + b += c;

    is not allowed. Neither is

    (a + b) += c;

    although the reasoning is a little different in the two cases,
    neither is allowed, because neither one makes sense.

    By analogy with the second example, the statement

    (a += b) += c;

    isn't allowed, because the left-hand side is wrong. So if we
    see

    a += b += c;

    it would be silly to parse it as

    (a += b) += c;

    because that's illegal. The only other way to parse it, viz.,

    a += (b += c);

    passes the semantic prerequisites. Since it's the only way that
    makes sense, it seems natural that (without any parentheses) the
    syntax should reflect that.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Ben Bacarisse on Wed Feb 14 22:04:15 2024
    Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    Michael S <already5chosen@yahoo.com> writes:

    On Tue, 13 Feb 2024 16:59:38 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    Though personally, I'd probably make the assignment the operand of a >>>>> larger expression. I understand that
    if (foo)
    is a common idiom where foo is of any scalar type, but I personally
    prefer to write one of
    if (foo != 0)
    if (foo != '\0')
    if (foo != 0.0)
    if (foo != NULL)
    because I find it clearer (unless foo is of type bool or is otherwise >>>>> appropriate to use directly as a condition).

    Thus if x and y are ints, I'd probably write:
    if ((x = y) != 0)
    (Assuming I'm not required to follow MISRA rules.)

    YMMV.

    Agreed with two small exception:
    (1) I never write '\0' myself always preferring plain 0.

    I'm in Keith's camp here when working with a char type, I'll
    use '\0' rather than plain zero.

    I tend to suffix constants as well if they're not being
    used as 'int', perhaps a bit too picky?

    uint64_t v;
    ...
    if (v == 0ul) ...

    There's no suffix for uint64_t. 0ul is of type unsigned long,
    which may or may not be the same type as uint64_t.

    In this particular case, I'd just use 0. If for some reason I
    needed to make it explicitly of type uint64_t (say, for an argument
    to a variadic function), I'd write `(uint64_t)0`.

    stdint.h also provides an UINT64_C(...) macro that could be used,
    though, as you say, 0 is really all that's needed in this case.

    Using UINT64_C(...) to make a constant of type uint64_t is a bit
    too sneaky for my taste. Despite what may appear to the be case,
    UINT64_C(...) produces a constant of type uint_least64_t, not
    uint64_t. Of course if the implementation does have a uint64_t
    type, then UINT64_C(...) will have the same width (but not
    necessarily the same type) as uint64_t, but the roundabout logic
    still bothers me.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Scott Lurndal on Wed Feb 14 22:07:03 2024
    scott@slp53.sl.home (Scott Lurndal) writes:

    Michael S <already5chosen@yahoo.com> writes:

    On Tue, 13 Feb 2024 16:59:38 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:



    Though personally, I'd probably make the assignment the operand of a
    larger expression. I understand that
    if (foo)
    is a common idiom where foo is of any scalar type, but I personally
    prefer to write one of
    if (foo != 0)
    if (foo != '\0')
    if (foo != 0.0)
    if (foo != NULL)
    because I find it clearer (unless foo is of type bool or is otherwise
    appropriate to use directly as a condition).

    Thus if x and y are ints, I'd probably write:
    if ((x = y) != 0)
    (Assuming I'm not required to follow MISRA rules.)

    YMMV.

    Agreed with two small exception:
    (1) I never write '\0' myself always preferring plain 0.

    I'm in Keith's camp here when working with a char type, I'll
    use '\0' rather than plain zero.

    I tend to suffix constants as well if they're not being
    used as 'int', perhaps a bit too picky?

    uint64_t v;
    ...
    if (v == 0ul) ...

    You say what you do but don't say why. Can you explain your
    rationale or motivation?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Wed Feb 14 22:11:36 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    Michael S <already5chosen@yahoo.com> writes:

    On Tue, 13 Feb 2024 16:59:38 -0800
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    Though personally, I'd probably make the assignment the operand
    of a larger expression. I understand that
    if (foo)
    is a common idiom where foo is of any scalar type, but I
    personally prefer to write one of
    if (foo != 0)
    if (foo != '\0')
    if (foo != 0.0)
    if (foo != NULL)
    because I find it clearer (unless foo is of type bool or is
    otherwise appropriate to use directly as a condition).

    Thus if x and y are ints, I'd probably write:
    if ((x = y) != 0)
    (Assuming I'm not required to follow MISRA rules.)

    YMMV.

    Agreed with two small exception:
    (1) I never write '\0' myself always preferring plain 0.

    I'm in Keith's camp here when working with a char type, I'll
    use '\0' rather than plain zero.

    I tend to suffix constants as well if they're not being
    used as 'int', perhaps a bit too picky?

    uint64_t v;
    ...
    if (v == 0ul) ...

    There's no suffix for uint64_t. 0ul is of type unsigned long,
    which may or may not be the same type as uint64_t.

    In this particular case, I'd just use 0. If for some reason I
    needed to make it explicitly of type uint64_t (say, for an
    argument to a variadic function), I'd write `(uint64_t)0`.

    Ick. At least write '(uint64_t){ 0 }' rather than casting.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Scott Lurndal on Wed Feb 14 22:37:55 2024
    scott@slp53.sl.home (Scott Lurndal) writes:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:

    But C has a *lot* of precedence levels, and they're not all
    obvious.

    If I see `a | b ^ c`, I'm not likely to remember off the top of my
    head ...

    So don't remember off the top of your head, [just] keep the docs
    handy. That's what I do.

    Why? The code is easier to read and maintain if the precedence is
    made explicit.

    Every serious C developer should know all the operator precedence
    relationships without having to look them up.

    In cases where it is still felt necessary to indicate how different
    operators parse with respect to one another, it's better to do that
    using spacing than with parentheses, as for example

    a | b^c

    or

    alpha | beta ^ gamma

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Thu Feb 15 08:00:00 2024
    On 14.02.2024 21:52, Lawrence D'Oliveiro wrote:
    On Wed, 14 Feb 2024 00:18:50 +0100, Janis Papanagnou wrote:

    Though most precedence rules in C make parenthesis usually unnecessary
    and expressions rarely need parenthesis to provide that certainty.

    And yet you were the one who added unnecessary ones in your example, I didn’t.

    Yes, and I explained that with the given rules you have no "clutter"
    (as you called it), so that you can use them even if [by precedence] unnecessary, to make (a few) specific contexts _clearer_ (i.e. the
    opposite of clutter).

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Thu Feb 15 08:23:09 2024
    On 14.02.2024 13:32, David Brown wrote:
    On 14/02/2024 11:43, Malcolm McLean wrote:

    The whole point of using C s to get away from the ad hoc scripting
    language that you don't use frequently enough to remember exactly how
    it works, and to use something familiar. So we do want a C
    interpreter, not a "C-like interpreter" to add yet another language
    with its own quirks to the mess which Bart has so correctly identiifed.

    Please stop using the "royal we" to mean you, personally. If there were
    many people wanting C interpreters for writing scripts, there would be
    lots of C interpreters and lots of scripts written in C. The reality is
    that there is one dead project, and there's tcc's script mode - but I
    have never heard of it being used in practice. Meanwhile, there are
    vast numbers of C programmers, and vast amounts of scripts written in
    Bash, Perl, Python, TCL, and other languages suitable for scripting.
    That should be a good indication that few people feel the need for
    writing scripts in C, even if they are familiar with C.

    It's worth to add Awk to your list of script languages, since it's
    standard on Unix, and its syntax largely resembles the syntax of C.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Thu Feb 15 08:38:36 2024
    On Tue, 13 Feb 2024 13:20:06 -0800, Keith Thompson wrote:

    Early Unix did have some methods for accomodating
    upper-case-only keyboards, some of which survive to the present.

    As I recall, if you typed your username all in uppercase when logging in,
    the login (getty?) program set a terminal mode that converted all
    uppercase to lowercase on input, and all lowercase to uppercase on output.

    Sort of a “passive-aggressive” case-conversion mode, if you like ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Scott Lurndal on Thu Feb 15 08:42:04 2024
    On Wed, 14 Feb 2024 21:53:37 GMT, Scott Lurndal wrote:

    address = (0xcul << 44) | ((uint64_t)node << 44) | (device << 32) | register_offset;

    I did say parenthesis clutter seemed to be a common affliction among C programmers, didn’t I?

    address = 0xcul << 44 | (uint64_t)node << 44 | device << 32 | register_offset;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Thu Feb 15 08:43:16 2024
    On Wed, 14 Feb 2024 14:38:01 -0800, Keith Thompson wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    And yet, all the examples posted so far have involved, not the actual
    types, but pointers to them.

    Because pointers to incompatible types are a good way to demonstrate incompatibility.

    But it was those types I was talking about, not pointers to them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Thu Feb 15 08:48:44 2024
    On Tue, 13 Feb 2024 16:55:32 +0100, Janis Papanagnou wrote:

    You are mistaken; C++ had no 'bool' type initially. It had been added
    later.

    The first version of the C++ standard was C++98, and that had bool in it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Thu Feb 15 08:47:14 2024
    On Wed, 14 Feb 2024 15:29:00 +0100, David Brown wrote:

    In the DOS/Windows world, Pascal was a major language for a long time - starting with Turbo Pascal, then Borland Pascal for DOS then Windows,
    then Delphi. Delphi's descendants are still in heavy use for Windows development. (And dotnet came from Delphi and related projects.)

    In the PC world generally, UCSD Pascal and its offshoots (of which Turbo
    Pascal was one) were very popular.

    The UCSD p-system pioneered the concept of “write once, run anywhere”, by defining a standardized p-code interpreter that could be implemented
    across a whole range of different processor architectures. Once you had
    done that, plus some basic OS routines, the main part of the software,
    written in Pascal, should port straight across.

    Yes, there was a performance hit. But many people considered it worth
    avoiding the pain of having to rewrite your code.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Thu Feb 15 08:51:15 2024
    On Thu, 15 Feb 2024 08:23:09 +0100, Janis Papanagnou wrote:

    It's worth to add Awk to your list of script languages, since it's
    standard on Unix, and its syntax largely resembles the syntax of C.

    Perl does everything Awk can do, and do it just as concisely, and it can
    do more besides.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Thu Feb 15 08:57:42 2024
    On Tue, 13 Feb 2024 12:58:49 -0800, Keith Thompson wrote:

    You're suggesting that correctness doesn't matter unless the software controls nuclear missiles.

    I would be hoping that safety-critical software would be written to higher standards than military stuff.

    After all, in military operations, a “friendly fire” rate of, say, 10-25%, seems to be considered acceptable.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Scott Lurndal on Thu Feb 15 08:59:14 2024
    On Wed, 14 Feb 2024 21:54:32 GMT, Scott Lurndal wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:

    But C has a *lot* of precedence levels, and they're not all obvious.

    If I see `a | b ^ c`, I'm not likely to remember off the top of my
    head ...

    So don’t remember “off the top of your head”: keep the docs handy. >>That’s what I do.

    Why? The code is easier to read and maintain if the precedence is made explicit.

    You’re assuming that the parenthesis clutter has negligible effect on readability. That may be OK with one or two extraneous pairs, but typical
    C code tends to end up with a lot more than that.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Thu Feb 15 09:00:16 2024
    On Thu, 15 Feb 2024 08:00:00 +0100, Janis Papanagnou wrote:

    On 14.02.2024 21:52, Lawrence D'Oliveiro wrote:

    On Wed, 14 Feb 2024 00:18:50 +0100, Janis Papanagnou wrote:

    Though most precedence rules in C make parenthesis usually unnecessary
    and expressions rarely need parenthesis to provide that certainty.

    And yet you were the one who added unnecessary ones in your example, I
    didn’t.

    Yes, and I explained that with the given rules you have no "clutter"
    (as you called it) ...

    “Clutter” is when you put in ones you don’t need.

    If Marie Kondo were to learn C programming, what do you think she would
    do?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Thu Feb 15 10:06:40 2024
    On 14/02/2024 22:44, Lawrence D'Oliveiro wrote:
    On Mon, 12 Feb 2024 12:23:35 +0100, David Brown wrote:

    Do you know what "incompatible types" are, and what they mean? Do you
    realise that they cannot be swapped around as you suggest?

    And yet, all the examples posted so far have involved, not the actual
    types, but pointers to them.

    Keith's post explains about pointers to incompatible types.

    Compatibility is also relevant for declarations. All declarations of
    the same function or object with external linkage must be the same
    within a program. It is undefined behaviour to have this :

    int foo(int);

    and this :

    int foo(long int);

    in the same program. That is true even if "int" and "long int" have the
    same size, or are passed using the same ABI conventions. Compilers will complain if they are within the same translation unit, but it is
    undefined (and usually not diagnosed) if they are in different
    translation units.

    There are /many/ situations where types must be compatible. I don't
    want to try to list all the rules here - you can look them up yourself.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Thu Feb 15 14:21:54 2024
    On 15/02/2024 09:59, Lawrence D'Oliveiro wrote:
    On Wed, 14 Feb 2024 21:54:32 GMT, Scott Lurndal wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:

    But C has a *lot* of precedence levels, and they're not all obvious.

    If I see `a | b ^ c`, I'm not likely to remember off the top of my
    head ...

    So don’t remember “off the top of your head”: keep the docs handy. >>> That’s what I do.

    Why? The code is easier to read and maintain if the precedence is made
    explicit.

    You’re assuming that the parenthesis clutter has negligible effect on readability. That may be OK with one or two extraneous pairs, but typical
    C code tends to end up with a lot more than that.

    He was assuming the programmer used parentheses without it being "clutter".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Thu Feb 15 14:23:57 2024
    On 15/02/2024 10:00, Lawrence D'Oliveiro wrote:
    On Thu, 15 Feb 2024 08:00:00 +0100, Janis Papanagnou wrote:

    On 14.02.2024 21:52, Lawrence D'Oliveiro wrote:

    On Wed, 14 Feb 2024 00:18:50 +0100, Janis Papanagnou wrote:

    Though most precedence rules in C make parenthesis usually unnecessary >>>> and expressions rarely need parenthesis to provide that certainty.

    And yet you were the one who added unnecessary ones in your example, I
    didn’t.

    Yes, and I explained that with the given rules you have no "clutter"
    (as you called it) ...

    “Clutter” is when you put in ones you don’t need.

    So now we are going to have to introduce terms like Lawrence-Clutter to
    go along with Malcolm-functions?


    If Marie Kondo were to learn C programming, what do you think she would
    do?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Tim Rentsch on Thu Feb 15 14:20:21 2024
    On 15/02/2024 07:37, Tim Rentsch wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:

    But C has a *lot* of precedence levels, and they're not all
    obvious.

    If I see `a | b ^ c`, I'm not likely to remember off the top of my
    head ...

    So don't remember off the top of your head, [just] keep the docs
    handy. That's what I do.

    Why? The code is easier to read and maintain if the precedence is
    made explicit.

    Every serious C developer should know all the operator precedence relationships without having to look them up.


    <https://en.wikipedia.org/wiki/No_true_Scotsman>

    /Serious/ developers write code that is as clear as they can. They know
    where references are for when they need them, but do not waste cognitive
    effort memorising things that are better expressed in a different way
    (such as by using parentheses or breaking expressions into parts).

    In cases where it is still felt necessary to indicate how different
    operators parse with respect to one another, it's better to do that
    using spacing than with parentheses, as for example

    a | b^c

    or

    alpha | beta ^ gamma


    No, that is the silliest thing to do. Don't write code that looks like
    what you think it should mean - even if it happens to match the somewhat arbitrary choices of a language. Write code that does exactly what you
    mean, clearly and unequivocally, and requires the minimum of cognitive
    effort on the part of the reader.

    People make mistakes, even if they are "serious C developers". And if
    you start using spaces to make it look like you are correct, neither you
    nor others looking at the code will notice mistakes like :

    alpha ^ beta | gamma

    If you use parentheses for less common operator precedence cases, as
    Keith suggests, your code will be clear and there will be an obvious and immediate match between what the programmer intended, what the compiler
    does, and what any reader (experienced or not) will see.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Scott Lurndal on Thu Feb 15 14:40:41 2024
    On 14/02/2024 22:53, Scott Lurndal wrote:

    OTOH, all the systems the code in question run typedef uint64_t to unsigned long, so the 'ul' suffix works correctly in all forseeable usages in this application. And it's less to type than casting. Granted it's not particularly meaningful in the 0ul case, but it's a habit that does
    come in handy in expressions like

    uint64_t address;
    address = (0xcul << 44) | ((uint64_t)node << 44) | (device << 32) | register_offset;

    Yes, a cast on the constant would work as well. And yes, a good compiler will warn if the suffix is missing from the first constant value.

    It would be better to use "ull", since there are lots of systems that
    have 32-bit "long", but "long long" is always going to be at least
    64-bit (and I have never heard of any where it is longer than that).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to David Brown on Thu Feb 15 13:47:39 2024
    On 15/02/2024 13:20, David Brown wrote:
    On 15/02/2024 07:37, Tim Rentsch wrote:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:

    But C has a *lot* of precedence levels, and they're not all
    obvious.

    If I see `a | b ^ c`, I'm not likely to remember off the top of my
    head ...

    So don't remember off the top of your head, [just] keep the docs
    handy.  That's what I do.

    Why?  The code is easier to read and maintain if the precedence is
    made explicit.

    Every serious C developer should know all the operator precedence
    relationships without having to look them up.


    <https://en.wikipedia.org/wiki/No_true_Scotsman>

    /Serious/ developers write code that is as clear as they can.  They know where references are for when they need them, but do not waste cognitive effort memorising things that are better expressed in a different way
    (such as by using parentheses or breaking expressions into parts).

    In cases where it is still felt necessary to indicate how different
    operators parse with respect to one another, it's better to do that
    using spacing than with parentheses, as for example

         a | b^c

    or

         alpha   |   beta ^ gamma


    No, that is the silliest thing to do.  Don't write code that looks like
    what you think it should mean - even if it happens to match the somewhat arbitrary choices of a language.  Write code that does exactly what you mean, clearly and unequivocally, and requires the minimum of cognitive
    effort on the part of the reader.

    People make mistakes, even if they are "serious C developers".  And if
    you start using spaces to make it look like you are correct, neither you
    nor others looking at the code will notice mistakes like :

        alpha   ^   beta | gamma

    If you use parentheses for less common operator precedence cases, as
    Keith suggests, your code will be clear and there will be an obvious and immediate match between what the programmer intended, what the compiler
    does, and what any reader (experienced or not) will see.


    You have to wonder why the creators of C thought it was a good idea in
    the first place to have so many precedence levels, if you're going to
    end up using parentheses anyway to disambiguate.

    There are 10 levels for binary operators (excl. augmented assignment);
    for the same set of operators, I have only 5 for example.

    I don't know about other languages, but splitting == != < <= >= > into
    two levels is surely an odd thing to do, for a start.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Thu Feb 15 06:07:39 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    Michael S <already5chosen@yahoo.com> writes:

    [...]

    Here is another way to think about it.

    C (and many or most other languages) are fairly strict about what
    is allowed on the left-hand side of an assignment. For example,

    a + b += c;

    is not allowed. Neither is

    (a + b) += c;

    although the reasoning is a little different in the two cases,
    neither is allowed, because neither one makes sense.

    By analogy with the second example, the statement

    (a += b) += c;

    isn't allowed, because the left-hand side is wrong. So if we
    see

    a += b += c;

    it would be silly to parse it as

    (a += b) += c;

    because that's illegal. The only other way to parse it, viz.,

    a += (b += c);

    passes the semantic prerequisites. Since it's the only way that
    makes sense, it seems natural that (without any parentheses) the
    syntax should reflect that.

    I don't think that reasoning is entirely solid.

    My comments aren't meant as reasoning. They are meant to offer a
    way of thinking that might help Michael S change his intuition
    about how C assignment operators work. Personally I have no
    problem with how assignment operators work in C. I was used to
    expression languages for years before the original K&R came out,
    and I had already internalized how cascading assignments work. At
    some point I did read the syntax rules in C for assignment
    operators, but I didn't really need them, because by that time it
    already felt natural to me that assignment proceeds right-to-left.
    And that has to be true for compound assignment operators as well
    as simple assignment, because compound assignment is simply a
    syntactic sugaring (with a small semantic adjustment) over the
    usual kind of assignment. Until I saw Michael's message it never
    would have occurred to me that someone (especially someone with his
    level of experience, which obviously is considerable) would find it
    confusing.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Janis Papanagnou on Thu Feb 15 06:14:57 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 12.02.2024 02:17, Lawrence D'Oliveiro wrote:

    You seem to be saying that something like

    bool a = b == c;

    should not be allowed.

    I have the habit to write such specific expressions with parenthesis

    a = (b == c);

    for own convenience or better maintainability. (Just BTW.)

    My practice is to avoid redundant parentheses. If it's important
    to emphasize the precedence relationships, in most cases I would
    do that something like this:

    a = b == c;

    I find using spacing in such cases to be a better impedance match
    to human eye hardware than using redundant parentheses.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Lawrence D'Oliveiro on Thu Feb 15 15:15:10 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Wed, 14 Feb 2024 15:29:00 +0100, David Brown wrote:


    The UCSD p-system pioneered the concept of “write once, run anywhere”, by >defining a standardized p-code interpreter that could be implemented
    across a whole range of different processor architectures. Once you had
    done that, plus some basic OS routines, the main part of the software, >written in Pascal, should port straight across.

    I used UCSD pascal on a Terek box in 1979. And haven't even seen
    a reference to UCSD pascal since.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Lawrence D'Oliveiro on Thu Feb 15 15:16:22 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Tue, 13 Feb 2024 16:55:32 +0100, Janis Papanagnou wrote:

    You are mistaken; C++ had no 'bool' type initially. It had been added
    later.

    The first version of the C++ standard was C++98, and that had bool in it.

    The first version of C++ was in the mid-80s and didn't have bool (c.f. cfront).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Lawrence D'Oliveiro on Thu Feb 15 15:55:06 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Wed, 14 Feb 2024 14:38:01 -0800, Keith Thompson wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    And yet, all the examples posted so far have involved, not the actual
    types, but pointers to them.

    Because pointers to incompatible types are a good way to demonstrate
    incompatibility.

    But it was those types I was talking about, not pointers to them.

    You seem to be arguing just for the sake it now since you pointedly
    refuse to answer Keith's question:

    "Do you understand that int and long are incompatible even though
    they're implicitly convertible, even if they happen to have the same
    size and representation?"

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Malcolm McLean on Thu Feb 15 17:11:15 2024
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    On 15/02/2024 08:59, Lawrence D'Oliveiro wrote:
    On Wed, 14 Feb 2024 21:54:32 GMT, Scott Lurndal wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:

    But C has a *lot* of precedence levels, and they're not all obvious. >>>>>
    If I see `a | b ^ c`, I'm not likely to remember off the top of my
    head ...

    So don’t remember “off the top of your head”: keep the docs handy. >>>> That’s what I do.

    Why? The code is easier to read and maintain if the precedence is made
    explicit.

    You’re assuming that the parenthesis clutter has negligible effect on
    readability. That may be OK with one or two extraneous pairs, but typical
    C code tends to end up with a lot more than that.

    That is an issue. It's hard to match parentheses in long expressions.

    Not if you're using an editor like vim, which highlights the matching paranthesis/brace/bracket automatically, if configured to do so.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Thu Feb 15 17:27:52 2024
    On 2024-02-15, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Thu, 15 Feb 2024 08:23:09 +0100, Janis Papanagnou wrote:

    It's worth to add Awk to your list of script languages, since it's
    standard on Unix, and its syntax largely resembles the syntax of C.

    Perl does everything Awk can do, and do it just as concisely

    Nope! E.g. remove duplicate lines:

    awk '!s[$0]++'

    Perl requires a clump of options to get into an Awk-style loop, and
    requires $ sigils on all variables. The positional fields are accessed
    in some F array, rather than $1, $2.

    Do you now the following famous quote from Larry Wall?
    Something along the lines, 'I still say "awk { print $1 }" a lot'.

    , and it can
    do more besides.

    GNU Awk can be extended with C, so you can do just about anything, in
    theory. It's not easy though. The language has a lot of shortcomings,
    like not being able to return an array from a function, or use [] indexing
    on strings, and having to represent local variables as exta unused
    parameters.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Thu Feb 15 17:29:31 2024
    On 2024-02-15, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Tue, 13 Feb 2024 12:58:49 -0800, Keith Thompson wrote:

    You're suggesting that correctness doesn't matter unless the software
    controls nuclear missiles.

    I would be hoping that safety-critical software would be written to higher standards than military stuff.

    After all, in military operations, a “friendly fire” rate of, say, 10-25%,
    seems to be considered acceptable.

    Using garbage collection in a missile should be entirely acceptable; use
    it liberally in development, and then in deployment, have enough RAM
    and tune the parameters so that it strikes the target before the first
    GC cycle.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Kaz Kylheku on Thu Feb 15 22:18:08 2024
    On 15/02/2024 18:29, Kaz Kylheku wrote:
    On 2024-02-15, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Tue, 13 Feb 2024 12:58:49 -0800, Keith Thompson wrote:

    You're suggesting that correctness doesn't matter unless the software
    controls nuclear missiles.

    I would be hoping that safety-critical software would be written to higher >> standards than military stuff.

    After all, in military operations, a “friendly fire” rate of, say, 10-25%,
    seems to be considered acceptable.

    Using garbage collection in a missile should be entirely acceptable; use
    it liberally in development, and then in deployment, have enough RAM
    and tune the parameters so that it strikes the target before the first
    GC cycle.


    It is not uncommon in embedded systems for "malloc" to allocate directly
    from a single block of memory with a single "next free byte" pointer,
    while "free" does nothing. As long as malloc is used just for memory allocations at startup, it all works fine.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Scott Lurndal on Fri Feb 16 01:12:50 2024
    On Thu, 15 Feb 2024 15:16:22 GMT, Scott Lurndal wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    The first version of the C++ standard was C++98, and that had bool in
    it.

    The first version of C++ was in the mid-80s and didn't have bool (c.f. cfront).

    It wasn’t a “standard” back then.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Fri Feb 16 01:09:14 2024
    On Tue, 13 Feb 2024 17:52:31 +0100, Janis Papanagnou wrote:

    On 12.02.2024 02:13, Lawrence D'Oliveiro wrote:

    But boolean is a subtype of int anyway, so what’s the harm in
    redefining conditional expressions to return bool instead?

    Well, no harm, but some useful constructs would probably not work any
    more.

    Just this morning I wrote[*], for example,

    size = (size+1+shift)%3; // cycle through three sizes

    where 'shift' is actually a boolean (with possible values 0 and 1).

    But they are interconvertible anyway, so that will be fine.

    [*] Actually in Javascript, but the expression is also valid in C.

    And that is valid in JavaScript. Just tried it:

    >> 2 + 2
    4
    >> 2 + true
    3
    >> 2 + false
    2

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Malcolm McLean on Fri Feb 16 01:16:52 2024
    On Thu, 15 Feb 2024 16:41:23 +0000, Malcolm McLean wrote:

    I can't remember the precedence relationships beyond a few very
    conventional and well known ones.

    No need to. This is why we have documentation. Keep it handy, and don’t be ashamed to refer to it often, even in the presence of colleagues.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Malcolm McLean on Fri Feb 16 01:18:53 2024
    On Thu, 15 Feb 2024 16:47:12 +0000, Malcolm McLean wrote:

    That is an issue. It's hard to match parentheses in long expressions.

    I have a simple answer to that: take advantage of the two dimensions of
    space available to you on the screen/page:

    if
    (
    nrhistentries <= 4
    ||
    nrpixels
    /
    (
    nrpixels
    -
    (
    histogram[0].count
    +
    histogram[1].count
    +
    histogram[2].count
    +
    histogram[3].count
    )
    ) /* won't be zero */
    >=
    count_factor
    )
    {
    ...
    } /*if*/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Fri Feb 16 01:20:35 2024
    On Thu, 15 Feb 2024 14:23:57 +0100, David Brown wrote:

    On 15/02/2024 10:00, Lawrence D'Oliveiro wrote:

    If Marie Kondo were to learn C programming, what do you think she would
    do?

    So now ...

    “Perfection is achieved, not when there is nothing more to add, but
    when there is nothing left to take away.”
    -- Antoine De Saint-Exupéry

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Fri Feb 16 02:29:24 2024
    On 2024-02-16, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Thu, 15 Feb 2024 16:47:12 +0000, Malcolm McLean wrote:

    That is an issue. It's hard to match parentheses in long expressions.

    I have a simple answer to that: take advantage of the two dimensions of
    space available to you on the screen/page:

    if
    (
    nrhistentries <= 4
    ||
    nrpixels
    /
    (
    nrpixels
    -
    (
    histogram[0].count
    +
    histogram[1].count
    +
    histogram[2].count
    +
    histogram[3].count
    )
    ) /* won't be zero */
    >=
    count_factor
    )
    {
    ...
    } /*if*/

    At that point you start losing to Lisp. E.g. TXR Lisp:

    (if (or (< hrhistentries 4)
    (>= (/ nrpixels
    (- nrpixels
    (+ [histogram 0].count
    [histogram 1].count
    [histogram 2].count
    [histogram 3].count)))
    count-factor))
    ...)

    This is idiomatic code, not a joke. I revisit code like this I've
    written years ago, or that someone else wrote, and have no trouble understanding it.

    Everything is an expression in Lisp. 200 line function definition?
    one giant expression. Breaking it into multiple lines follows
    a simple algorithm, with a handful of cases.

    Right inside this edit session for this Usenet article, I can do this:

    (if (or (< hrhistentries 4)
    = (/ nrpixels
    (- nrpixels
    (+ [histogram 0].count
    [histogram 1].count
    [histogram 2].count
    [histogram 3].count)))
    count-factor))
    ...)

    Then turn on Lisp mode in Vim using :set lisp, visually select
    the block and hit = to reindent it:

    (if (or (< hrhistentries 4)
    (>= (/ nrpixels
    (- nrpixels
    (+ [histogram 0].count
    [histogram 1].count
    [histogram 2].count
    [histogram 3].count)))
    count-factor))
    ...)

    It knows that if is an operator so the ... body is indented
    by two, rather than lined up with (or ...). This is because
    if is listed in the "lispwords" variable (:set lispwords=...).

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Fri Feb 16 03:37:34 2024
    On 15.02.2024 09:51, Lawrence D'Oliveiro wrote:
    On Thu, 15 Feb 2024 08:23:09 +0100, Janis Papanagnou wrote:

    It's worth to add Awk to your list of script languages, since it's
    standard on Unix, and its syntax largely resembles the syntax of C.

    Perl does everything Awk can do, and do it just as concisely, and it can
    do more besides.

    You missed the point; it was about scripting languages and C syntax,
    in context of someone trying to make a point whether special C-like
    scripting languages were necessary (or C as a scripting language).

    It was not about what some scripting language provides as features
    or libraries. I wonder why you try to open a completely unnecessary
    dispute like that, especially by trying to compare C with Perl.

    Perl is not standard and has its own cryptic syntax deviating from C.
    And Perl is not a terse language tool but more like a huge tractor.
    You can master Awk in few hours, not so Perl. Why do you think that
    anyone would feel a need to dispute language richness and compare
    Perl with Awk.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Fri Feb 16 03:46:54 2024
    On 15.02.2024 10:00, Lawrence D'Oliveiro wrote:
    On Thu, 15 Feb 2024 08:00:00 +0100, Janis Papanagnou wrote:

    On 14.02.2024 21:52, Lawrence D'Oliveiro wrote:

    On Wed, 14 Feb 2024 00:18:50 +0100, Janis Papanagnou wrote:

    Though most precedence rules in C make parenthesis usually unnecessary >>>> and expressions rarely need parenthesis to provide that certainty.

    And yet you were the one who added unnecessary ones in your example, I
    didn’t.

    Yes, and I explained that with the given rules you have no "clutter"
    (as you called it) ...

    “Clutter” is when you put in ones you don’t need.

    You seem to have some specific restricted definition for "need".
    You may need it syntactically or not when you have a given semantics.
    You may need it to clarify (or ascertain) something or not.

    I certainly don't consider it "clutter" if I can make non-obvious
    things clearer for the maintainers of a piece of code.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Fri Feb 16 04:03:25 2024
    On 15.02.2024 09:48, Lawrence D'Oliveiro wrote:
    On Tue, 13 Feb 2024 16:55:32 +0100, Janis Papanagnou wrote:

    You are mistaken; C++ had no 'bool' type initially. It had been added
    later.

    The first version of the C++ standard was C++98, and that had bool in it.

    Yes. But my comment about the other poster being mistaken was where
    he wrote about the time "When C++ was forked from C" (and not "When
    C++ became standardized").

    And then he squirmed by introducing vague terms to muddy this fault ("Pre-history vs history.")

    The "fork from C" was (as BJ's book) in the 1980's, the standard in
    the late 1990's.

    And the other poster makes (obviously) a wrong claim about it being
    in the first edition of Stroustrup's book.

    (Is spreading "alternative facts" so established meanwhile?)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Fri Feb 16 04:11:56 2024
    On 16.02.2024 02:09, Lawrence D'Oliveiro wrote:

    And that is valid in JavaScript. Just tried it:

    >> 2 + 2
    4
    >> 2 + true
    3
    >> 2 + false
    2


    Oh, I'm just programming in JS (since I've no web server running),
    but I'm not the right one to discuss this language. (I would have
    far too much to criticize and my "copious free time" is limited.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Kaz Kylheku on Fri Feb 16 04:14:47 2024
    On 15.02.2024 18:29, Kaz Kylheku wrote:
    On 2024-02-15, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Tue, 13 Feb 2024 12:58:49 -0800, Keith Thompson wrote:

    You're suggesting that correctness doesn't matter unless the software
    controls nuclear missiles.

    I would be hoping that safety-critical software would be written to higher >> standards than military stuff.

    After all, in military operations, a “friendly fire” rate of, say, 10-25%,
    seems to be considered acceptable.

    Using garbage collection in a missile should be entirely acceptable; use
    it liberally in development, and then in deployment, have enough RAM
    and tune the parameters so that it strikes the target before the first
    GC cycle.

    Great! :-)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Fri Feb 16 04:46:21 2024
    On Fri, 16 Feb 2024 03:37:34 +0100, Janis Papanagnou wrote:

    You can master Awk in few hours, not so Perl.

    You can figure out those same functions in Perl in the same amount of
    time. I would say that is time better spent.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Fri Feb 16 08:54:21 2024
    On 16/02/2024 02:16, Lawrence D'Oliveiro wrote:
    On Thu, 15 Feb 2024 16:41:23 +0000, Malcolm McLean wrote:

    I can't remember the precedence relationships beyond a few very
    conventional and well known ones.

    No need to. This is why we have documentation. Keep it handy, and don’t be ashamed to refer to it often, even in the presence of colleagues.

    Agreed. Fill your brain with useful things, rather than things that you
    rarely need and can easily look up. Or in the case of precedence for
    the less commonly used operators, use parentheses or break expressions
    into parts. Extra local variables are free.

    And use good tools, such as an IDE that gives you suggestions and auto-completion. Some people are dyslexic - a tool that helps you spell
    your identifiers correctly, or tells you the name of function parameters
    when you type a function name (so you can get the order right) saves you
    effort and lets you concentrate on the important things.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Kaz Kylheku on Fri Feb 16 08:59:35 2024
    On 16/02/2024 03:29, Kaz Kylheku wrote:
    On 2024-02-16, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Thu, 15 Feb 2024 16:47:12 +0000, Malcolm McLean wrote:

    That is an issue. It's hard to match parentheses in long expressions.

    I have a simple answer to that: take advantage of the two dimensions of
    space available to you on the screen/page:

    if
    (
    nrhistentries <= 4
    ||
    nrpixels
    /
    (
    nrpixels
    -
    (
    histogram[0].count
    +
    histogram[1].count
    +
    histogram[2].count
    +
    histogram[3].count
    )
    ) /* won't be zero */
    >=
    count_factor
    )
    {
    ...
    } /*if*/

    At that point you start losing to Lisp. E.g. TXR Lisp:


    He is a short step from losing to Befunge <https://en.wikipedia.org/wiki/Befunge> !

    Here's a clue. It's one thing to mark your #endif's with a comment on
    which #ifdef it matches, but if you need to do that with your "if"
    statements, your style is an incomprehensible mess.

    (I'm snipping the Lisp code, in case Malcolm sees it. He gets his
    knickers in a twist if there are more than three levels of parentheses,
    so a glance at Lisp code would give him nightmares for a week.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Fri Feb 16 09:49:48 2024
    On 16/02/2024 04:03, Janis Papanagnou wrote:
    On 15.02.2024 09:48, Lawrence D'Oliveiro wrote:
    On Tue, 13 Feb 2024 16:55:32 +0100, Janis Papanagnou wrote:

    You are mistaken; C++ had no 'bool' type initially. It had been added
    later.

    The first version of the C++ standard was C++98, and that had bool in it.

    Yes. But my comment about the other poster being mistaken was where
    he wrote about the time "When C++ was forked from C" (and not "When
    C++ became standardized").


    That was me. I was wrong, and you corrected me. Thanks for that.

    And then he squirmed by introducing vague terms to muddy this fault ("Pre-history vs history.")

    I don't know to whom you are referring here, as I haven't seen any posts
    like that. I certainly didn't make any. (Are you making up your own "alternative facts" here?)

    I did say that the C++ standards committee felt more able to make
    breaking changes to the language when they standardised it, which is not "squirming" - it is fact. In particular, when they introduced "bool"
    they changed the definition of relational operators to evaluate to a
    "bool" result rather than an "int" result. The C standards committee
    did not make a similar change when they introduced _Bool in C99.


    The "fork from C" was (as BJ's book) in the 1980's, the standard in
    the late 1990's.

    Yes.

    The first C++ ISO standard was 1998. Prior to that, it had a couple of editions of "The C++ Programming Language" (I think I have the second
    edition on my shelf), then the "C++ Annotated Reference Manual" which
    was a "de-facto standard" on the lines of "K&R C".

    It seems "bool" didn't make it until C++98, which surprised me.



    And the other poster makes (obviously) a wrong claim about it being
    in the first edition of Stroustrup's book.

    (Is spreading "alternative facts" so established meanwhile?)

    Janis


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Lawrence D'Oliveiro on Fri Feb 16 10:01:37 2024
    On 16/02/2024 01:18, Lawrence D'Oliveiro wrote:
    On Thu, 15 Feb 2024 16:47:12 +0000, Malcolm McLean wrote:

    That is an issue. It's hard to match parentheses in long expressions.

    I have a simple answer to that: take advantage of the two dimensions of
    space available to you on the screen/page:

    if
    (
    nrhistentries <= 4
    ||
    nrpixels
    /
    (
    nrpixels
    -
    (
    histogram[0].count
    +
    histogram[1].count
    +
    histogram[2].count
    +
    histogram[3].count
    )
    ) /* won't be zero */
    >=
    count_factor
    )
    {
    ...
    } /*if*/


    hsum = hist[0].count+hist[1].count+hist[2].count+hist[3].count;
    if(nrhist<=4 || nrpixels / (nrpixels - hsum) >= count_factor ) {
    // ...
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to David Brown on Fri Feb 16 15:35:06 2024
    On Fri, 16 Feb 2024 09:49:48 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 16/02/2024 04:03, Janis Papanagnou wrote:
    On 15.02.2024 09:48, Lawrence D'Oliveiro wrote:
    On Tue, 13 Feb 2024 16:55:32 +0100, Janis Papanagnou wrote:

    You are mistaken; C++ had no 'bool' type initially. It had been
    added later.

    The first version of the C++ standard was C++98, and that had bool
    in it.

    Yes. But my comment about the other poster being mistaken was where
    he wrote about the time "When C++ was forked from C" (and not "When
    C++ became standardized").


    That was me. I was wrong, and you corrected me. Thanks for that.

    And then he squirmed by introducing vague terms to muddy this fault ("Pre-history vs history.")

    I don't know to whom you are referring here, as I haven't seen any
    posts like that. I certainly didn't make any. (Are you making up
    your own "alternative facts" here?)


    "Pre-history vs history" it's me.
    Establishing The Book as the point where one turnes into another is
    also me. The very next line in the same post.
    The rest is Janis' reading between the lines and finding there
    something I didn't wrote.

    I did say that the C++ standards committee felt more able to make
    breaking changes to the language when they standardised it, which is
    not "squirming" - it is fact. In particular, when they introduced
    "bool" they changed the definition of relational operators to
    evaluate to a "bool" result rather than an "int" result. The C
    standards committee did not make a similar change when they
    introduced _Bool in C99.


    The "fork from C" was (as BJ's book) in the 1980's, the standard in
    the late 1990's.

    Yes.

    The first C++ ISO standard was 1998. Prior to that, it had a couple
    of editions of "The C++ Programming Language" (I think I have the
    second edition on my shelf), then the "C++ Annotated Reference
    Manual" which was a "de-facto standard" on the lines of "K&R C".

    It seems "bool" didn't make it until C++98, which surprised me.



    And the other poster makes (obviously) a wrong claim about it being
    in the first edition of Stroustrup's book.

    (Is spreading "alternative facts" so established meanwhile?)

    Janis



    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Scott Lurndal on Fri Feb 16 08:33:56 2024
    scott@slp53.sl.home (Scott Lurndal) writes:

    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

    [...] It's hard to match parentheses in long expressions.

    Not if you're using an editor like vim, which highlights the
    matching paranthesis/brace/bracket automatically, if configured to
    do so.

    There are several problem with that:

    One, not all code reading takes place on a computer;

    Two, even when the reading takes place on a computer, it isn't
    always done inside an editor (I expect everyone seeing this
    message has at some point read code inside a web browser, for
    example); and

    Three, even when being conducted inside an appropriate editor,
    the highlighting takes place as a result of typing, but not as a
    result of just reading. Certainly having matching bracket
    highlighting can be helpful, but it's only a small part of the
    problem of understanding deeply nested expressions and so forth.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Tim Rentsch on Fri Feb 16 17:45:30 2024
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:

    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

    [...] It's hard to match parentheses in long expressions.

    Not if you're using an editor like vim, which highlights the
    matching paranthesis/brace/bracket automatically, if configured to
    do so.

    There are several problem with that:

    No, there are not. It works as described _when using and editor like vim_.

    Cases where you're not using 'vim' are irrelevent to that statement,
    even if otherwise on point.

    I'd point out that the last time I read code without using an editor
    such as vi/vim were line printer printouts in the 80's.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Harnden@21:1/5 to Malcolm McLean on Fri Feb 16 21:39:22 2024
    On 16/02/2024 21:24, Malcolm McLean wrote:
    On 16/02/2024 20:20, Chris M. Thomasson wrote:
    On 2/15/2024 5:16 PM, Lawrence D'Oliveiro wrote:
    On Thu, 15 Feb 2024 16:41:23 +0000, Malcolm McLean wrote:

    I can't remember the precedence relationships beyond a few very
    conventional and well known ones.

    No need to. This is why we have documentation. Keep it handy, and
    don’t be
    ashamed to refer to it often, even in the presence of colleagues.

    Agreed. In fact, double checking something in front of colleagues
    might make them feel better, so to speak. Too ashamed to double check
    something can lead to errors, bug, oh my! :^)

    Usually it's pretty clear what the expression should say, so whip
    parentheses in. Rerun. If behaviour changes, that was your bug. If not,
    at least you've made it clearer. But you never actually find out what
    the precedence relations are.

    Just use parentheses; Your precedence-fu may fail tomorrow.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to bart on Fri Feb 16 22:43:10 2024
    On Tue, 13 Feb 2024 21:08:55 +0000, bart wrote:

    No, that's not Linux-centric at all!

    Feel free to stick to the Windows-centric equivalent, then.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to bart on Fri Feb 16 22:45:27 2024
    On Tue, 13 Feb 2024 22:50:40 +0000, bart wrote:

    You don't see it because you permanently live in a Unix-shaped box and everything you deal with is designed for that box.

    Think of the walls of any box as dividing the Universe into two parts. The
    way you tell which is which is that “inside” is normally much smaller than “outside”.

    Now think of the wall between you and us: we are the ones who are free to stretch our arms out, walk and run and even fly about freely, while you
    are the one complaining about not being able to do the same.

    Which one sounds more like “inside” and which one “outside”?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Scott Lurndal on Fri Feb 16 22:47:29 2024
    On Wed, 14 Feb 2024 15:58:09 GMT, Scott Lurndal wrote:

    I see no benefit in a "C" interpreter - for which string handling is an afterthought - in any build process.

    Talk about string handling being an afterthought ... I once had this idea
    of using GNU m4 as a preprocessor for an SQL dump so that the same file
    could be loaded into both MySQL and SQLite, just by changing some command-
    line options.

    The result worked, but was very slow. I had a look at the m4 source code,
    and was quite surprised to discover that it used standard C-library
    strings.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Fri Feb 16 23:08:01 2024
    On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote:

    And use good tools, such as an IDE that gives you suggestions and auto-completion.

    auto-completion doesn’t really take you far, though. My favourite example
    is how many times people write “sqrt(x * x + y * y)” to compute a hypotenuse, not realizing that there is a “hypot(x, y)” function available in any reasonable maths library.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Richard Harnden on Fri Feb 16 23:08:25 2024
    On Fri, 16 Feb 2024 21:39:22 +0000, Richard Harnden wrote:

    Just use parentheses; Your precedence-fu may fail tomorrow.

    Not if you have the documentation handy, to refer to.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to bart on Fri Feb 16 23:10:47 2024
    On Fri, 16 Feb 2024 10:01:37 +0000, bart wrote:

    hsum = hist[0].count+hist[1].count+hist[2].count+hist[3].count;
    if(nrhist<=4 || nrpixels / (nrpixels - hsum) >= count_factor ) {
    // ...
    }

    I see you had to shorten the variable names as well. Descriptive layout
    *and* names too much for you?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Fri Feb 16 23:11:01 2024
    On Fri, 16 Feb 2024 08:59:35 +0100, David Brown wrote:

    Here's a clue. It's one thing to mark your #endif's with a comment on
    which #ifdef it matches, but if you need to do that with your "if" statements, your style is an incomprehensible mess.

    I wonder why ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Lawrence D'Oliveiro on Fri Feb 16 23:44:10 2024
    On 16/02/2024 23:10, Lawrence D'Oliveiro wrote:
    On Fri, 16 Feb 2024 10:01:37 +0000, bart wrote:

    hsum = hist[0].count+hist[1].count+hist[2].count+hist[3].count;
    if(nrhist<=4 || nrpixels / (nrpixels - hsum) >= count_factor ) {
    // ...
    }

    I see you had to shorten the variable names as well. Descriptive layout
    *and* names too much for you?

    Keep local variable names short and snappy is part of knowing how to
    write readable code.

    Now you can grok what the thing does much more easily.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Lawrence D'Oliveiro on Fri Feb 16 23:55:07 2024
    On 16/02/2024 22:45, Lawrence D'Oliveiro wrote:
    On Tue, 13 Feb 2024 22:50:40 +0000, bart wrote:

    You don't see it because you permanently live in a Unix-shaped box and
    everything you deal with is designed for that box.

    Think of the walls of any box as dividing the Universe into two parts. The way you tell which is which is that “inside” is normally much smaller than
    “outside”.

    Now think of the wall between you and us: we are the ones who are free to stretch our arms out, walk and run and even fly about freely, while you
    are the one complaining about not being able to do the same.

    Which one sounds more like “inside” and which one “outside”?

    It sounds like you're the ones who are locked in to all those myriad
    different tools and all your different systems.

    I got my first portable machine exactly 30 years ago, and for the next
    decade or two was able to work anywhere, either camping next to a beach,
    or on a tropical island, or from my car. I didn't need the internet!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Keith Thompson on Sat Feb 17 01:43:15 2024
    On 2024-02-17, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    Usually it's pretty clear what the expression should say, so whip
    parentheses in. Rerun. If behaviour changes, that was your bug. If
    not, at least you've made it clearer. But you never actually find out
    what the precedence relations are.

    Is that a joke?

    Would you seriously add parentheses to an expression and re-run to see
    if the behavior changes *without bothering to look up the actual
    precedence rules*?

    It seems it might be mildly useful to have (? ...) parentheses which
    override precedence and associativily like the regular ones, but emit a diagnostic.

    If the parentheses are necessary, the diagnostic indicates that.

    If the parentheses do nothing, it also indicates that.

    So based on the diagnostic, you remove just the ? or the entire
    (? ...).

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to Keith.S.Thompson+u@gmail.com on Sat Feb 17 05:07:48 2024
    In article <8734tr9ajg.fsf@nosuchdomain.example.com>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    ...
    Is that a joke?

    Would you seriously add parentheses to an expression and re-run to see
    if the behavior changes *without bothering to look up the actual
    precedence rules*?

    Most people (i.e., sane people) don't take a copy of the latest C standards docs with them on vacation.

    Nor do they take them on dates. Or most other places.

    --
    Res ipsa loquitur.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Harnden@21:1/5 to Kaz Kylheku on Sat Feb 17 10:08:43 2024
    On 17/02/2024 01:43, Kaz Kylheku wrote:
    On 2024-02-17, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    Usually it's pretty clear what the expression should say, so whip
    parentheses in. Rerun. If behaviour changes, that was your bug. If
    not, at least you've made it clearer. But you never actually find out
    what the precedence relations are.

    Is that a joke?

    Would you seriously add parentheses to an expression and re-run to see
    if the behavior changes *without bothering to look up the actual
    precedence rules*?

    It seems it might be mildly useful to have (? ...) parentheses which
    override precedence and associativily like the regular ones, but emit a diagnostic.

    If the parentheses are necessary, the diagnostic indicates that.

    If the parentheses do nothing, it also indicates that.

    So based on the diagnostic, you remove just the ? or the entire
    (? ...).


    Okay, but they help with semantics, so just leave them in.
    Is it better to remove them and add a commnent ... ? // didn't expect that!

    Do extra parens in the source - when they turn out to be unnecessary -
    result in bloated executable size? Or will the compiler optimise them away?

    Do extra parens in the source help the human reader?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Kenny McCormack on Sat Feb 17 12:09:06 2024
    On 17/02/2024 06:07, Kenny McCormack wrote:
    In article <8734tr9ajg.fsf@nosuchdomain.example.com>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    ...
    Is that a joke?

    Would you seriously add parentheses to an expression and re-run to see
    if the behavior changes *without bothering to look up the actual
    precedence rules*?

    Most people (i.e., sane people) don't take a copy of the latest C standards docs with them on vacation.

    Nor do they take them on dates. Or most other places.


    <https://letmegooglethat.com/?q=c+operator+precedence>


    Most people have their phone with them on vacation.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Sat Feb 17 12:11:36 2024
    On 17/02/2024 00:11, Lawrence D'Oliveiro wrote:
    On Fri, 16 Feb 2024 08:59:35 +0100, David Brown wrote:

    Here's a clue. It's one thing to mark your #endif's with a comment on
    which #ifdef it matches, but if you need to do that with your "if"
    statements, your style is an incomprehensible mess.

    I wonder why ...

    /You/ wrote it, and I've not seen anyone but you post code with " }
    /*if*/ " comments. So only you can explain why your feel your own style
    is such an incomprehensible mess.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Keith Thompson on Sat Feb 17 12:04:28 2024
    On 17/02/2024 02:13, Keith Thompson wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote:
    And use good tools, such as an IDE that gives you suggestions and
    auto-completion.

    auto-completion doesn’t really take you far, though. My favourite example >> is how many times people write “sqrt(x * x + y * y)” to compute a
    hypotenuse, not realizing that there is a “hypot(x, y)” function available
    in any reasonable maths library.

    More relevantly, it's in the C standard library (since C99, I think).


    Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on
    virtually any real system.

    "hypot" is generally not implemented as a dedicated hardware
    instruction, and is thus handled in software - it will involve a library
    call to a "hypot" function that finds the maximum absolute values of x
    and y, divides both x and y by this, then squares them and adds them,
    then finds the square root, and then multiplies up again - all so that
    it will give the correct result without a risk of overflow.

    And that's great, if your x and y are nearing half the maximum range of
    your floating point type. But how often is that realistic?

    The "sqrt(x * x + y * y)" version will generally be inlined with two
    multiples, an add, and a square root function - much faster, especially
    if the compiler can vectorize the code or interleave it with other instructions.

    A very quick test on my machine had the sqrt() version running at least
    3 times the speed of the hypot() version.

    Of course speed is not everything, and if you need the range guarantees
    of hypot(), you need them - but it would be silly to suggest that
    "hypot" is always better.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Sat Feb 17 16:01:01 2024
    On 17/02/2024 14:10, Malcolm McLean wrote:
    On 17/02/2024 11:04, David Brown wrote:
    On 17/02/2024 02:13, Keith Thompson wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote:
    And use good tools, such as an IDE that gives you suggestions and
    auto-completion.

    auto-completion doesn’t really take you far, though. My favourite
    example
    is how many times people write “sqrt(x * x + y * y)” to compute a
    hypotenuse, not realizing that there is a “hypot(x, y)” function
    available
    in any reasonable maths library.

    More relevantly, it's in the C standard library (since C99, I think).


    Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on
    virtually any real system.

    "hypot" is generally not implemented as a dedicated hardware
    instruction, and is thus handled in software - it will involve a
    library call to a "hypot" function that finds the maximum absolute
    values of x and y, divides both x and y by this, then squares them and
    adds them, then finds the square root, and then multiplies up again -
    all so that it will give the correct result without a risk of overflow.

    And that's great, if your x and y are nearing half the maximum range
    of your floating point type.  But how often is that realistic?

    The "sqrt(x * x + y * y)" version will generally be inlined with two
    multiples, an add, and a square root function - much faster,
    especially if the compiler can vectorize the code or interleave it
    with other instructions.

    A very quick test on my machine had the sqrt() version running at
    least 3 times the speed of the hypot() version.

    Of course speed is not everything, and if you need the range
    guarantees of hypot(), you need them - but it would be silly to
    suggest that "hypot" is always better.

    And in graphics software, taking the square root to normalise a vector
    is often the single most expensive step.

    That's less true that it used to be. Modern hardware square roots are
    not much slower than division - and you need two divisions and a square
    root for hypot(). (The multiplies and adds are quick.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to David Brown on Sat Feb 17 16:54:14 2024
    David Brown <david.brown@hesbynett.no> writes:
    On 17/02/2024 06:07, Kenny McCormack wrote:
    In article <8734tr9ajg.fsf@nosuchdomain.example.com>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    ...
    Is that a joke?

    Would you seriously add parentheses to an expression and re-run to see
    if the behavior changes *without bothering to look up the actual
    precedence rules*?

    Most people (i.e., sane people) don't take a copy of the latest C standards >> docs with them on vacation.

    Nor do they take them on dates. Or most other places.


    <https://letmegooglethat.com/?q=c+operator+precedence>


    Most people have their phone with them on vacation.


    Even if they do, they may not have a data plan.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Scott Lurndal on Sat Feb 17 18:46:11 2024
    On 17/02/2024 17:54, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 17/02/2024 06:07, Kenny McCormack wrote:
    In article <8734tr9ajg.fsf@nosuchdomain.example.com>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    ...
    Is that a joke?

    Would you seriously add parentheses to an expression and re-run to see >>>> if the behavior changes *without bothering to look up the actual
    precedence rules*?

    Most people (i.e., sane people) don't take a copy of the latest C standards >>> docs with them on vacation.

    Nor do they take them on dates. Or most other places.


    <https://letmegooglethat.com/?q=c+operator+precedence>


    Most people have their phone with them on vacation.


    Even if they do, they may not have a data plan.

    OK, let's everyone who takes a computer with them planning on doing
    programming is likely to have the ability to look things up online. We
    are no longer in the 1990's.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Sat Feb 17 18:54:50 2024
    On 16.02.2024 09:49, David Brown wrote:
    On 16/02/2024 04:03, Janis Papanagnou wrote:
    On 15.02.2024 09:48, Lawrence D'Oliveiro wrote:
    On Tue, 13 Feb 2024 16:55:32 +0100, Janis Papanagnou wrote:

    You are mistaken; C++ had no 'bool' type initially. It had been added
    later.

    The first version of the C++ standard was C++98, and that had bool in
    it.

    Yes. But my comment about the other poster being mistaken was where
    he wrote about the time "When C++ was forked from C" (and not "When
    C++ became standardized").


    That was me. I was wrong, and you corrected me. Thanks for that.

    And then he squirmed by introducing vague terms to muddy this fault
    ("Pre-history vs history.")

    I don't know to whom you are referring here, as I haven't seen any posts
    like that. I certainly didn't make any. (Are you making up your own "alternative facts" here?)

    No, I was replying to statements on this topic in this sub-thread
    and didn't name anyone personally here, neither you nor the other
    poster, because I try to focus on the facts not persons (and also
    not on "alternative facts" that are occasionally seen here).

    For your convenience that post said:
    : Pre-history vs history.
    : As far as I am concerned, 'initially' == it presents in in the first
    : edition of "The C++ Programming Language".

    And, yes, you were not the one who posted that. (And I didn't say so.)

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to david.brown@hesbynett.no on Sat Feb 17 19:37:04 2024
    In article <uqqrd3$h6ku$1@dont-email.me>,
    David Brown <david.brown@hesbynett.no> wrote:
    ...
    OK, let's everyone who takes a computer with them planning on doing >programming is likely to have the ability to look things up online. We
    are no longer in the 1990's.

    From which language was the above paragraph Google-translated?

    --
    The randomly chosen signature file that would have appeared here is more than 4 lines long. As such, it violates one or more Usenet RFCs. In order to remain in compliance with said RFCs, the actual sig can be found at the following URL:
    http://user.xmission.com/~gazelle/Sigs/EternalFlame

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to bart on Sat Feb 17 20:45:26 2024
    On 15.02.2024 14:47, bart wrote:
    On 15/02/2024 13:20, David Brown wrote:
    [...]

    You have to wonder why the creators of C thought it was a good idea in
    the first place to have so many precedence levels, if you're going to
    end up using parentheses anyway to disambiguate.

    I can't comment on the "parentheses to disambiguate" statement you are referring to. Where and when folks are using parentheses, IME, depends
    on various factors, and there are personal preferences for one's own
    personal projects, and [sensible] rules in larger projects' contexts.

    Parentheses are certainly not to disambiguate; precedence rules are
    there to disambiguate! Parenthesis are necessary to express semantics
    where an expression not put in parenthesis would yield something else
    than you wanted. And parentheses can also clarify *programmatically*
    how an expression has to be understood, whereas (for example) using
    indentation and formatting can only give (unreliable!) hints about
    the programmer's intention.


    There are 10 levels for binary operators (excl. augmented assignment);

    For C - if in doubt - I'm still looking up my old K&R book; here I
    find a table with altogether 15 entries. (And that's really a lot.)

    for the same set of operators, I have only 5 for example.

    Less distinguished levels implies that you need more parentheses.
    (And I make no valuation here, just observe, and conclude.)


    I don't know about other languages, but splitting == != < <= >= > into
    two levels is surely an odd thing to do, for a start.

    Whether something is appearing "odd" or not depends on ones experience
    and knowledge. C was certainly not the first language that separated
    equalities ('==' and '!=') from the comparisons that imply an ordering.
    Algol, for example, did that as well. But Algol had less precedence
    levels (1..10) - though a lot more operators than C. But, OTOH, Algol
    is also more complex here; it allows to define own operators and assign precedences to these. And even "well known" operator precedences might
    not apply if used on other types; for example an 'op * (matrix, matrix)'
    might have a lower precedence than an 'op + (matrix, matrix)'. Pascal,
    for example, has "completely" other rules (if compared to C or Algol),
    as far as boolean operations are concerned. Here the boolean 'AND' is
    close to the '*' and '/', and the 'OR' is defined close to the '+' and
    '-'; the rules makes it necessary to use parentheses (whether we like
    them or not) when combinations with comparison operator types appear.

    Given a "hierarchy of types" model, with 'bool' as the most elementary
    type[*] B, and arbitrary (e.g. scalar) types S, we observe functions
    that stay within B
    p: B -> B
    q: B x B -> B
    functions on types that yield B (like the comparison operators)
    r: S -> B
    s: S x S -> B
    and types unrelated to B
    t: S -> S
    u: S x S -> S
    With that model one would naturally write (without parenthesis), say,

    ABS A = ABS B OR X < -5 + 4 * 3^2 AND P = NOT Q

    without thinking or a lookup necessary (despite there being about 10
    operator precedences involved).

    But note that '==' and '!=' are not only used for functions of the
    type S x S -> B but can also be used for function type B x B -> B .
    So it's sensible to have these two operators on a lower precedence
    level level that the ordering functions.[**]

    From the languages mentioned above (as examples) the most coherent
    and sophisticatedly chosen precedences rules are, IMO, not found in
    Pascal or C. (YMMV.)

    Janis

    [*] Note to all those who think 'integer' is the most basic type on
    computers because they basically handle integral numbers; this sort of discussion probably deserves an own thread (if anyone's interested).

    [**] Here as well; I'm aware that for programmers from the C world it
    might be difficult to get rid of the "everything (including bool) is
    an integer" way of thinking. From a language design perspective that
    is an hindrance, though. And also the implication that there would
    be an ordering [conceptually] necessary, say, that 'true' < 'false'
    or the other way round, is a hindrance to understanding why '==' and
    '!=' is more universal than the ordering operators (which is for bool unnecessary; which again doesn't say anything about a possible value
    in practice to *have* an ordering defined for bool).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Michael S on Sat Feb 17 20:13:37 2024
    Michael S <already5chosen@yahoo.com> writes:
    On Sat, 17 Feb 2024 12:04:28 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 17/02/2024 02:13, Keith Thompson wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes: =20
    On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote: =20
    And use good tools, such as an IDE that gives you suggestions and
    auto-completion. =20

    auto-completion doesn=E2=80=99t really take you far, though. My favour= >ite
    example is how many times people write =E2=80=9Csqrt(x * x + y * y)=E2= >=80=9D to
    compute a hypotenuse, not realizing that there is a =E2=80=9Chypot(x, = >y)=E2=80=9D
    function available in any reasonable maths library. =20
    =20
    More relevantly, it's in the C standard library (since C99, I
    think).=20
    =20
    Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on=20
    virtually any real system.
    =20
    "hypot" is generally not implemented as a dedicated hardware=20
    instruction, and is thus handled in software - it will involve a
    library call to a "hypot" function that finds the maximum absolute
    values of x and y, divides both x and y by this, then squares them
    and adds them, then finds the square root, and then multiplies up
    again - all so that it will give the correct result without a risk of
    overflow.


    It is not how it is done and *not* because division is slow, but
    because your method could produce the result that is off by one LS bit.
    Most likely, a library implementation looks like that, at least >algorithmically:

    double hypot(double x, double y)

    Or perhaps like this:

    https://github.com/lattera/glibc/blob/master/sysdeps/ieee754/dbl-64/e_hypot.c

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to David Brown on Sat Feb 17 22:08:06 2024
    On Sat, 17 Feb 2024 12:04:28 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 17/02/2024 02:13, Keith Thompson wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote:
    And use good tools, such as an IDE that gives you suggestions and
    auto-completion.

    auto-completion doesn’t really take you far, though. My favourite
    example is how many times people write “sqrt(x * x + y * y)” to
    compute a hypotenuse, not realizing that there is a “hypot(x, y)”
    function available in any reasonable maths library.

    More relevantly, it's in the C standard library (since C99, I
    think).

    Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on
    virtually any real system.

    "hypot" is generally not implemented as a dedicated hardware
    instruction, and is thus handled in software - it will involve a
    library call to a "hypot" function that finds the maximum absolute
    values of x and y, divides both x and y by this, then squares them
    and adds them, then finds the square root, and then multiplies up
    again - all so that it will give the correct result without a risk of overflow.


    It is not how it is done and *not* because division is slow, but
    because your method could produce the result that is off by one LS bit.
    Most likely, a library implementation looks like that, at least algorithmically:

    double hypot(double x, double y)
    {
    int xi = ilogb(x);
    switch (xi) {
    case FP_ILOGB0:
    return abs(y);
    case FP_ILOGBNAN:
    return x;
    default:
    break;
    }

    int yi = ilogb(y);
    switch (yi) {
    case FP_ILOGB0:
    return abs(x);
    case FP_ILOGBNAN:
    return y;
    default:
    break;
    }

    if (yi > xi)
    xi = yi;
    if (xi == INT_MAX)
    return HUGE_VAL;

    int ri = xi / 2;
    x = ldexp(x, -ri*2);
    y = ldexp(y, -ri*2);
    return ldexp(sqrt(x*x+y*y), ri);
    }

    Apart from that, you are right.

    And that's great, if your x and y are nearing half the maximum range
    of your floating point type. But how often is that realistic?

    The "sqrt(x * x + y * y)" version will generally be inlined with two multiples, an add, and a square root function - much faster,
    especially if the compiler can vectorize the code or interleave it
    with other instructions.

    A very quick test on my machine had the sqrt() version running at
    least 3 times the speed of the hypot() version.

    Of course speed is not everything, and if you need the range
    guarantees of hypot(), you need them - but it would be silly to
    suggest that "hypot" is always better.


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Scott Lurndal on Sat Feb 17 22:33:03 2024
    On Sat, 17 Feb 2024 20:13:37 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Michael S <already5chosen@yahoo.com> writes:
    On Sat, 17 Feb 2024 12:04:28 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 17/02/2024 02:13, Keith Thompson wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes: =20
    On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote: =20
    And use good tools, such as an IDE that gives you suggestions
    and auto-completion. =20

    auto-completion doesn=E2=80=99t really take you far, though. My
    favour=
    ite
    example is how many times people write =E2=80=9Csqrt(x * x + y
    * y)=E2=
    =80=9D to
    compute a hypotenuse, not realizing that there is a
    =E2=80=9Chypot(x, =
    y)=E2=80=9D
    function available in any reasonable maths library. =20
    =20
    More relevantly, it's in the C standard library (since C99, I
    think).=20
    =20
    Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on=20
    virtually any real system.
    =20
    "hypot" is generally not implemented as a dedicated hardware=20
    instruction, and is thus handled in software - it will involve a
    library call to a "hypot" function that finds the maximum absolute
    values of x and y, divides both x and y by this, then squares them
    and adds them, then finds the square root, and then multiplies up
    again - all so that it will give the correct result without a risk
    of overflow.


    It is not how it is done and *not* because division is slow, but
    because your method could produce the result that is off by one LS
    bit. Most likely, a library implementation looks like that, at least >algorithmically:

    double hypot(double x, double y)

    Or perhaps like this:

    https://github.com/lattera/glibc/blob/master/sysdeps/ieee754/dbl-64/e_hypot.c


    It looks like approximately the same algorithm implemented in IEEE-754
    specific manner and optimized for 32-bit target, so slower than
    necessary on 64-bit machines.
    I intentionally limited myself to portable C in order to illustrate the principle with maximal clarity and at the same time to minimize
    pretenses of few commoners that read the C standard through lawyer's
    glasses.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to David Brown on Sat Feb 17 17:35:34 2024
    On 2/17/24 06:04, David Brown wrote:
    ...
    Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on
    virtually any real system.

    "hypot" is generally not implemented as a dedicated hardware
    instruction, and is thus handled in software - it will involve a
    library call to a "hypot" function that finds the maximum absolute
    values of x and y, divides both x and y by this, then squares them and
    adds them, then finds the square root, and then multiplies up again -
    all so that it will give the correct result without a risk of overflow.

    And that's great, if your x and y are nearing half the maximum range
    of your floating point type. But how often is that realistic?

    Keep in mind that the same approach also protects against undue loss of precision with very small numbers. If the numbers involved are
    sufficiently small, the sqrt(x*x + y*y) approach will give 0, even
    though the correct value can be accurately represented.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Scott Lurndal on Sat Feb 17 15:56:38 2024
    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

    [...] It's hard to match parentheses in long expressions.

    Not if you're using an editor like vim, which highlights the
    matching paranthesis/brace/bracket automatically, if configured to
    do so.

    There are several problem with that:

    No, there are not. It works as described _when using and editor
    like vim_.

    Cases where you're not using 'vim' are irrelevent to that
    statement, even if otherwise on point.

    I fully expect that vim does everything you say it does.
    My point is that the highlighting that vim does doesn't
    fully solve the problem of needing a non-trivial effort
    to see which parentheses go with which other parentheses,
    in order to understand how a long expression with lots
    of parentheses parses, even just in the context of reading
    code using vim.

    I'd point out that the last time I read code without using an
    editor such as vi/vim were line printer printouts in the 80's.

    Just out of curiosity, when you read news, do the articles
    come up in a vim-like editor? When you see an article that
    has code in it, do you somehow put the article into vim to
    read it?

    The last time I read code without using an editor was this
    morning.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Sat Feb 17 16:10:06 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    [...]

    In this particular case, I'd just use 0. If for some reason I
    needed to make it explicitly of type uint64_t (say, for an
    argument to a variadic function), I'd write `(uint64_t)0`.

    Ick. At least write '(uint64_t){ 0 }' rather than casting.

    Why?

    Casts are dangerous. Besides being dangerous, in many cases
    casts are accidents waiting to happen. Writing casts at the drop
    of a hat is a bad habit. A good programming practice is to avoid
    using a cast whenever feasible. Using a compound literal isn't a
    lot better than just a raw cast, but it does at least provide a
    little extra safety because it allows only "safe" conversions.
    Seeing a cast in open code should always raise a red flag,
    especially when, as in this case, it's easy to find a safer
    alternative.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Keith Thompson on Sun Feb 18 02:35:37 2024
    On 18.02.2024 01:45, Keith Thompson wrote:
    [...] But anyone who knows C can recognize
    that casting a constant 0 to an integer type is not in any way
    dangerous.

    That's what I'd expect. Moreover...

    I recall that we had used the _specific literal constant_ 0 as a
    "universal" constant to all integral types, floats, and pointers
    without cast.[*] That was in the 1990's. Are there meanwhile any
    restrictions on using 0 without cast?

    Janis

    [*] I anyway preferred '\0', 0.0, or a 'null' constant definition
    for pointers.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Janis Papanagnou on Sun Feb 18 02:39:37 2024
    On 18.02.2024 02:16, Janis Papanagnou wrote:

    Okay, that seems to be what I was also saying. (I don't know the terms Bodmas/Bidmas, though. Here we have the "Punkt vor Strich" Rule; "dot
    before dash", where the dot operations are mult and add, and the dash

    Should have been: "dot operations are mult and div"

    operations plus and minus, according to the symbols used in writing,
    '·' ':' '+' '-'.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Malcolm McLean on Sun Feb 18 02:16:39 2024
    On 17.02.2024 21:45, Malcolm McLean wrote:

    In computer programs it is normally acceptable to write a = b + c * d
    and because programs contain so many similar expressions, and because
    the reader is another programmer and knows that the meaning is
    constrained by the language as well as by convention, it will not cause
    any confusion. But in a non-computer, non-professional mathematical
    context, it is too likely to cause confusion, and you must write a = b +
    (c * d).

    I cannot follow you where you write about "non-computer" etc. contexts.
    Are you really saying that the '*' is evaluated before '+' rule is not generally taught and well known? I mean, I'd expect that anyone who is
    doing even most simple arithmetic calculations must know that; knowing
    the total price, for example, when buying a bread and 3 pretzels.


    That's for the widely known and accepted convention about the four rules
    of arithmetic. Taught in British schools as Bodmas, or sometimes Bidmas
    (i is for index).

    Okay, that seems to be what I was also saying. (I don't know the terms Bodmas/Bidmas, though. Here we have the "Punkt vor Strich" Rule; "dot
    before dash", where the dot operations are mult and add, and the dash operations plus and minus, according to the symbols used in writing,
    '·' ':' '+' '-'.)

    Enough people also know that "or" is lower precedence
    than "and" in logical expressions. But for anything else, all bets are
    off, and again, you must use parentheses.

    Right. - I'm not saying that you should avoid parenthesis, rather the
    opposite; make things clear where it helps. And if in doubt use some parentheses. Maintainers of such code will be grateful for such easy
    to spot means of generating clarity.

    (I think the other poster's exaggerative use of negative wording when
    using parentheses must have some "parentheses everywhere" nightmare in
    mind; but I can't tell.)

    But I'm also saying that a language can be designed in a more or less
    helpful ("natural") way concerning precedence. In a well-designed
    language you can choose the best parenthesis-level depending on the
    context (formulas and people), in a not so good designed language you
    may have to use parentheses at places where it's not so clear why you
    have to. And you may experience an issue with your or others' code.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to bart on Sun Feb 18 02:22:38 2024
    On Fri, 16 Feb 2024 23:55:07 +0000, bart wrote:

    On 16/02/2024 22:45, Lawrence D'Oliveiro wrote:

    Which one sounds more like “inside” and which one “outside”?

    It sounds like you're the ones who are locked in to all those myriad different tools and all your different systems.

    Great. So what are you complaining about? Because remember, most of the
    noise and whining seems to be coming from your side of the wall, not ours.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Sun Feb 18 02:28:33 2024
    On Sat, 17 Feb 2024 16:45:49 -0800, Keith Thompson wrote:

    Yes, casts certainly can be dangerous ...

    This is why C++ defined four different kinds of casting. The dangerous one
    is called “reinterpret_cast”, while the others are much safer to use.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Sun Feb 18 02:30:08 2024
    On Sun, 18 Feb 2024 02:35:37 +0100, Janis Papanagnou wrote:

    I recall that we had used the _specific literal constant_ 0 as a
    "universal" constant to all integral types, floats, and pointers without cast.[*] That was in the 1990's.

    That is still true in the C spec today. Note that “0” as a pointer does
    not mean that the address value has to be zero: the implementation is
    expected to convert the integer literal 0 to whatever address value is
    meant to be interpreted as “no such address”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Sun Feb 18 02:34:43 2024
    On Sat, 17 Feb 2024 12:04:28 +0100, David Brown wrote:

    And that's great, if your x and y are nearing half the maximum range of
    your floating point type. But how often is that realistic?

    There is an old saying: “correctness comes before efficiency”.

    A key principle of IEEE754 is that users, particularly users nonexpert in
    the field of numerics, should be exposed to a minimum of surprise.

    If you’ve done much in numerics, you will likely have come across some of
    the writings of Prof William “Mr IEEE754” Kahan. He’s a guy well worth listening to.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to bart on Sun Feb 18 02:42:40 2024
    On Fri, 16 Feb 2024 23:44:10 +0000, bart wrote:

    On 16/02/2024 23:10, Lawrence D'Oliveiro wrote:
    On Fri, 16 Feb 2024 10:01:37 +0000, bart wrote:

    hsum = hist[0].count+hist[1].count+hist[2].count+hist[3].count;
    if(nrhist<=4 || nrpixels / (nrpixels - hsum) >= count_factor ) {
    // ...
    }

    I see you had to shorten the variable names as well. Descriptive layout
    *and* names too much for you?

    Keep local variable names short and snappy is part of knowing how to
    write readable code.

    That’s about making the code easier to write, not easier to read. Don’t confuse the two. And don’t assume that the first has more importance than
    the second.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Sun Feb 18 02:40:22 2024
    On Sun, 18 Feb 2024 02:16:39 +0100, Janis Papanagnou wrote:

    (I don't know the terms Bodmas/Bidmas, though. ...

    We learned BODMAS, too. Although I remember the “O” stood for “Of”, as in
    implied multiplication. So that binds more tightly than division (“D”), which in turn binds more tightly than explicit multiplication (“M”). So
    for example

    a ÷ b(c + d)

    should be interpreted as

    a ÷ (b(c + d))

    while

    a ÷ b × (c + d)

    should be interpreted as

    (a ÷ b) × (c + d)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Sun Feb 18 02:43:55 2024
    On Sat, 17 Feb 2024 12:11:36 +0100, David Brown wrote:

    On 17/02/2024 00:11, Lawrence D'Oliveiro wrote:

    On Fri, 16 Feb 2024 08:59:35 +0100, David Brown wrote:

    Here's a clue. It's one thing to mark your #endif's with a comment on
    which #ifdef it matches, but if you need to do that with your "if"
    statements, your style is an incomprehensible mess.

    I wonder why ...

    /You/ wrote it, and I've not seen anyone but you post code with " }
    /*if*/ " comments. So only you can explain why your feel your own style
    is such an incomprehensible mess.

    You are the one who has never seen it before, and so you react with
    ignorance and fear. Almost as though the code has become like magic to
    you.

    You are the one calling it an “incomprehensible mess”, it is up to you to back up your claim.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Keith Thompson on Sun Feb 18 06:45:14 2024
    On 18.02.2024 03:07, Keith Thompson wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 18.02.2024 01:45, Keith Thompson wrote:
    [...] But anyone who knows C can recognize
    that casting a constant 0 to an integer type is not in any way
    dangerous.

    That's what I'd expect. Moreover...

    I recall that we had used the _specific literal constant_ 0 as a
    "universal" constant to all integral types, floats, and pointers
    without cast.[*] That was in the 1990's. Are there meanwhile any
    restrictions on using 0 without cast?

    0 is of type int. In most contexts, it will be implicitly converted to
    any scalar type -- which is why { 0 } is a valid initializer for any
    type (C23 will allow {}).

    What I had in mind was not the implicit cast from any integer literal
    to other scalar types. But back these days the folks who handled that
    told us that the 0 was a specific value, especially in the context of
    pointers (where, IIRC, the NULL pointer could have a non-0 decimal
    value, but using 0 would not act as decimal 0 but as NULL-pointer).
    In other words; however NULL was defined you could use p=NULL or p=0
    with the same result.
    (But since this had been just second hand information that I hadn't
    checked myself I'm asking.)

    The problem is contexts where that conversion
    doesn't occur. The most common is an argument to a variadic function;
    for example printf("%ld\n", 0) has undefined behavior.

    Yes. If I'm using modifiers like 'l' I also use variables (or values
    with suffix) of appropriate type. (In C++ we didn't care with type
    safe stream output.)

    A less common
    case is a call to a function with an old-style non-prototype
    declaration.

    (I use only declared functions.)


    [*] I anyway preferred '\0', 0.0, or a 'null' constant definition
    for pointers.

    I presume you mean NULL (and C23 adds nullptr).

    No. Using NULL was disputed but dismissed in favor of an own 'null'
    definition. But I don't recall anymore what the reason for it was.
    It was part of a class library that had been developed centrally.

    (BTW, all I said was in a C++ context (not C), in case it matters.)

    But note that NULL
    requires a cast in some cases, like printf("%p\n", (void*)NULL);

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Sun Feb 18 06:12:57 2024
    On Sun, 18 Feb 2024 06:46:36 +0100, Janis Papanagnou wrote:

    This is exactly what I was remembering.

    This is why it helps to keep a copy of the docs handy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Sun Feb 18 06:46:36 2024
    On 18.02.2024 03:30, Lawrence D'Oliveiro wrote:
    On Sun, 18 Feb 2024 02:35:37 +0100, Janis Papanagnou wrote:

    I recall that we had used the _specific literal constant_ 0 as a
    "universal" constant to all integral types, floats, and pointers without
    cast.[*] That was in the 1990's.

    That is still true in the C spec today. Note that “0” as a pointer does not mean that the address value has to be zero: the implementation is expected to convert the integer literal 0 to whatever address value is
    meant to be interpreted as “no such address”.

    This is exactly what I was remembering. Thanks for the confirmation.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Lawrence D'Oliveiro on Sun Feb 18 11:02:43 2024
    On Sun, 18 Feb 2024 02:28:33 -0000 (UTC)
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    On Sat, 17 Feb 2024 16:45:49 -0800, Keith Thompson wrote:

    Yes, casts certainly can be dangerous ...

    This is why C++ defined four different kinds of casting. The
    dangerous one is called “reinterpret_cast”, while the others are much safer to use.

    Potential usefulness of the distinction almost fully nullified both
    by retention of C-style cast and by presence of similarly omnipotent function-style cast that C++ added on its own.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Lawrence D'Oliveiro on Sun Feb 18 11:09:46 2024
    On Sun, 18 Feb 2024 02:42:40 -0000 (UTC)
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    On Fri, 16 Feb 2024 23:44:10 +0000, bart wrote:

    On 16/02/2024 23:10, Lawrence D'Oliveiro wrote:
    On Fri, 16 Feb 2024 10:01:37 +0000, bart wrote:

    hsum =
    hist[0].count+hist[1].count+hist[2].count+hist[3].count;
    if(nrhist<=4 || nrpixels / (nrpixels - hsum) >= count_factor ) {
    // ... }

    I see you had to shorten the variable names as well. Descriptive
    layout *and* names too much for you?

    Keep local variable names short and snappy is part of knowing how to
    write readable code.

    That’s about making the code easier to write, not easier to read.
    Don’t confuse the two. And don’t assume that the first has more importance than the second.

    Short-named local vars are easier to read, too.
    That is, as long as they are truly local, rather than declared at the
    top in the style advocated by Malcolm (and by bart too?).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Malcolm McLean on Sun Feb 18 09:34:26 2024
    On 2024-02-18, Malcolm McLean <malcolm.arthur.mclean@gmail.com> wrote:
    On 18/02/2024 01:22, Keith Thompson wrote:
    What audience are you writing for that knows that "*" means
    multiplication but won't understand "a = b + c * d;"?

    [...]

    Anyone who either thinks that the rule to to apply the operations in
    sequence from left to right, or thinks that the writer may be using this rule, or who thinks that if you enter the expression into a calculator,
    the calculator is always right.

    Or someone who was last employed in 1985, working in Smalltalk.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Malcolm McLean on Sun Feb 18 11:30:07 2024
    On 18/02/2024 07:48, Malcolm McLean wrote:
    On 18/02/2024 01:22, Keith Thompson wrote:
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    [...]
    In computer programs it is normally acceptable to write a = b + c * d
    and because programs contain so many similar expressions, and because
    the reader is another programmer and knows that the meaning is
    constrained by the language as well as by convention, it will not
    cause any confusion. But in a non-computer, non-professional
    mathematical context, it is too likely to cause confusion, and you
    must write a = b +   (c * d).

    What audience are you writing for that knows that "*" means
    multiplication but won't understand "a = b + c * d;"?

    [...]

    Anyone who either thinks that the rule to to apply the operations in
    sequence from left to right, or thinks that the writer may be using this rule, or who thinks that if you enter the expression into a calculator,
    the calculator is always right.

    1970s calculators might have been too crude to use precedence. But Casio calculator now will give you 14 if you enter '2 + 3 x 4'. Any calculator
    app will do so. Even Google will give you 14 if you enter that.

    Very few expect it to be 20.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Richard Harnden on Sun Feb 18 04:32:36 2024
    Richard Harnden <richard.harnden@gmail.invalid> writes:

    On 17/02/2024 01:43, Kaz Kylheku wrote:

    [.. ideas for how to deal with parentheses and precedence ..]

    It seems it might be mildly useful to have (? ...) parentheses
    which override precedence and associativily like the regular ones,
    but emit a diagnostic.

    If the parentheses are necessary, the diagnostic indicates that.

    If the parentheses do nothing, it also indicates that.

    So based on the diagnostic, you remove just the ? or the entire
    (? ...).

    Okay, but they help with semantics, so just leave them in. Is it
    better to remove them and add a commnent ... ? // didn't expect
    that!

    Do extra parens in the source - when they turn out to be
    unnecessary - result in bloated executable size?

    Almost certainly not.

    Or will the compiler optimise them away?

    Probably the code will be transformed, prior to code generation,
    to an internal form where parentheses don't even exist, so no
    further effort is needed to remove superfluous parentheses.

    Do extra parens in the source help the human reader?

    Let's consider an example. Suppose we see this line of code:

    if( (a == b) & (c == d) ) ...

    (I have put in extra spaces inside the if() parentheses so the
    condition being tested stands out more.)

    The parentheses in the test condition are unnecessary. Why are
    they there? Was the author

    confused about what the rules are?

    unsure of what the rules are, and put them in to be safe?

    aware that the parentheses are unnecessary, but put them
    in because a co-worker is known to be confused or unsure?

    confident that everyone on the team knows the rules, but
    added the unnecessary parentheses because of some internal
    coding standard or belief about good practices, etc?

    Without more information it's difficult to guess which of those
    possibilities explains the situation.

    By contrast, suppose we see this line:

    if( a==b & c==d ) ...

    First, it is reasonable to infer that the author believes the
    equality comparisons will be done before the bitwise and (and
    that belief is correct as far as C is concerned).

    Second, the extra spaces allow that assumption to be verified,
    either by the compiler or by a stand-alone tool, and a warning
    given if the assumption was wrong (for example, if the '&' had
    instead been a '+').

    Third, the extra spaces help a reader understand both how the
    expression is parsed and that the author knows the rules and the
    code accurately reflects how the program will in fact behave.

    Fourth, the visual appearance of the second line makes it easier
    to assimilate than the first line (not rigorously tested, but
    there is anecdotal evidence that it's true).

    Even if extra parentheses in the source do help a human reader
    (and certainly they can in some cases), in my view it seems clear
    that there is more benefit to choosing the extra spaces style
    than the extra parentheses style.

    Just some things to think about...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Harnden@21:1/5 to Malcolm McLean on Sun Feb 18 12:39:15 2024
    On 18/02/2024 12:00, Malcolm McLean wrote:
    On 18/02/2024 11:30, bart wrote:
    On 18/02/2024 07:48, Malcolm McLean wrote:
    On 18/02/2024 01:22, Keith Thompson wrote:
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    [...]
    In computer programs it is normally acceptable to write a = b + c * d >>>>> and because programs contain so many similar expressions, and because >>>>> the reader is another programmer and knows that the meaning is
    constrained by the language as well as by convention, it will not
    cause any confusion. But in a non-computer, non-professional
    mathematical context, it is too likely to cause confusion, and you
    must write a = b +   (c * d).

    What audience are you writing for that knows that "*" means
    multiplication but won't understand "a = b + c * d;"?

    [...]

    Anyone who either thinks that the rule to to apply the operations in
    sequence from left to right, or thinks that the writer may be using
    this rule, or who thinks that if you enter the expression into a
    calculator, the calculator is always right.

    1970s calculators might have been too crude to use precedence. But
    Casio calculator now will give you 14 if you enter '2 + 3 x 4'. Any
    calculator app will do so. Even Google will give you 14 if you enter
    that.

    Very few expect it to be 20.


    Oh you are right. I pushed it into the calculator that ships with my
    Mac, and it is 14. It did use to be 20 for that type of calculator.

    Even the shell does it properly:

    $ echo $(( 2 + 3 * 4 ))
    14


    The one I had at school would have answered 20. But I seldom used
    calculators after leaving school. They can't do the sums you have to do
    at university.


    Desktop calcualtors meant for accountants, where 'plus-equals' is a
    single key ... now they are impossible to use.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Sun Feb 18 15:38:39 2024
    On 18.02.2024 07:12, Lawrence D'Oliveiro wrote:
    On Sun, 18 Feb 2024 06:46:36 +0100, Janis Papanagnou wrote:

    This is exactly what I was remembering.

    This is why it helps to keep a copy of the docs handy.

    ???

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Malcolm McLean on Sun Feb 18 15:31:33 2024
    On 18.02.2024 12:01, Malcolm McLean wrote:
    On 18/02/2024 02:28, Lawrence D'Oliveiro wrote:
    On Sat, 17 Feb 2024 16:45:49 -0800, Keith Thompson wrote:

    Yes, casts certainly can be dangerous ...

    This is why C++ defined four different kinds of casting.

    It was certainly good to separate the different types of casts.

    Though I generally tried to avoid casts (in C and in C++), and
    that worked generally pretty well...

    The dangerous one
    is called “reinterpret_cast”, while the others are much safer to use.

    ...and I think I (almost?) never needed to use this type of cast.

    The same with const_cast; I tried to write 'const'-coherent code
    and did not need it. And also the remaining ones I rarely used.


    And my experience is the opposite. Reinterpeting a bit pattern as
    something else is a safe and proper use of a cast, whilst calling user-defined code without necessarily realising it is dangerous, and manipulating inheritance hierachies in strange ways is also confusing
    and dangerous.

    But you don't "manipulate" hierarchies with a dynamic_cast; it's
    (from the four) the most (sort of) "complex" cast, in the sense
    that it's evaluated on run-time, but you get definite results
    from it to reliably act on the objects (or 0) that you can test
    with that cast. (Disclaimer: as far as long-term memory serves.)

    I also think that re-interpreting types on bit level is not only
    the most C-like but by far also the most "dangerous" one, no
    less as it is in C.

    The separation of casts in C++ helps locating critical places.
    (In C with the two parenthesis syntaxes that was a nightmare.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Michael S on Sun Feb 18 15:36:31 2024
    On 18.02.2024 10:02, Michael S wrote:
    On Sun, 18 Feb 2024 02:28:33 -0000 (UTC)
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Sat, 17 Feb 2024 16:45:49 -0800, Keith Thompson wrote:

    Yes, casts certainly can be dangerous ...

    This is why C++ defined four different kinds of casting. The
    dangerous one is called “reinterpret_cast”, while the others are much
    safer to use.

    Potential usefulness of the distinction almost fully nullified both
    by retention of C-style cast and by presence of similarly omnipotent function-style cast that C++ added on its own.

    You don't have to use the old C syntax or C++ function-style for
    old casting. It's on you to make use of the new distinct forms.
    And in projects you can define coding standards to make sure that
    the old less secure forms are not used. We certainly defined such
    standards in out projects.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Sun Feb 18 15:46:02 2024
    On 18/02/2024 03:40, Lawrence D'Oliveiro wrote:
    On Sun, 18 Feb 2024 02:16:39 +0100, Janis Papanagnou wrote:

    (I don't know the terms Bodmas/Bidmas, though. ...

    We learned BODMAS, too. Although I remember the “O” stood for “Of”, as in
    implied multiplication. So that binds more tightly than division (“D”), which in turn binds more tightly than explicit multiplication (“M”). So for example

    a ÷ b(c + d)

    should be interpreted as

    a ÷ (b(c + d))

    while

    a ÷ b × (c + d)

    should be interpreted as

    (a ÷ b) × (c + d)

    Having been educated in Britain, I have never heard of "Bodmas" or
    "Bidmas". I don't recall any mnemonic for the rules of precedence in
    normal arithmetic.

    In written maths, you can use spacing and free arrangement of symbols to indicate precedence. But you should be very careful of mixing division
    and multiplication operators unless it is clear from the layout - the
    way people interpret these things differ. Different countries have
    different rules, and the rules change over time.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Sun Feb 18 15:52:01 2024
    On 17/02/2024 21:08, Michael S wrote:
    On Sat, 17 Feb 2024 12:04:28 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 17/02/2024 02:13, Keith Thompson wrote:
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote:
    And use good tools, such as an IDE that gives you suggestions and
    auto-completion.

    auto-completion doesn’t really take you far, though. My favourite
    example is how many times people write “sqrt(x * x + y * y)” to
    compute a hypotenuse, not realizing that there is a “hypot(x, y)”
    function available in any reasonable maths library.

    More relevantly, it's in the C standard library (since C99, I
    think).

    Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on
    virtually any real system.

    "hypot" is generally not implemented as a dedicated hardware
    instruction, and is thus handled in software - it will involve a
    library call to a "hypot" function that finds the maximum absolute
    values of x and y, divides both x and y by this, then squares them
    and adds them, then finds the square root, and then multiplies up
    again - all so that it will give the correct result without a risk of
    overflow.


    It is not how it is done and *not* because division is slow, but
    because your method could produce the result that is off by one LS bit.
    Most likely, a library implementation looks like that, at least algorithmically:


    OK. I don't claim to have more than an approximate idea about how these
    are implemented, and freely accept that you and others know the details
    much better. (I know I can always look these things up if I need them,
    but have never had cause to do so.) My point was just that the "hypot" function will be a lot slower than the plain sqrt() version, but it will
    also be more accurate and have greater ranges.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Sun Feb 18 15:59:28 2024
    On 18/02/2024 03:34, Lawrence D'Oliveiro wrote:
    On Sat, 17 Feb 2024 12:04:28 +0100, David Brown wrote:

    And that's great, if your x and y are nearing half the maximum range of
    your floating point type. But how often is that realistic?

    There is an old saying: “correctness comes before efficiency”.


    Sure - but what is "correct" here? Very often, "correct" in floating
    point code means "end results within a certain margin of error, for
    realistic input values". What these error margins and ranges are will
    depend on the code and its use.

    IEEE correctness is a different matter - it aims to be as accurate as
    possible within the limits of the representations used. That is not a
    suitable specification for "correctness" in user code - but it is a way
    to help write your user code to specification.

    A key principle of IEEE754 is that users, particularly users nonexpert in
    the field of numerics, should be exposed to a minimum of surprise.


    It could well be a surprise to non-experts that there is a function
    "hypot" in the C library, rather than just writing "sqrt(x*x + y*y)".
    And it would certainly be a surprise to non-experts that the dedicated
    "hypot" function is far slower than the hand-written version.

    In general, however, I agree with you in regard to IEEE754's intentions.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Malcolm McLean on Sun Feb 18 15:54:05 2024
    On 18.02.2024 13:09, Malcolm McLean wrote:

    "i" is effectively a keyword, and "i=0" was picked up as one of the most common sequences in C by some sort of analysis. I think it was for compression. Just out "int i;" at the top and you have it in scope and
    handy.

    Sure.

    And don't decare it in the loop because you can't then do

    for (i = 0; i < N; i++)
    if(!x[i])
    break;
    if (i == N)

    and you don't want a mix of counter variables declared in the loop and variables not. It's not a huge deal. But it is that bit harder to
    understand and to read.

    You could of course use a semantical name and keep variables localized

    bool null_found = false;
    for (int i = 0; i < N; i++)
    if(!x[i]) {
    null_found = true; break;
    }
    if (! null_found)

    (Of course you should find a better, more sensible name for the !x[i] condition, which I cannot guess from the few lines above.)

    But that's of course a style issue, where opinions certainly differ,
    and that people who prefer terse names and terse code will probably
    dislike this. (Myself I like local declarations and semantical names.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Malcolm McLean on Sun Feb 18 15:59:45 2024
    On 18.02.2024 08:48, Malcolm McLean wrote:
    On 18/02/2024 01:22, Keith Thompson wrote:
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    [...]
    In computer programs it is normally acceptable to write a = b + c * d
    and because programs contain so many similar expressions, and because
    the reader is another programmer and knows that the meaning is
    constrained by the language as well as by convention, it will not
    cause any confusion. But in a non-computer, non-professional
    mathematical context, it is too likely to cause confusion, and you
    must write a = b + (c * d).

    What audience are you writing for that knows that "*" means
    multiplication but won't understand "a = b + c * d;"?

    Anyone who either thinks that the rule to to apply the operations in
    sequence from left to right, or thinks that the writer may be using this rule, or who thinks that if you enter the expression into a calculator,
    the calculator is always right.

    We probably should fall back to calculators (and interfaces) with
    RPN input; this solves not only the precedence "problem" but also
    the parenthesis "problem". :-)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Sun Feb 18 16:14:23 2024
    On 18/02/2024 03:43, Lawrence D'Oliveiro wrote:
    On Sat, 17 Feb 2024 12:11:36 +0100, David Brown wrote:

    On 17/02/2024 00:11, Lawrence D'Oliveiro wrote:

    On Fri, 16 Feb 2024 08:59:35 +0100, David Brown wrote:

    Here's a clue. It's one thing to mark your #endif's with a comment on >>>> which #ifdef it matches, but if you need to do that with your "if"
    statements, your style is an incomprehensible mess.

    I wonder why ...

    /You/ wrote it, and I've not seen anyone but you post code with " }
    /*if*/ " comments. So only you can explain why your feel your own style
    is such an incomprehensible mess.

    You are the one who has never seen it before, and so you react with
    ignorance and fear. Almost as though the code has become like magic to
    you.

    "Ignorance and fear" ? Really? /That/ is what you inferred from my post?


    You are the one calling it an “incomprehensible mess”, it is up to you to back up your claim.

    My claim is that no one would feel the need to add "/*if*/" comments to
    closing brackets unless they felt the code was not clearly
    comprehensible without such comments. I am saying that /you/ write
    /your/ code as though /you/ think your own code is hard to comprehend.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Sun Feb 18 16:06:22 2024
    On 18.02.2024 15:46, David Brown wrote:
    [...] Different countries have
    different rules, and the rules change over time.

    In my country luckily not the (long established) math rules.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Kenny McCormack on Sun Feb 18 16:01:24 2024
    On 17/02/2024 20:37, Kenny McCormack wrote:
    In article <uqqrd3$h6ku$1@dont-email.me>,
    David Brown <david.brown@hesbynett.no> wrote:
    ...
    OK, let's everyone who takes a computer with them planning on doing
    programming is likely to have the ability to look things up online. We
    are no longer in the 1990's.

    From which language was the above paragraph Google-translated?


    Spotting the missing word "say" was left as an exercise for the reader.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Janis Papanagnou on Sun Feb 18 17:42:07 2024
    On Sun, 18 Feb 2024 15:54:05 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 18.02.2024 13:09, Malcolm McLean wrote:

    "i" is effectively a keyword, and "i=0" was picked up as one of the
    most common sequences in C by some sort of analysis. I think it was
    for compression. Just out "int i;" at the top and you have it in
    scope and handy.

    Sure.

    And don't decare it in the loop because you can't then do

    for (i = 0; i < N; i++)
    if(!x[i])
    break;
    if (i == N)

    and you don't want a mix of counter variables declared in the loop
    and variables not. It's not a huge deal. But it is that bit harder
    to understand and to read.

    You could of course use a semantical name and keep variables localized

    bool null_found = false;
    for (int i = 0; i < N; i++)
    if(!x[i]) {
    null_found = true; break;
    }
    if (! null_found)

    (Of course you should find a better, more sensible name for the !x[i] condition, which I cannot guess from the few lines above.)


    Your variant is unlikely to achieve the result that an idiom shown by
    Malcolm normally wants to achieve, which is not just the knowledge that
    a certain condition happened, but also an index at which it happened for
    a first time. This modification will do both:
    int nul_idx = N;
    for (int i = 0; i < N; i++) {
    if(!x[i]) {
    nul_idx = i;
    break;
    }
    }
    if (nul_idx == N) {
    } else {
    }

    It is true that it is longer to type than Malcolm's variant, but IMHO
    it is a little easier to understand. More importantly, it's more
    resilient to future changes in the code. E.g. somebody wants to add
    another loop in which the natural name for the index is again i and
    this new loop happens to be placed between the first and the last use
    of nul_idx.

    But that's of course a style issue, where opinions certainly differ,
    and that people who prefer terse names and terse code will probably
    dislike this. (Myself I like local declarations and semantical names.)

    Janis


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Janis Papanagnou on Sun Feb 18 12:37:50 2024
    On 2/18/24 00:45, Janis Papanagnou wrote:
    On 18.02.2024 03:07, Keith Thompson wrote:
    ...
    0 is of type int. In most contexts, it will be implicitly converted to
    any scalar type -- which is why { 0 } is a valid initializer for any
    type (C23 will allow {}).

    What I had in mind was not the implicit cast from any integer literal
    to other scalar types. But back these days the folks who handled that
    told us that the 0 was a specific value, especially in the context of pointers (where, IIRC, the NULL pointer could have a non-0 decimal
    value, but using 0 would not act as decimal 0 but as NULL-pointer).
    In other words; however NULL was defined you could use p=NULL or p=0
    with the same result.
    (But since this had been just second hand information that I hadn't
    checked myself I'm asking.)

    What you're thinking about is called a null pointer constant(NPC). 0 is
    the simplest NPC, but any integer constant expression with a value of 0,
    or such an expression cast to (void*), also qualifies as a null pointer constant. In many contexts, a null pointer constant gets implicitly
    converted to a null pointer of the the appropriate type. In C2023,
    nullptr also counts as an NPC.

    Note that an integer expression with a value of 0 that does NOT qualify
    as an integer constant expression therefore also does not qualify as an
    NPC. (void*)n when n happens to be 0 might or might not be a null pointer.

    All null pointers must compare equal to each other, and are prohibited
    from comparing equal to a pointer to any object or function. In
    particular, this means that any null pointer must compare equal to 0.
    However, null pointers need not be represented by all bits zero, and
    there can be multiple different representations of a null pointer in any
    given type.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Malcolm McLean on Sun Feb 18 21:07:49 2024
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

    On 18/02/2024 09:09, Michael S wrote:
    ...
    Short-named local vars are easier to read, too.
    That is, as long as they are truly local, rather than declared at the
    top in the style advocated by Malcolm (and by bart too?).

    "i" is effectively a keyword, and "i=0" was picked up as one of the most common sequences in C by some sort of analysis. I think it was for compression. Just out "int i;" at the top and you have it in scope and
    handy. And don't decare it in the loop because you can't then do

    for (i = 0; i < N; i++)
    if(!x[i])
    break;
    if (i == N)

    The replies to your tendentious advice seem to be vying for maximum obfuscation. This should not written as a 'for' loop at all; it's a
    natural 'while' loop:

    int i = 0;
    while (i < N && x[i]) i++;
    if (i == N) ...

    One sees at a glance that the loop ends when !(i < N && x[i]) i.e. when
    i >= N || !x[i]. The following condition is clearly intended to
    determine which.

    Do programmers not reason by negating loop conditions these days?

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Sun Feb 18 22:09:23 2024
    On Sun, 18 Feb 2024 15:31:33 +0100, Janis Papanagnou wrote:

    On 18/02/2024 02:28, Lawrence D'Oliveiro wrote:

    This is why C++ defined four different kinds of casting.

    It was certainly good to separate the different types of casts.

    Also, they had distinctive names that could be searched for in the code.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Malcolm McLean on Sun Feb 18 22:10:45 2024
    On Sun, 18 Feb 2024 17:43:53 +0000, Malcolm McLean wrote:

    Reintepreting bits is safe. Obviously you can do it in a way that gets
    it wrong. But that is true of all computer code.

    Doing dangerous things is safe. Obviously you can do it in a way that gets
    it wrong. But that is true of all things, not just dangerous things.

    (Spot the fallacy.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Richard Harnden on Sun Feb 18 22:19:08 2024
    On Sun, 18 Feb 2024 12:39:15 +0000, Richard Harnden wrote:

    Desktop calcualtors meant for accountants, where 'plus-equals' is a
    single key ... now they are impossible to use.

    Certainly very confusing for C programmers ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Sun Feb 18 22:23:09 2024
    On Sun, 18 Feb 2024 15:59:28 +0100, David Brown wrote:

    It could well be a surprise to non-experts that there is a function
    "hypot" in the C library, rather than just writing "sqrt(x*x + y*y)".

    What kind of programmer is it, that it would be so easy to surprise them
    just by pointing out something in the documentation?

    And yet they can remember the mathematical formula for a hypotenuse?

    And it would certainly be a surprise to non-experts that the dedicated "hypot" function is far slower than the hand-written version.

    Most of the time, they wouldn’t notice. Particularly since the function is designed to keep them out of trouble.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Sun Feb 18 22:30:10 2024
    On Sun, 18 Feb 2024 14:02:15 -0800, Keith Thompson wrote:

    Do you know of any C compilers or standalone tools that give this kind
    of warning based on spacing? I don't.

    I thought GCC had something, so I checked through the man page. I
    didn’t quite find that, but I did find these interesting ones:

    -Wparentheses
    Warn if parentheses are omitted in certain contexts, such as
    when there is an assignment in a context where a truth value is
    expected, or when operators are nested whose precedence people
    often get confused about.

    Also warn if a comparison like "x<=y<=z" appears; this is
    equivalent to "(x<=y ? 1 : 0) <= z", which is a different
    interpretation from that of ordinary mathematical notation.

    Also warn for dangerous uses of the GNU extension to "?:" with
    omitted middle operand. When the condition in the "?": operator
    is a boolean expression, the omitted value is always 1. Often
    programmers expect it to be a value computed inside the
    conditional expression instead.

    For C++ this also warns for some cases of unnecessary
    parentheses in declarations, which can indicate an attempt at a
    function call instead of a declaration:

    {
    // Declares a local variable called mymutex.
    std::unique_lock<std::mutex> (mymutex);
    // User meant std::unique_lock<std::mutex> lock (mymutex);
    }

    -Wlogical-op
    Warn about suspicious uses of logical operators in expressions.
    This includes using logical operators in contexts where a
    bit-wise operator is likely to be expected.

    -Wxor-used-as-pow (C, C++, Objective-C and Objective-C++ only)
    Warn about uses of "^", the exclusive or operator, where it
    appears the user meant exponentiation. Specifically, the
    warning occurs when the left-hand side is the decimal constant
    2 or 10 and the right-hand side is also a decimal constant.

    In C and C++, "^" means exclusive or, whereas in some other
    languages (e.g. TeX and some versions of BASIC) it means
    exponentiation.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Malcolm McLean on Sun Feb 18 22:34:57 2024
    On Sun, 18 Feb 2024 10:52:27 +0000, Malcolm McLean wrote:

    On 16/02/2024 23:10, Lawrence D'Oliveiro wrote:

    I see you had to shorten the variable names as well. Descriptive
    layout *and* names too much for you?

    Keep local variable names short and snappy is part of knowing how to
    write readable code.

    That’s about making the code easier to write, not easier to read. Don’t >> confuse the two. And don’t assume that the first has more importance
    than the second.

    It is easier to type "i" than "histogram_counter".

    Except there was no “histogram_counter” variable in my code. The name doesn’t even make sense.

    But it also makes a
    long expression with more than one index operation in it easier to read.

    The only indexing operations in the example I posted used constant
    indices. I’m not sure how you can shorten integer literals ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Malcolm McLean on Sun Feb 18 22:34:06 2024
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

    On 18/02/2024 14:46, David Brown wrote:
    On 18/02/2024 03:40, Lawrence D'Oliveiro wrote:
    On Sun, 18 Feb 2024 02:16:39 +0100, Janis Papanagnou wrote:

    (I don't know the terms Bodmas/Bidmas, though. ...

    We learned BODMAS, too. Although I remember the “O” stood for “Of”, as in
    implied multiplication. So that binds more tightly than division (“D”), >>> which in turn binds more tightly than explicit multiplication (“M”). So >>> for example

         a ÷ b(c + d)

    should be interpreted as

         a ÷ (b(c + d))

    while

         a ÷ b × (c + d)

    should be interpreted as

         (a ÷ b) × (c + d)
    Having been educated in Britain, I have never heard of "Bodmas" or
    "Bidmas".  I don't recall any mnemonic for the rules of precedence in
    normal arithmetic.

    My sister used to be maths teacher and she taught Bodmas. I remember
    because she pointed out that there was some inconsistency in it which had confused a child, but I can't remember what that was, I think it was ti do with unary minus.

    Maybe she knew what was wrong with it, but was forced to teach it
    anyway. It *can* be taught correctly, but a simple web search shows
    that it usually isn't. The trouble is that most people (and most online resources) make the order strict: first brackets, orders, division, multiplication, addition and finally subtraction, so

    3 - 2 + 1

    should have the addition done before the subtraction which is just
    wrong.

    Explaining (as some teachers no doubt try to do) that the "DM" and
    particularly "AS" bits are "grouped": first brackets, orders, then
    divisions and multiplications, and finally additions and subtractions
    (done left to right) is not really a good solution. It's just too easy
    to think it's simply an exact sequence to be followed.

    Brackets, of, division, multiplication, addition, subtraction. "of" doesn't really appear in school mathematical expressions and was mainly to make it pronouceable, and it is now "Bidmas" where "i" is "index", meaning
    exponent.

    I've always seen it rendered as "orders". I think "indexes" is better,
    but it does not fix the basic problem.

    And, for the record, I was never taught it.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Sun Feb 18 23:48:22 2024
    On 18/02/2024 15:59, Janis Papanagnou wrote:
    On 18.02.2024 08:48, Malcolm McLean wrote:
    On 18/02/2024 01:22, Keith Thompson wrote:
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    [...]
    In computer programs it is normally acceptable to write a = b + c * d
    and because programs contain so many similar expressions, and because
    the reader is another programmer and knows that the meaning is
    constrained by the language as well as by convention, it will not
    cause any confusion. But in a non-computer, non-professional
    mathematical context, it is too likely to cause confusion, and you
    must write a = b + (c * d).

    What audience are you writing for that knows that "*" means
    multiplication but won't understand "a = b + c * d;"?

    Anyone who either thinks that the rule to to apply the operations in
    sequence from left to right, or thinks that the writer may be using this
    rule, or who thinks that if you enter the expression into a calculator,
    the calculator is always right.

    We probably should fall back to calculators (and interfaces) with
    RPN input; this solves not only the precedence "problem" but also
    the parenthesis "problem". :-)


    FORTH, we now in program shall.

    :-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Sun Feb 18 23:46:28 2024
    On 18/02/2024 19:12, Malcolm McLean wrote:
    On 18/02/2024 14:46, David Brown wrote:
    On 18/02/2024 03:40, Lawrence D'Oliveiro wrote:
    On Sun, 18 Feb 2024 02:16:39 +0100, Janis Papanagnou wrote:

    (I don't know the terms Bodmas/Bidmas, though. ...

    We learned BODMAS, too. Although I remember the “O” stood for “Of”, >>> as in
    implied multiplication. So that binds more tightly than division (“D”), >>> which in turn binds more tightly than explicit multiplication (“M”). So >>> for example

         a ÷ b(c + d)

    should be interpreted as

         a ÷ (b(c + d))

    while

         a ÷ b × (c + d)

    should be interpreted as

         (a ÷ b) × (c + d)

    Having been educated in Britain, I have never heard of "Bodmas" or
    "Bidmas".  I don't recall any mnemonic for the rules of precedence in
    normal arithmetic.

    My sister used to be maths teacher and she taught Bodmas. I remember
    because she pointed out that there was some inconsistency in it which
    had confused a child, but I can't remember what that was, I think it was
    ti do with unary minus.
    Brackets, of, division, multiplication, addition, subtraction. "of"
    doesn't really appear in school mathematical expressions and was mainly
    to make it pronouceable, and it is now "Bidmas" where "i" is "index",
    meaning exponent.

    I quite believe that /some/ British schools teach "Bodmas" or "Bidmas",
    or other such acronyms. All I can say confidently is it was not taught
    in any school /I/ attended. So it is not something that was standard curriculum in British schools, at least at the time I was at school.

    Of course, there are big differences between the curriculums in Scotland
    and the other bits of the UK which follow the English school system.


    In written maths, you can use spacing and free arrangement of symbols
    to indicate precedence.  But you should be very careful of mixing
    division and multiplication operators unless it is clear from the
    layout - the way people interpret these things differ.  Different
    countries have different rules, and the rules change over time.

    I read a lot of mathematical papers that I haven't been formally trained
    how to read or understand, and it is often challenging. But precedence
    is seldom a difficulty.


    In a well-written paper, it should not be an issue. People simply don't
    write things like "a / b * c" unless it is laid out in a totally
    unambiguous manner (or parentheses are added).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Harnden@21:1/5 to Ben Bacarisse on Sun Feb 18 23:06:48 2024
    On 18/02/2024 22:34, Ben Bacarisse wrote:

    [BODMAS]


    I've always seen it rendered as "orders". I think "indexes" is better,
    but it does not fix the basic problem.

    And, for the record, I was never taught it.


    Just curious - Were you taught SOHCAHTOA for trig? I always found that
    easy to remember.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Sun Feb 18 23:53:39 2024
    On 18/02/2024 23:23, Lawrence D'Oliveiro wrote:
    On Sun, 18 Feb 2024 15:59:28 +0100, David Brown wrote:

    It could well be a surprise to non-experts that there is a function
    "hypot" in the C library, rather than just writing "sqrt(x*x + y*y)".

    What kind of programmer is it, that it would be so easy to surprise them
    just by pointing out something in the documentation?

    Once they know it exists, it will no longer be a surprise.


    And yet they can remember the mathematical formula for a hypotenuse?


    Surely most programmers know enough mathematics to remember that one?

    And it would certainly be a surprise to non-experts that the dedicated
    "hypot" function is far slower than the hand-written version.

    Most of the time, they wouldn’t notice. Particularly since the function is designed to keep them out of trouble.

    If you need an efficient way to calculate such hypotenuses, the function "hypot" will get you /into/ trouble. Typical use-cases would be in
    games or graphics programming. The range issues are totally irrelevant,
    and you need a final accuracy of your calculations to the nearest pixel
    - you don't care about the LSB's (even for single-precision floats).
    But you /do/ care about speed.

    But most often, neither speed nor range nor maximal accuracy are at all relevant, and either solution would work fine.

    (And if you care about /both/ speed and accuracy, you are probably
    better off using a pre-written numerical methods library.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Sun Feb 18 23:38:24 2024
    On Sun, 18 Feb 2024 23:53:39 +0100, David Brown wrote:

    If you need an efficient way to calculate such hypotenuses, the function "hypot" will get you /into/ trouble.

    Tip: something that programmers *do* frequently find surprising is that
    their intuitions over which parts of their code to optimize and which ones
    not to are all too frequently wrong.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Sun Feb 18 23:39:48 2024
    On Sun, 18 Feb 2024 16:14:23 +0100, David Brown wrote:

    My claim is that no one would feel the need to add "/*if*/" comments to closing brackets unless they felt the code was not clearly
    comprehensible without such comments. I am saying that /you/ write
    /your/ code as though /you/ think your own code is hard to comprehend.

    No, you originally said “... if you need to do that with your "if" statements, your style is an incomprehensible mess”. So the “incomprehensible mess” nonsense is *your* claim, not mine, and *you* are the one who needs to back it up, not me.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Ben Bacarisse on Sun Feb 18 23:42:34 2024
    On Sun, 18 Feb 2024 22:34:06 +0000, Ben Bacarisse wrote:

    ... brackets, orders ...

    “Of” (implied multiplication), not “orders”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mike Terry@21:1/5 to Richard Harnden on Mon Feb 19 00:06:12 2024
    On 18/02/2024 23:06, Richard Harnden wrote:
    On 18/02/2024 22:34, Ben Bacarisse wrote:

    [BODMAS]


    I've always seen it rendered as "orders". I think "indexes" is better,
    but it does not fix the basic problem.

    And, for the record, I was never taught it.


    Just curious - Were you taught SOHCAHTOA for trig? I always found that easy to remember.


    Never heard that one - is it thought of as one long word??

    Just as we're on the subject, a friend of mine at high school was pleased with himself for inventing
    what might be the most useless maths mnemonic ever:

    Smelly Armpits Cause Termites

    ok, it's memorable for sure, no problem on that front! But I was baffled why he thought it
    important to have a mnemonic for what it explains. (Plus it's hardly logical (mathematically) even
    if you know what it's explaining!)

    ob. Puzzle - what was his mnemonic helping him remember? [hint: it's trig related]


    Mike.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Lawrence D'Oliveiro on Mon Feb 19 02:14:43 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sun, 18 Feb 2024 22:34:06 +0000, Ben Bacarisse wrote:

    ... brackets, orders ...

    “Of” (implied multiplication), not “orders”.

    You may have been taught that (why?) but an online search suggests that
    that is not what gets taught.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Richard Harnden on Mon Feb 19 02:12:34 2024
    Richard Harnden <richard.nospam@gmail.invalid> writes:

    On 18/02/2024 22:34, Ben Bacarisse wrote:

    [BODMAS]

    I've always seen it rendered as "orders". I think "indexes" is better,
    but it does not fix the basic problem.
    And, for the record, I was never taught it.

    Just curious - Were you taught SOHCAHTOA for trig? I always found that
    easy to remember.

    No.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Mon Feb 19 04:34:59 2024
    On 18.02.2024 23:53, David Brown wrote:
    On Sun, 18 Feb 2024 15:59:28 +0100, David Brown wrote:

    It could well be a surprise to non-experts that there is a function
    "hypot" in the C library, rather than just writing "sqrt(x*x + y*y)".
    [...]

    If you need an efficient way to calculate such hypotenuses, the function "hypot" will get you /into/ trouble. Typical use-cases would be in
    games or graphics programming. The range issues are totally irrelevant,
    and you need a final accuracy of your calculations to the nearest pixel
    - you don't care about the LSB's (even for single-precision floats). But
    you /do/ care about speed.

    And not only to the nearest pixel. - Reminds me roguelike games (like
    Nethack) that work on _character maps_. They completely avoided using
    the 'float' types in Nethack and did all arithmetic in integer; even
    with (in their context rarely necessary) functions like sqrt()...

    /* integer square root function without using floating point */
    int
    isqrt(val)
    int val;
    {
    int rt = 0;
    int odd = 1;
    /*
    * This could be replaced by a faster algorithm, but has not been
    because:
    * + the simple algorithm is easy to read;
    * + this algorithm does not require 64-bit support;
    * + in current usage, the values passed to isqrt() are not really that
    * large, so the performance difference is negligible;
    * + isqrt() is used in only few places, which are not bottle-necks.
    */
    while (val >= odd) {
    val = val - odd;
    odd = odd + 2;
    rt = rt + 1;
    }
    return rt;
    }


    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Malcolm McLean on Mon Feb 19 05:06:59 2024
    On 18.02.2024 18:43, Malcolm McLean wrote:
    On 18/02/2024 14:31, Janis Papanagnou wrote:

    But you don't "manipulate" hierarchies with a dynamic_cast;

    So "manipulate" is the wrong word. You can't create or modify a
    hierarchy with a cast. But you can obtain access to members in strange
    ways.

    Okay. - Only I cannot guess in what way it appears strange to you.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Ben Bacarisse on Mon Feb 19 05:01:23 2024
    On 18.02.2024 22:07, Ben Bacarisse wrote:

    The replies to your tendentious advice seem to be vying for maximum obfuscation. This should not written as a 'for' loop at all; it's a
    natural 'while' loop:

    Yes, but the original post contained an specific for() based example
    and the topic was about local declaration not about the best control
    construct.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Malcolm McLean on Mon Feb 19 05:01:13 2024
    On 18.02.2024 18:56, Malcolm McLean wrote:
    On 18/02/2024 14:54, Janis Papanagnou wrote:
    On 18.02.2024 13:09, Malcolm McLean wrote:

    for (i = 0; i < N; i++)
    if(!x[i])
    break;
    if (i == N)

    [...]

    You could of course use a semantical name and keep variables localized
    [ my code, using 'null_found', snipped ]
    (Of course you should find a better, more sensible name for the !x[i]
    condition, which I cannot guess from the few lines above.)

    x is an array of given data which contains scalars, that is conventional
    and you ought to be able to work that out. On loop exit i will be set to
    the index of the first zero value, or N if no zero is found, and we then
    test for the latter. It should be perfectly obvious to anyone with any experience what is going on, and it's a perfectly normal thing to need
    to so. [...]

    You are just explaining what the C commands do. So your explanation is
    as useless as the comment in a=b; // a is assigned the value of b

    My statement for using a "more sensible name" to match the functional
    semantics was just saying that _I_ could only use a generic name (the semantically meaningless 'null_found') in _my_ code variant and that
    it should be replaced by a better one depending on the (to me unknown
    and also not derivable) semantics of your code.

    But don't bother.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Mon Feb 19 05:14:53 2024
    On 18.02.2024 23:09, Lawrence D'Oliveiro wrote:
    On Sun, 18 Feb 2024 15:31:33 +0100, Janis Papanagnou wrote:

    On 18/02/2024 02:28, Lawrence D'Oliveiro wrote:

    This is why C++ defined four different kinds of casting.

    It was certainly good to separate the different types of casts.

    Also, they had distinctive names that could be searched for in the code.

    Indeed. - That's why I wrote explicitly (you snipped that part)...

    The separation of casts in C++ helps locating critical places.

    ...where "locating" meant what you also expressed with "searched".

    (In C with the two parenthesis syntaxes that was a nightmare.)

    BTW; a mistake of mine was to write inaccurately "C with the two
    parenthesis syntaxes"; it was, I think, C++ that added the second
    form that made it possible that a cast looks like a function call.
    Frankly, I don't know whether C also added that.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Mon Feb 19 05:13:31 2024
    On Mon, 19 Feb 2024 05:14:53 +0100, Janis Papanagnou wrote:

    On 18.02.2024 23:09, Lawrence D'Oliveiro wrote:

    Also, they had distinctive names that could be searched for in the
    code.

    Indeed. - That's why I wrote explicitly (you snipped that part)...

    The separation of casts in C++ helps locating critical places.

    ...where "locating" meant what you also expressed with "searched".

    You didn’t say how; I did.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Mon Feb 19 05:18:32 2024
    On Mon, 19 Feb 2024 04:34:59 +0100, Janis Papanagnou wrote:

    They completely avoided using
    the 'float' types in Nethack and did all arithmetic in integer ...

    Back then, floating-point hardware cost extra, and cheaper machines (particularly in the PC market) usually did without.

    Some programs did calculations in fixed-point, to get some fractional part without going whole hog with floats.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Ben Bacarisse on Mon Feb 19 05:17:01 2024
    On Mon, 19 Feb 2024 02:14:43 +0000, Ben Bacarisse wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sun, 18 Feb 2024 22:34:06 +0000, Ben Bacarisse wrote:

    ... brackets, orders ...

    “Of” (implied multiplication), not “orders”.

    You may have been taught that (why?) but an online search suggests that
    that is not what gets taught.

    I’m not sure why. Given that exponentiation is conventionally denoted by placement, e.g.

    b + c
    a

    there cannot possibly be any ambiguity about how the binding is supposed
    to work. Unlike, for example, this case:

    a ÷ b(c + d)

    versus

    a ÷ b × (c + d)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Lawrence D'Oliveiro on Mon Feb 19 00:39:00 2024
    On 2/18/24 17:23, Lawrence D'Oliveiro wrote:
    On Sun, 18 Feb 2024 15:59:28 +0100, David Brown wrote:

    It could well be a surprise to non-experts that there is a function
    "hypot" in the C library, rather than just writing "sqrt(x*x + y*y)".

    What kind of programmer is it, that it would be so easy to surprise them
    just by pointing out something in the documentation?

    A fairly normal one, in my experience. Few programmers have the standard memorized, certainly not me. I am sufficiently familiar with it to know
    where to go looking if I have a question, but even that level of
    familiarity is rare. In particular, there's lots of programmers not particularly interested in or familiar with the math library. Most of
    those would consider hypot() an obscure function. I was working on a
    NASA contract on scientific software when I introduced hypot() into a
    function, and at least half the people who reviewed the code needed to
    be reminded what it does.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Malcolm McLean on Mon Feb 19 05:19:26 2024
    On Mon, 19 Feb 2024 02:20:22 +0000, Malcolm McLean wrote:

    On 18/02/2024 23:38, Lawrence D'Oliveiro wrote:

    On Sun, 18 Feb 2024 23:53:39 +0100, David Brown wrote:

    If you need an efficient way to calculate such hypotenuses, the
    function "hypot" will get you /into/ trouble.

    Tip: something that programmers *do* frequently find surprising is that
    their intuitions over which parts of their code to optimize and which
    ones not to are all too frequently wrong.

    I rarely find that with C. Usually each statement or operator compiles
    to a single machine instruction.

    It’s not the number of instructions that’s the issue, but the time taken
    to execute them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Mon Feb 19 08:58:46 2024
    On 19/02/2024 03:26, Malcolm McLean wrote:
    Our maths teacher was Selby Brock (a
    brilliant man who taught that the earth was flat),

    Isn't that somewhat of an oxymoron? I had one primary teacher that
    taught that there were 10 planets (Pluto was still called a planet at
    the time, and he counted the sun as a planet) and another that did not
    consider the sun to be a star or the earth to be a planet. But these
    were /not/ good teachers.

    It's conceivable that this person was a good teacher of maths, but
    that's different from being a good teacher in general.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Richard Harnden on Mon Feb 19 09:00:58 2024
    On 19/02/2024 00:06, Richard Harnden wrote:
    On 18/02/2024 22:34, Ben Bacarisse wrote:

    [BODMAS]


    I've always seen it rendered as "orders".  I think "indexes" is better,
    but it does not fix the basic problem.

    And, for the record, I was never taught it.


    Just curious - Were you taught SOHCAHTOA for trig?  I always found that
    easy to remember.


    I remember one teacher using that phrase. I didn't see the point, but I
    was already quite happy with basic trig by then.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Mon Feb 19 09:29:19 2024
    On 19/02/2024 06:17, Lawrence D'Oliveiro wrote:
    On Mon, 19 Feb 2024 02:14:43 +0000, Ben Bacarisse wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    On Sun, 18 Feb 2024 22:34:06 +0000, Ben Bacarisse wrote:

    ... brackets, orders ...

    “Of” (implied multiplication), not “orders”.

    You may have been taught that (why?) but an online search suggests that
    that is not what gets taught.

    I’m not sure why. Given that exponentiation is conventionally denoted by placement, e.g.

    b + c
    a

    there cannot possibly be any ambiguity about how the binding is supposed
    to work.


    I think you underestimate the ability of schoolkids to get things wrong!
    ab² could easily be misinterpreted as (ab)².

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Mon Feb 19 09:36:20 2024
    On 19/02/2024 00:38, Lawrence D'Oliveiro wrote:
    On Sun, 18 Feb 2024 23:53:39 +0100, David Brown wrote:

    If you need an efficient way to calculate such hypotenuses, the function
    "hypot" will get you /into/ trouble.

    Tip: something that programmers *do* frequently find surprising is that
    their intuitions over which parts of their code to optimize and which ones not to are all too frequently wrong.

    That is absolutely true.

    And they also regularly misunderstand what actually affects the speed of
    their code. This is particularly true for "big" systems, where a single
    cache miss can make as much difference as many dozens of instructions,
    and where pipelining, scheduling and out-of-order execution makes it
    very difficult to figure out the real bottlenecks.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Mon Feb 19 09:50:49 2024
    On 19/02/2024 00:39, Lawrence D'Oliveiro wrote:
    On Sun, 18 Feb 2024 16:14:23 +0100, David Brown wrote:

    My claim is that no one would feel the need to add "/*if*/" comments to
    closing brackets unless they felt the code was not clearly
    comprehensible without such comments. I am saying that /you/ write
    /your/ code as though /you/ think your own code is hard to comprehend.

    No, you originally said “... if you need to do that with your "if" statements, your style is an incomprehensible mess”. So the “incomprehensible mess” nonsense is *your* claim, not mine, and *you* are the one who needs to back it up, not me.

    I have explained what I meant, and given my reasoning. If you don't
    understand that, or don't like it, feel free to ignore it.

    (Note that I did not say your style is an incomprehensible mess. I said
    /if/ you need these comments, it is a mess. But I don't know if you
    feel you /need/ these comments, or if you generally use them - I would
    assume the post with the "histogram" function was not a realistic
    example of your normal coding style.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Janis Papanagnou on Mon Feb 19 10:15:26 2024
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 18.02.2024 22:07, Ben Bacarisse wrote:

    The replies to your tendentious advice seem to be vying for maximum
    obfuscation. This should not written as a 'for' loop at all; it's a
    natural 'while' loop:

    Yes, but the original post contained an specific for() based example
    and the topic was about local declaration not about the best control construct.

    Oh. It seemed like you were suggesting an improvement to the posted
    code.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Malcolm McLean on Mon Feb 19 15:15:36 2024
    Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
    On 18/02/2024 23:38, Lawrence D'Oliveiro wrote:
    On Sun, 18 Feb 2024 23:53:39 +0100, David Brown wrote:

    If you need an efficient way to calculate such hypotenuses, the function >>> "hypot" will get you /into/ trouble.

    Tip: something that programmers *do* frequently find surprising is that
    their intuitions over which parts of their code to optimize and which ones >> not to are all too frequently wrong.

    I rarely find that with C. Usually each statement or operator compiles
    to a single machine instruction.

    You must not look at the output of compiled C very often if
    those are your observations. Setting up the arguments for
    a function call, for example. Switch statements. Loops.

    Try 'objdump -dS' sometime.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Mon Feb 19 16:18:30 2024
    On 19.02.2024 06:17, Lawrence D'Oliveiro wrote:

    I’m not sure why. Given that exponentiation is conventionally denoted by placement, e.g.

    b + c
    a

    there cannot possibly be any ambiguity about how the binding is supposed
    to work.

    It is relevant, e.g. in 4^3^2 which is 4^(3^2) and not (4^3)^2
    (when "placement" is the representation in writings), and in computer
    formulas it's anyway relevant when everything is on one line.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Malcolm McLean on Mon Feb 19 16:28:29 2024
    On 19/02/2024 15:21, Malcolm McLean wrote:
    On 19/02/2024 07:58, David Brown wrote:
    On 19/02/2024 03:26, Malcolm McLean wrote:
    Our maths teacher was Selby Brock (a brilliant man who taught that
    the earth was flat),

    Isn't that somewhat of an oxymoron?  I had one primary teacher that
    taught that there were 10 planets (Pluto was still called a planet at
    the time, and he counted the sun as a planet) and another that did not
    consider the sun to be a star or the earth to be a planet.  But these
    were /not/ good teachers.

    It's conceivable that this person was a good teacher of maths, but
    that's different from being a good teacher in general.

    Come on. Some respect and some intelligence. If I say he was a brilliant
    man I wouldn't say that lightly, and he had very good reasons for
    teaching that the Earth was flat. It was nonsense, everyone knew it was nonsense, but no boy ever actually managed to prove that it was
    nonsense, and that was the point.

    It's fine to challenge pupils to prove that the earth is not flat, and
    to force them to think about things that they take for granted. But
    that's not what you said he did.

    There are teachers who hold all kinds of weird and nonsensical beliefs,
    just as in many other areas of life. People can believe what they want
    - freedom of religion is important. But what they /teach/, or how they otherwise interact with people that they have power or authority over,
    is a different matter.

    There are surely good teachers out there that believe the earth is flat.
    But if they teach it, they are not good teachers - and that's what you
    said this guy did.

    And if he is just trying to challenge the kids to justify their
    conviction that the earth is not flat, and he left them unable to prove
    their claims, then he is still bad. Now the kids are left confused -
    they don't know whether they are wrong to think the earth is round, or
    whether it is something that everyone believes without proof and that
    it's okay to believe things because simply because lots of other people
    believe them.


    But it perfectly justified "Selby always teaches crap".


    For the sake of that guy's reputation, I'll assume you are right that he
    was a good teacher - but it is not what you said.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Janis Papanagnou on Mon Feb 19 17:55:22 2024
    On 19.02.2024 16:18, Janis Papanagnou wrote:
    On 19.02.2024 06:17, Lawrence D'Oliveiro wrote:

    I’m not sure why. Given that exponentiation is conventionally denoted by >> placement, e.g.

    b + c
    a

    there cannot possibly be any ambiguity about how the binding is supposed
    to work.

    It is relevant, e.g. in 4^3^2 which is 4^(3^2) and not (4^3)^2

    I just noticed that my newsreader (and probably also other newsreaders) replaced the expression partially and might obfuscate the point I made.

    The expressions were: 4 caret 4 caret 2
    and: 4 caret ( 4 caret 2 )
    and: ( 4 caret 4 ) caret 2

    where "caret" is meant to be the exponentiation operator.

    (when "placement" is the representation in writings), and in computer formulas it's anyway relevant when everything is on one line.

    Janis


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Malcolm McLean on Mon Feb 19 17:48:43 2024
    On 19.02.2024 08:54, Malcolm McLean wrote:
    On 19/02/2024 04:14, Janis Papanagnou wrote:

    BTW; a mistake of mine was to write inaccurately "C with the two
    parenthesis syntaxes"; it was, I think, C++ that added the second
    form that made it possible that a cast looks like a function call.
    Frankly, I don't know whether C also added that.

    Is a constructor a cast?

    That was something I pondered about when I programmed C++ in the 1990's.

    But above, it was not (not primarily) meant when using own classes, but
    with bascis types; as in (int)x vs. int(x) .

    My question was about newer C standards supporting the second form;
    a quick test shows that C++ (of course) does, but my C version doesn't.
    But I (still) don't know about the current C standards.


    We have a class called "fixed" which represents reals in binary using a
    fixed binary point. So obviously we shall write a constructor for it so
    we can easily and conviently obtain values like "0.5", which shall take
    a double. And if we all it exlicitly it's

    fixed x;

    x = fixed(0.5);

    and to all intents and purposes we've just cast a double to a fixed.

    And in fact

    x = (fixed) 0.5;

    will call the same constructor.

    Sure.

    (But wouldn't x = 0.5; have also used your constructor, unless
    explicitly prohibited by its definition?)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to David Brown on Mon Feb 19 18:09:27 2024
    On 19.02.2024 16:28, David Brown wrote:

    There are teachers who hold all kinds of weird and nonsensical beliefs,
    just as in many other areas of life. People can believe what they want
    - freedom of religion is important. But what they /teach/, or how they otherwise interact with people that they have power or authority over,
    is a different matter.

    It gets really bad in societies where teachers are forced to teach
    against all reasons, and some (even basic) knowledges just banned.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Keith Thompson on Mon Feb 19 18:14:08 2024
    On 19.02.2024 17:58, Keith Thompson wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    (int)x vs. int(x)

    My question was about newer C standards supporting the second form;
    a quick test shows that C++ (of course) does, but my C version doesn't.
    But I (still) don't know about the current C standards.

    C does not support C++-style int(x) casts in any version up to and
    including C23. The only form of cast in C is (type-name) expression.

    Thanks.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mike Terry@21:1/5 to Mike Terry on Mon Feb 19 19:21:17 2024
    On 19/02/2024 00:06, Mike Terry wrote:
    On 18/02/2024 23:06, Richard Harnden wrote:
    On 18/02/2024 22:34, Ben Bacarisse wrote:

    [BODMAS]


    I've always seen it rendered as "orders". I think "indexes" is better,
    but it does not fix the basic problem.

    And, for the record, I was never taught it.


    Just curious - Were you taught SOHCAHTOA for trig? I always found that easy to remember.


    Never heard that one - is it thought of as one long word??

    Just as we're on the subject, a friend of mine at high school was pleased with himself for inventing
    what might be the most useless maths mnemonic ever:

    Smelly Armpits Cause Termites

    ok, it's memorable for sure, no problem on that front! But I was baffled why he thought it
    important to have a mnemonic for what it explains. (Plus it's hardly logical (mathematically) even
    if you know what it's explaining!)

    ob. Puzzle - what was his mnemonic helping him remember? [hint: it's trig related]


    In case anyone was curious...

    |
    |
    Cause | Armpits
    |
    |
    --------------+--------------
    |
    |
    Termites | Smelly
    |
    |

    Reminding us of:

    |
    |
    Cosine | All
    |
    |
    --------------+--------------
    |
    |
    Tangent | Sine
    |
    |

    That's right, it's helping us remember which trig functions are positive in each of the four quadrants!

    Um, don't ask....! :)


    Mike.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Mike Terry on Tue Feb 20 00:05:56 2024
    Mike Terry <news.dead.person.stones@darjeeling.plus.com> writes:

    In case anyone was curious...

    |
    |
    Cause | Armpits
    |
    |
    --------------+--------------
    |
    |
    Termites | Smelly
    |
    |

    Reminding us of:

    |
    |
    Cosine | All
    |
    |
    --------------+--------------
    |
    |
    Tangent | Sine
    |
    |

    That's right, it's helping us remember which trig functions are
    positive in each of the four quadrants!

    Um, don't ask....! :)

    Your example shows why I never liked this sort of "help". Remembering
    where to start and what order to label the quadrants is harder (for me)
    than knowing how trig functions work.

    Now, can we find a good mnemonic for C's operator precedence levels?
    Extra credit if left/right associativity is also covered. (Few! On
    topic again.)

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Malcolm McLean on Tue Feb 20 01:31:59 2024
    On Mon, 19 Feb 2024 07:54:15 +0000, Malcolm McLean wrote:

    Is a constructor a cast?

    One thing should be clear: there should not be any confusion between safe
    and unsafe type conversions.

    In Modula-2, for unsafe conversions you had CAST(«type», «expr»), which
    you had to import from SYSTEM before you could use it. So it was easy to
    scan through the code to find instances of its use.

    In C++, you have const_cast and reinterpret_cast, which while they don’t
    need to be imported from anywhere, are still sufficiently distinctive
    names.

    The C syntax is very difficult to search for. And of course it mixes up
    both safe (e.g. int⟷float) and unsafe conversions in the same syntax, so checking for the latter becomes doubly hard.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Tue Feb 20 01:33:23 2024
    On Mon, 19 Feb 2024 09:29:19 +0100, David Brown wrote:

    I think you underestimate the ability of schoolkids to get things wrong!
    ab² could easily be misinterpreted as (ab)².

    Ah. That’s a point.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to James Kuyper on Tue Feb 20 01:35:55 2024
    On Mon, 19 Feb 2024 00:39:00 -0500, James Kuyper wrote:

    In particular, there's lots of programmers not
    particularly interested in or familiar with the math library. Most of
    those would consider hypot() an obscure function. I was working on a
    NASA contract on scientific software when I introduced hypot() into a function, and at least half the people who reviewed the code needed to
    be reminded what it does.

    Interesting that they would be qualified to review maths-intensive code, without having to be familiar with the maths library.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Tue Feb 20 01:34:14 2024
    On Mon, 19 Feb 2024 16:18:30 +0100, Janis Papanagnou wrote:

    On 19.02.2024 06:17, Lawrence D'Oliveiro wrote:

    there cannot possibly be any ambiguity about how the binding is
    supposed to work.

    It is relevant, e.g. in 4^3^2 which is 4^(3^2) and not (4^3)^2 ...

    That has to do with left- versus right-associativity, not operator
    precedence as such. After all, an operator has the same precedence as
    itself.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Ben Bacarisse on Tue Feb 20 01:37:02 2024
    On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:

    Now, can we find a good mnemonic for C's operator precedence levels?

    “RTFM”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Mon Feb 19 17:58:26 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    [...]

    In this particular case, I'd just use 0. If for some reason I
    needed to make it explicitly of type uint64_t (say, for an
    argument to a variadic function), I'd write `(uint64_t)0`.

    Ick. At least write '(uint64_t){ 0 }' rather than casting.

    Why?

    Casts are dangerous. Besides being dangerous, in many cases
    casts are accidents waiting to happen. Writing casts at the drop
    of a hat is a bad habit. A good programming practice is to avoid
    using a cast whenever feasible. Using a compound literal isn't a
    lot better than just a raw cast, but it does at least provide a
    little extra safety because it allows only "safe" conversions.
    Seeing a cast in open code should always raise a red flag,
    especially when, as in this case, it's easy to find a safer
    alternative.

    I disagree in this case. Yes, casts certainly can be dangerous,
    especially those involving pointers, and I'd say that all casts
    should be looked on with some suspicion. But anyone who knows C
    can recognize that casting a constant 0 to an integer type is not
    in any way dangerous.

    It's easier on readers if casts are used only in situations where
    they are really necessary. Of course any competent C programmer
    can realize with only a small effort that a cast of 0 to an integer
    type is safe, but it's better not to have to make the effort at
    all. That way whenever a cast is encountered we immediately know
    that we are in a potentially dangerous situation, without having
    to expend any effort deciding if the cast is "trivial" or not.

    Easy writing makes hard reading, and vice versa.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Ben Bacarisse on Mon Feb 19 18:19:48 2024
    Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

    [...]

    Now, can we find a good mnemonic for C's operator precedence levels?
    Extra credit if left/right associativity is also covered.

    Let me ask, which areas give people the most trouble, or where do
    they find that they need help remembering? My reason for asking is
    I myself find most of C's expression syntax behaves the way I expect
    without having to think about it, so I need relatively few memory
    aids to feel confident in knowing the whole stack. But what are the
    stumbling blocks for other folks?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Mike Terry on Tue Feb 20 02:43:00 2024
    On 2024-02-19, Mike Terry <news.dead.person.stones@darjeeling.plus.com> wrote:
    In case anyone was curious...

    |
    |
    Cause | Armpits
    |
    |
    --------------+--------------
    |
    |
    Termites | Smelly
    |
    |

    I learned

    crazy all

    teachers are science

    from a math teacher who was Scottish. Someone in the class piped up
    with "all Scottish teachers are crazy", to great laughter.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to David Brown on Tue Feb 20 01:45:54 2024
    On Mon, 19 Feb 2024 09:50:49 +0100, David Brown wrote:

    On 19/02/2024 00:39, Lawrence D'Oliveiro wrote:

    On Sun, 18 Feb 2024 16:14:23 +0100, David Brown wrote:

    My claim is that no one would feel the need to add "/*if*/" comments
    to closing brackets unless they felt the code was not clearly
    comprehensible without such comments. I am saying that /you/ write
    /your/ code as though /you/ think your own code is hard to comprehend.

    No, you originally said “... if you need to do that with your "if"
    statements, your style is an incomprehensible mess”. So the
    “incomprehensible mess” nonsense is *your* claim, not mine, and *you*
    are the one who needs to back it up, not me.

    I have explained what I meant, and given my reasoning. If you don't understand that, or don't like it, feel free to ignore it.

    I interpreted all that as attempts to say something different from what
    you originally said.

    (Note that I did not say your style is an incomprehensible mess. I said
    /if/ you need these comments, it is a mess.

    Obviously you seem to think my code is an “incomprehensible mess” with those comments, and possibly even without. But you still haven’t explained why.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Ben Bacarisse on Tue Feb 20 09:06:25 2024
    On 20/02/2024 01:05, Ben Bacarisse wrote:
    Mike Terry <news.dead.person.stones@darjeeling.plus.com> writes:



    Your example shows why I never liked this sort of "help". Remembering
    where to start and what order to label the quadrants is harder (for me)
    than knowing how trig functions work.


    Same for me. The trick to getting the signs of sins right is to think
    of circles, not triangles, when doing trig. Then it is all completely
    obvious.

    Now, can we find a good mnemonic for C's operator precedence levels?
    Extra credit if left/right associativity is also covered. (Few! On
    topic again.)


    People Pick Unix 'Cause Make And Bake 'Re Easy ....

    Primary, Postfix, Unary, Cast, Multiplicative, Additive, Bitwise shift, Relational, Equality ...

    I haven't got to the bitwise operators yet!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Tue Feb 20 09:26:47 2024
    On 20/02/2024 02:31, Lawrence D'Oliveiro wrote:
    On Mon, 19 Feb 2024 07:54:15 +0000, Malcolm McLean wrote:

    Is a constructor a cast?

    One thing should be clear: there should not be any confusion between safe
    and unsafe type conversions.

    In Modula-2, for unsafe conversions you had CAST(«type», «expr»), which you had to import from SYSTEM before you could use it. So it was easy to
    scan through the code to find instances of its use.

    In C++, you have const_cast and reinterpret_cast, which while they don’t need to be imported from anywhere, are still sufficiently distinctive
    names.

    The C syntax is very difficult to search for. And of course it mixes up
    both safe (e.g. int⟷float) and unsafe conversions in the same syntax, so checking for the latter becomes doubly hard.

    I am not sure what distinction you are making between "safe" and
    "unsafe" casts, and I suspect that different people would draw such a
    line in different places. "safe" or "unsafe" is in the usage, not just
    the cast expression itself. The same applies to implicit conversions -
    writing "int x = 1e30;" is far from "safe".

    A cast in C is just an explicit conversion. Sometimes it is better to
    be explicit rather than implicit. (One of the reasons for C++'s
    different cast operators is to be explicit about what kind of cast you
    are using at the time.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Lawrence D'Oliveiro on Tue Feb 20 03:32:19 2024
    On 2/19/24 20:37, Lawrence D'Oliveiro wrote:
    On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:

    Now, can we find a good mnemonic for C's operator precedence levels?

    “RTFM”.

    The standard doesn't describe operator precedence levels. It provides
    grammar rules, and precedence must be inferred from the grammar. I've
    found that it is not widely understood how to infer precedence from the grammar. A shortcut you can use is the fact that the relevant section is organized in order of decreasing precedence, but you have to know the precedence to realize that - the standard doesn't mention that fact.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Lawrence D'Oliveiro on Tue Feb 20 03:18:22 2024
    On 2/19/24 20:35, Lawrence D'Oliveiro wrote:
    On Mon, 19 Feb 2024 00:39:00 -0500, James Kuyper wrote:

    In particular, there's lots of programmers not
    particularly interested in or familiar with the math library. Most of
    those would consider hypot() an obscure function. I was working on a
    NASA contract on scientific software when I introduced hypot() into a
    function, and at least half the people who reviewed the code needed to
    be reminded what it does.

    Interesting that they would be qualified to review maths-intensive code, without having to be familiar with the maths library.

    They were very familiar with the commonly used math functions, and in particular the ones that had long been part of the C library. Keep in
    mind that hypot() was added in C99, which was slow to be adopted. The
    changes to the math library were extensive, and technical, as a result
    of which they were among the last parts of C99 to be widely adopted. At
    the time I'm remembering, C99 was only about 10 years old.
    Also, NASA is a conservative organization - you might think that they concentrate on cutting edge technology, but they also has a strong
    preference for reliability - it's hard to do maintenance on a device
    once it's been launched. At that time we were still bound by a contract
    with NASA that required that we deliver code that conformed to C90 plus
    the 1994 amendments. The only reason I was permitted to use hypot() was
    that this was purely internal code, not delivered code.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Kaz Kylheku on Tue Feb 20 11:02:53 2024
    Kaz Kylheku <433-929-6894@kylheku.com> writes:

    On 2024-02-19, Mike Terry <news.dead.person.stones@darjeeling.plus.com> wrote:
    In case anyone was curious...

    |
    |
    Cause | Armpits
    |
    |
    --------------+--------------
    |
    |
    Termites | Smelly
    |
    |

    I learned

    crazy all

    teachers are science

    from a math teacher who was Scottish. Someone in the class piped up
    with "all Scottish teachers are crazy", to great laughter.

    I don't think it worked! I was maybe too subtle in my last post, but
    you have to remember something entirely arbitrary with this sort of
    thing -- where to start and the order of going round (or otherwise
    naming) the quadrants. All the posted examples I've see have the C and
    S quadrants swapped over.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Ben Bacarisse on Tue Feb 20 13:03:32 2024
    On 20/02/2024 12:20, Ben Bacarisse wrote:
    David Brown <david.brown@hesbynett.no> writes:

    On 20/02/2024 01:05, Ben Bacarisse wrote:
    Mike Terry <news.dead.person.stones@darjeeling.plus.com> writes:


    Your example shows why I never liked this sort of "help". Remembering
    where to start and what order to label the quadrants is harder (for me)
    than knowing how trig functions work.


    Same for me. The trick to getting the signs of sins right is to think of
    circles, not triangles, when doing trig. Then it is all completely
    obvious.

    Now, can we find a good mnemonic for C's operator precedence levels?
    Extra credit if left/right associativity is also covered. (Few! On
    topic again.)


    People Pick Unix 'Cause Make And Bake 'Re Easy ....

    Primary, Postfix, Unary, Cast, Multiplicative, Additive, Bitwise shift,
    Relational, Equality ...

    A valiant effort, but why is cast singled out and put after other unary operators? Also B (=Bitwise) for shift when there are so many bit-wise operators? It would be better if "sh" were in the mnemonic there as in
    "make and shell"?


    It was not a very serious effort! The letters are simply the start of
    the titles of the sub-sections in section 6.5 - thus "Cast" comes after
    "Unary" because "6.5.4 Cast operators" comes after "6.5.3 Unary operators".

    I haven't got to the bitwise operators yet!

    They, of course, are the ones that trip people up since they have unexpectedly odd precedence due to their use in B as the sole way to get logical connectives. I happened to learn B before C, so that was not so
    hard for me to internalise.


    Yes, I know. And IMHO the correct way to handle this is parentheses
    when the expression is not immediately clear with minimal cognitive
    effort to a wide range of C programmers, rather than trying to find a
    way to make the precedences easier to remember. So as I see it, this is
    just a bit of fun and a word challenge. But I could not think of a continuation with letters B, B, B, L, L, C, A, C.

    For me, pretty much the only one I'd have to look up (though only in a
    year or two, since I've recently been reminded!) is ^ vs |.


    I think that if I were to close all references and try to write down all
    the operators in precedence order, I'd need to think hard about some of
    them, but probably get them right in the end - except guesswork for
    those two.

    I always prefer to write my code in a way where I do not have to think
    hard about it to be sure of what it means.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to David Brown on Tue Feb 20 11:20:46 2024
    David Brown <david.brown@hesbynett.no> writes:

    On 20/02/2024 01:05, Ben Bacarisse wrote:
    Mike Terry <news.dead.person.stones@darjeeling.plus.com> writes:


    Your example shows why I never liked this sort of "help". Remembering
    where to start and what order to label the quadrants is harder (for me)
    than knowing how trig functions work.


    Same for me. The trick to getting the signs of sins right is to think of circles, not triangles, when doing trig. Then it is all completely
    obvious.

    Now, can we find a good mnemonic for C's operator precedence levels?
    Extra credit if left/right associativity is also covered. (Few! On
    topic again.)


    People Pick Unix 'Cause Make And Bake 'Re Easy ....

    Primary, Postfix, Unary, Cast, Multiplicative, Additive, Bitwise shift, Relational, Equality ...

    A valiant effort, but why is cast singled out and put after other unary operators? Also B (=Bitwise) for shift when there are so many bit-wise operators? It would be better if "sh" were in the mnemonic there as in
    "make and shell"?

    I haven't got to the bitwise operators yet!

    They, of course, are the ones that trip people up since they have
    unexpectedly odd precedence due to their use in B as the sole way to get logical connectives. I happened to learn B before C, so that was not so
    hard for me to internalise.

    For me, pretty much the only one I'd have to look up (though only in a
    year or two, since I've recently been reminded!) is ^ vs |.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Tue Feb 20 16:19:55 2024
    On 20.02.2024 02:37, Lawrence D'Oliveiro wrote:
    On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:

    Now, can we find a good mnemonic for C's operator precedence levels?

    “RTFM”.

    LOL! :-)

    But I think Ben's idea is anyway interesting.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Ben Bacarisse on Tue Feb 20 16:32:25 2024
    On 20.02.2024 12:02, Ben Bacarisse wrote:
    Kaz Kylheku <433-929-6894@kylheku.com> writes:

    On 2024-02-19, Mike Terry <news.dead.person.stones@darjeeling.plus.com> wrote:
    In case anyone was curious...

    |
    |
    Cause | Armpits
    |
    |
    --------------+--------------
    |
    |
    Termites | Smelly
    |
    |

    I learned

    crazy all

    teachers are science

    from a math teacher who was Scottish. Someone in the class piped up
    with "all Scottish teachers are crazy", to great laughter.

    I don't think it worked! I was maybe too subtle in my last post, but
    you have to remember something entirely arbitrary with this sort of
    thing -- where to start and the order of going round (or otherwise
    naming) the quadrants. All the posted examples I've see have the C and
    S quadrants swapped over.

    I like (and certainly easily memorize) "All Scottish Teachers [are]
    Crazy", and starting in Q1 with clockwise orientation seems fine to
    me (even if the quadrants are usually numbered counterclockwise).

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to James Kuyper on Tue Feb 20 17:06:13 2024
    On 2024-02-20, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 2/19/24 20:37, Lawrence D'Oliveiro wrote:
    On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:

    Now, can we find a good mnemonic for C's operator precedence levels?

    “RTFM”.

    The standard doesn't describe operator precedence levels. It provides
    grammar rules, and precedence must be inferred from the grammar. I've
    found that it is not widely understood how to infer precedence from the grammar.

    Really? But it's dead trivial.

    The parent production has lower precedence than the child; e.g.

    additive_expression '+' multiplicative_expression.

    The '+' has precedence over '*' and '/' because the
    multiplicative_expression is an indivisible symbol in the
    additive_expression rule. The rule does not "see" the multiplicative
    symbols at all, but a multiplicative_expression phrasal unit.

    That's basically it.

    I suppose if you don't know a grammar from a hammer, this might
    not click.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Ben Bacarisse on Tue Feb 20 17:12:55 2024
    On 2024-02-20, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
    Kaz Kylheku <433-929-6894@kylheku.com> writes:

    On 2024-02-19, Mike Terry <news.dead.person.stones@darjeeling.plus.com> wrote:
    In case anyone was curious...

    |
    |
    Cause | Armpits
    |
    |
    --------------+--------------
    |
    |
    Termites | Smelly
    |
    |

    I learned

    crazy all

    teachers are science

    from a math teacher who was Scottish. Someone in the class piped up
    with "all Scottish teachers are crazy", to great laughter.

    I don't think it worked! I was maybe too subtle in my last post, but
    you have to remember something entirely arbitrary with this sort of
    thing -- where to start and the order of going round (or otherwise
    naming) the quadrants. All the posted examples I've see have the C and
    S quadrants swapped over.

    Like a Chat AI robot, I just followed my interlocutor's example,
    and pretended it's right.

    For a moment, I wondered why the words are going clockwise (negative
    rotation) but didn't give it a moment's thought beyond that.

    Part of the value of the "all science teachers are crazy" mnemonic is
    that it starts with the first quadrant and follows the positive angle.

    You will not get it wrong, unless you're preloaded with a wrong example
    and don't think about it.

    If you think about it for a millisecond, of course sin() is positive
    over the first 180 degrees, but since cos() starts high, that
    function drops and crosses zero at 90. If you know this simple
    thing, you don't need the mnemonic.


    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Kaz Kylheku on Tue Feb 20 12:37:20 2024
    On 2/20/24 12:06, Kaz Kylheku wrote:
    On 2024-02-20, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 2/19/24 20:37, Lawrence D'Oliveiro wrote:
    On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:

    Now, can we find a good mnemonic for C's operator precedence levels?

    “RTFM”.

    The standard doesn't describe operator precedence levels. It provides
    grammar rules, and precedence must be inferred from the grammar. I've
    found that it is not widely understood how to infer precedence from the
    grammar.

    Really? But it's dead trivial.

    The parent production has lower precedence than the child; e.g.

    additive_expression '+' multiplicative_expression.

    The '+' has precedence over '*' and '/' because the
    multiplicative_expression is an indivisible symbol in the
    additive_expression rule. The rule does not "see" the multiplicative
    symbols at all, but a multiplicative_expression phrasal unit.

    That's basically it.

    I have no trouble with it, but I've seen other people have trouble. And
    of course, it gets particularly tricky with regard to a few special cases:

    primary-expression:
    ( expression )

    generic-selection:
    _Generic ( assignment-expression , generic-assoc-list )

    postfix-expression:
    postfix-expression [ expression ]

    conditional-expression:
    logical-OR-expression ? expression : conditional-expression

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Tim Rentsch on Tue Feb 20 17:20:00 2024
    On 20/02/2024 02:19, Tim Rentsch wrote:
    Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

    [...]

    Now, can we find a good mnemonic for C's operator precedence levels?
    Extra credit if left/right associativity is also covered.

    Let me ask, which areas give people the most trouble, or where do
    they find that they need help remembering? My reason for asking is
    I myself find most of C's expression syntax behaves the way I expect
    without having to think about it, so I need relatively few memory
    aids to feel confident in knowing the whole stack. But what are the stumbling blocks for other folks?


    I like to intuitively think of binary operators as belonging to three
    groups:

    (1) Within expressions (arithmetic, but also bitwise ops)

    (2) Comparisons (with one precedence level)

    (3) Logical and/or (only 2 precedence levels)

    All (1) have higher precendence than (2), which are higher than (3). (In
    my code, groups (2) and (3) mostly occur in conditional expressions such
    as 'f (expr)'.)

    C mixes up some operators between (1) and (2), that's one thing.
    For example, ^ is bizarrely lower precedence than ==.

    Even within the same group (1), I think of << and >> as scaling
    operators of the same rank as * and /, since they really do the same job
    (any shift can be implemented with multiple or divide by a power of two).

    Yet C puts the precedence of << and >> the other side of + and -. This
    means that:

    1 << 2 + 3

    is 1<<(2+3) or 32, not (1<<2)+3 or 7.

    Another one is ?: as in:

    a ? b ? c : d : e // or:
    a ? b : c ? d : e

    With more complex terms, it's easy to get lost. Although this one is not
    so much about precedence; I wouldn't class it as an operator all, and
    would insist on parentheses so that the boundaries of this 3-way
    construct are absolutely clear.

    With parentheses, I /believe/ the correct grouping that corrresponds is repectively:

    (a ? (b ? c : d) : e)
    (a ? b : (c ? d : e))

    Now I can change 'I believe' to 'I know'.

    Remember this is not just about working with C. People may work on
    different languages with their own rules.

    `2 + 3 * 4` is near-universally evaluated as 14. With `1 << 2 + 3` most languages I managed to try on rextester.com (which supported infix
    `<<`), also gave C's result of 32.

    This means a lot of languages that have perpetuated C's bad choices.

    A few languages however did not just blindly follow C, such as Pascal,
    Go and Swift; those gave a result of 7.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to bart on Tue Feb 20 18:14:42 2024
    On 2024-02-20, bart <bc@freeuk.com> wrote:
    C mixes up some operators between (1) and (2), that's one thing.
    For example, ^ is bizarrely lower precedence than ==.

    Yes, this is an ancient mistake that was acknowledged by D. Ritchie
    decades ago.

    It's an unfortunate thing that is hard to change.

    The most harm that came out of it is, I think, not the programming
    bugs, but the endless debate.

    It's not impossible to change. Basically first we would have to
    mark the current precedence deprecated, and require a diagnostic
    for programw which rely on it.

    For instance the expression a == b & c == d would require a diagnostic,
    similar to the optional one can obtain get anyway from some popular
    compilers.

    Then, after a long period of obsolescence and diagnosis, perhaps 25
    years or more, new rules could be put in. a == b & c == d would not
    longer require a diagnostic, but silently parse as (a == (b & c)) == d.

    IMO, it would have been a good idea had ANSI C 89 taken the above
    obsolescence step. By C11, if not C99, we could have been rid of the
    precedence infelicities.

    The problem with requiring a diagnostic is that the standard doesn't distinguish errors and warnings. A program which requires a diagnostic
    is erroneous. If it is translated and executed anyway, its behavior is undefined.

    You can't say that a == b & c == d is correct, and parses as (a == b ) &
    (c == d), while at the same time demanding a diagnostic. That's
    contradictory: if it requires a diagnostic, it is incorrect.

    The standard would have to sharpen its knife and introduce the concept
    of informational diagnostics which don't indicate an incorrect
    situation, but only some deprecated situation.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to James Kuyper on Tue Feb 20 19:29:06 2024
    On 2024-02-20, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 2/20/24 12:06, Kaz Kylheku wrote:
    On 2024-02-20, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 2/19/24 20:37, Lawrence D'Oliveiro wrote:
    On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:

    Now, can we find a good mnemonic for C's operator precedence levels?

    “RTFM”.

    The standard doesn't describe operator precedence levels. It provides
    grammar rules, and precedence must be inferred from the grammar. I've
    found that it is not widely understood how to infer precedence from the
    grammar.

    Really? But it's dead trivial.

    The parent production has lower precedence than the child; e.g.

    additive_expression '+' multiplicative_expression.

    The '+' has precedence over '*' and '/' because the
    multiplicative_expression is an indivisible symbol in the
    additive_expression rule. The rule does not "see" the multiplicative
    symbols at all, but a multiplicative_expression phrasal unit.

    That's basically it.

    I have no trouble with it, but I've seen other people have trouble. And
    of course, it gets particularly tricky with regard to a few special cases:

    primary-expression:
    ( expression )

    Here since the right hand side is flanked by terminal symbols, and no
    other grammar symbols, there is no precedence issue to be seen.
    No operator occurs outside of the expression.

    postfix-expression:
    postfix-expression [ expression ]

    This is at tricky case where we have to understand that the left
    recursion in the grammar gives us left associativity:

    postfix
    / \
    postfix [ expr ]
    / \
    postfix [ expr ]

    so that a[0][0][0] means ((a[0])[1])[0]

    conditional-expression:
    logical-OR-expression ? expression : conditional-expression

    The intuition is that the ? : nonterminals act as parentheses
    around the inner expression, shielding it from issues of
    precedence relative to the other expressions.

    Assuming the syntax is good, we can determine what part of the
    input comprises the inner "expression" just by finding the closing :
    which matches the opening ?, whereby we count balancing parentheses
    and ? : pairs.

    The pieces outside ? : are units: a logical-OR-expression will not
    fragment into pieces, one of which binds to ?: so we know
    that the OR operator has higher precedence.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Keith Thompson on Tue Feb 20 19:39:05 2024
    On 20/02/2024 17:46, Keith Thompson wrote:
    bart <bc@freeuk.com> writes:
    [...]
    I like to intuitively think of binary operators as belonging to three
    groups:

    (1) Within expressions (arithmetic, but also bitwise ops)

    (2) Comparisons (with one precedence level)

    (3) Logical and/or (only 2 precedence levels)

    All (1) have higher precendence than (2), which are higher than
    (3). (In my code, groups (2) and (3) mostly occur in conditional
    expressions such as 'f (expr)'.)
    [...]

    "Within expressions" is an odd way to describe it, since all operators
    are within expressions.


    I explained what I mean in the brackets, which is that of arithmetic expressions like a*(b+c[i])-1.

    Ones that also include comparisons or logical are rare in most contexts,
    and mainly occur in conditionals:

    if (a == b)
    while (c > 0 && d > 0)

    Some languages may not even allow groups (2) and (3) outside of such conditionals.

    That means that in most non-conditional expressions, there would only
    have been group (1) precedences to worry about. Although in C, that
    still means 6 levels; I make do with 2 elsewhere.

    6 for C is just too much. Why not have each operator have its own
    private precedence? 18 levels is not much harder to remember than 10!
    And about as useful.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Kaz Kylheku on Tue Feb 20 20:09:40 2024
    On 20/02/2024 18:14, Kaz Kylheku wrote:
    On 2024-02-20, bart <bc@freeuk.com> wrote:
    C mixes up some operators between (1) and (2), that's one thing.
    For example, ^ is bizarrely lower precedence than ==.

    Yes, this is an ancient mistake that was acknowledged by D. Ritchie
    decades ago.

    It's an unfortunate thing that is hard to change.

    The most harm that came out of it is, I think, not the programming
    bugs, but the endless debate.

    It's not impossible to change. Basically first we would have to
    mark the current precedence deprecated, and require a diagnostic
    for programw which rely on it.

    For instance the expression a == b & c == d would require a diagnostic, similar to the optional one can obtain get anyway from some popular compilers.

    Then, after a long period of obsolescence and diagnosis, perhaps 25
    years or more, new rules could be put in. a == b & c == d would not
    longer require a diagnostic, but silently parse as (a == (b & c)) == d.

    IMO, it would have been a good idea had ANSI C 89 taken the above obsolescence step. By C11, if not C99, we could have been rid of the precedence infelicities.

    The problem with requiring a diagnostic is that the standard doesn't distinguish errors and warnings. A program which requires a diagnostic
    is erroneous. If it is translated and executed anyway, its behavior is undefined.

    You can't say that a == b & c == d is correct, and parses as (a == b ) &
    (c == d), while at the same time demanding a diagnostic. That's contradictory: if it requires a diagnostic, it is incorrect.

    The standard would have to sharpen its knife and introduce the concept
    of informational diagnostics which don't indicate an incorrect
    situation, but only some deprecated situation.


    Another way is to introduce new versions of & | ^ operators with revised precedences. (But you can't use the names in iso646.h.)

    After a while, those original operators can be deprecated, then banned.
    When there is no more code using & | ^, they can be introduced as
    synonyms for the new operators.

    But that only fixes part of it.

    I would also quite like to see chained comparisons like a == b == c.
    That is valid code now, but doen't anything that useful. You want it to
    mean (a == b) && (b == c) while only evaluating b once.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to James Kuyper on Tue Feb 20 23:10:56 2024
    On Tue, 20 Feb 2024 03:32:19 -0500, James Kuyper wrote:

    On 2/19/24 20:37, Lawrence D'Oliveiro wrote:
    On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:

    Now, can we find a good mnemonic for C's operator precedence levels?

    “RTFM”.

    The standard doesn't describe operator precedence levels. It provides
    grammar rules, and precedence must be inferred from the grammar. I've
    found that it is not widely understood how to infer precedence from the grammar.

    Wasn’t BNF covered in one of your undergraduate CS courses? Didn’t you practise it by reading the grammar of some unfamiliar (maybe made-up) languages? So the fact that a “postfix-expression” occurs within a “unary-
    expression”, and not the other way around (not without intervening parentheses, anyway), should indicate that postfix operators bind more
    tightly than prefix ones.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to bart on Tue Feb 20 23:03:19 2024
    On Tue, 20 Feb 2024 17:20:00 +0000, bart wrote:

    For example, ^ is bizarrely lower precedence than ==.

    That I agree is bizarre. Python quietly rearranges things, and I don’t
    think many C programmers have noticed.

    Yet C puts the precedence of << and >> the other side of + and -. This
    means that:

    1 << 2 + 3

    is 1<<(2+3) or 32, not (1<<2)+3 or 7.

    This seems to work reasonably well, even in complex cases, e.g.

    *resultptr++ =
    alpha << 24
    |
    (b << 3 | (b & 0xE0) >> 5) * alpha / 255 << 16
    |
    (g << 2 | (g & 0xC0) >> 6) * alpha / 255 << 8
    |
    (r << 3 | (r & 0xE0) >> 5) * alpha / 255;

    Another one is ?: as in:

    a ? b ? c : d : e // or:
    a ? b : c ? d : e

    With more complex terms, it's easy to get lost. Although this one is not
    so much about precedence; I wouldn't class it as an operator all, and
    would insist on parentheses so that the boundaries of this 3-way
    construct are absolutely clear.

    Indentation works, too:

    final PointF ThisMouse =
    ThisMouse1 != null ?
    ThisMouse2 != null ?
    new PointF
    (
    (ThisMouse1.x + ThisMouse2.x) / 2.0f,
    (ThisMouse1.y + ThisMouse2.y) / 2.0f
    )
    :
    ThisMouse1
    :
    ThisMouse2;

    OK, that’s Java code, but you get the idea.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Tue Feb 20 23:22:06 2024
    On 2024-02-20, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Tue, 20 Feb 2024 10:11:19 +0000, Malcolm McLean wrote:

    this will be the problem than that somone will need an accurate value
    for a vector with members pushing DBL_MAX, and this will be the problem.

    Remember that one of the key goals of IEEE754 was to minimize surprises
    for those who are not complete wizards at numerical techniques (i.e.
    nearly all of us).

    That seems exactly like the kind of goal that requires throwing some
    of the math under the bus.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Malcolm McLean on Tue Feb 20 23:16:28 2024
    On Tue, 20 Feb 2024 10:11:19 +0000, Malcolm McLean wrote:

    this will be the problem than that somone will need an accurate value
    for a vector with members pushing DBL_MAX, and this will be the problem.

    Remember that one of the key goals of IEEE754 was to minimize surprises
    for those who are not complete wizards at numerical techniques (i.e.
    nearly all of us).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to bart on Wed Feb 21 00:45:21 2024
    On Wed, 21 Feb 2024 00:33:21 +0000, bart wrote:

    On 20/02/2024 23:03, Lawrence D'Oliveiro wrote:

    *resultptr++ =
    alpha << 24
    |
    (b << 3 | (b & 0xE0) >> 5) * alpha / 255 << 16
    |
    (g << 2 | (g & 0xC0) >> 6) * alpha / 255 << 8
    |
    (r << 3 | (r & 0xE0) >> 5) * alpha / 255;


    You're using | instead of + ...

    Of course; that seems the natural one to use, when concatenating bit
    fields.

    final PointF ThisMouse =
    ThisMouse1 != null ?
    ThisMouse2 != null ?
    new PointF
    (
    (ThisMouse1.x + ThisMouse2.x) / 2.0f,
    (ThisMouse1.y + ThisMouse2.y) / 2.0f
    )
    :
    ThisMouse1
    :
    ThisMouse2;

    But you wouldn't write that would you?

    I did. That is from actual, working code.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Lawrence D'Oliveiro on Wed Feb 21 00:33:21 2024
    On 20/02/2024 23:03, Lawrence D'Oliveiro wrote:
    On Tue, 20 Feb 2024 17:20:00 +0000, bart wrote:

    For example, ^ is bizarrely lower precedence than ==.

    That I agree is bizarre. Python quietly rearranges things, and I don’t think many C programmers have noticed.

    Yet C puts the precedence of << and >> the other side of + and -. This
    means that:

    1 << 2 + 3

    is 1<<(2+3) or 32, not (1<<2)+3 or 7.

    This seems to work reasonably well, even in complex cases, e.g.

    *resultptr++ =
    alpha << 24
    |
    (b << 3 | (b & 0xE0) >> 5) * alpha / 255 << 16
    |
    (g << 2 | (g & 0xC0) >> 6) * alpha / 255 << 8
    |
    (r << 3 | (r & 0xE0) >> 5) * alpha / 255;


    You're using | instead of +; their precedences are each the other side
    of <<, at least in C.

    Something else I do elsewhere is to have the same precedence for + and
    |, since the is no real reason to have them different. And even if there
    was, who'd be able to remember which was which?

    Myriad precedence sounds a good idea on paper - after all they're free!
    But usually impractical.

    Another one is ?: as in:

    a ? b ? c : d : e // or:
    a ? b : c ? d : e

    With more complex terms, it's easy to get lost. Although this one is not
    so much about precedence; I wouldn't class it as an operator all, and
    would insist on parentheses so that the boundaries of this 3-way
    construct are absolutely clear.

    Indentation works, too:

    final PointF ThisMouse =
    ThisMouse1 != null ?
    ThisMouse2 != null ?
    new PointF
    (
    (ThisMouse1.x + ThisMouse2.x) / 2.0f,
    (ThisMouse1.y + ThisMouse2.y) / 2.0f
    )
    :
    ThisMouse1
    :
    ThisMouse2;

    But you wouldn't write that would you? Operators such as ?: are best
    used within one line to keep things compact.

    As soon as you span multiple lines, you might as well use regular
    if-else statements.

    Now, standard C doesn't allow regular `if` to return values, so you'd
    have to take the assignments inside.

    (My language does allow that, but I would do the same.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Lawrence D'Oliveiro on Wed Feb 21 01:57:42 2024
    On 21/02/2024 00:45, Lawrence D'Oliveiro wrote:
    On Wed, 21 Feb 2024 00:33:21 +0000, bart wrote:

    On 20/02/2024 23:03, Lawrence D'Oliveiro wrote:

    *resultptr++ =
    alpha << 24
    |
    (b << 3 | (b & 0xE0) >> 5) * alpha / 255 << 16
    |
    (g << 2 | (g & 0xC0) >> 6) * alpha / 255 << 8
    |
    (r << 3 | (r & 0xE0) >> 5) * alpha / 255;


    You're using | instead of + ...

    Of course; that seems the natural one to use, when concatenating bit
    fields.

    final PointF ThisMouse =
    ThisMouse1 != null ?
    ThisMouse2 != null ?
    new PointF
    (
    (ThisMouse1.x + ThisMouse2.x) / 2.0f,
    (ThisMouse1.y + ThisMouse2.y) / 2.0f
    )
    :
    ThisMouse1
    :
    ThisMouse2;

    But you wouldn't write that would you?

    I did. That is from actual, working code.

    So why didn't you use 'if' and 'else'? Because 'if' couldn't be used on
    the right side of an assignment?

    I would call that a language failing, except I don't agree with having a multi-line RHS to an assignment anyway, unless lines overflow. Getting
    around that failing by abusing the ?: syntax I think compounds the problem.

    Those dozen lines of code correspond to an assignment that looks like this:

    A := (B | (C | (B.X+C.X, B.Y+C.Y)/2 | B | C)

    (In the syntax of my 1990s scripting language.)

    In Java, I would write it like this, if {} blocks are optional:

    PointF ThisMouse;

    if (ThisMouse1)
    if (ThisMouse2)
    ThisMouse = PointF((ThisMouse1.x + ThisMouse2.x)/2,
    (ThisMouse1.y + ThisMouse2.y)/2);
    else
    ThisMouse = ThisMouse1;
    else
    ThisMouse = ThisMouse2;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mike Terry@21:1/5 to Chris M. Thomasson on Wed Feb 21 01:29:45 2024
    On 20/02/2024 20:11, Chris M. Thomasson wrote:
    On 2/19/2024 11:21 AM, Mike Terry wrote:
    On 19/02/2024 00:06, Mike Terry wrote:
    On 18/02/2024 23:06, Richard Harnden wrote:
    On 18/02/2024 22:34, Ben Bacarisse wrote:

    [BODMAS]


    I've always seen it rendered as "orders". I think "indexes" is better, >>>>> but it does not fix the basic problem.

    And, for the record, I was never taught it.


    Just curious - Were you taught SOHCAHTOA for trig? I always found that easy to remember.


    Never heard that one - is it thought of as one long word??

    Just as we're on the subject, a friend of mine at high school was pleased with himself for
    inventing what might be the most useless maths mnemonic ever:

    Smelly Armpits Cause Termites

    ok, it's memorable for sure, no problem on that front! But I was baffled why he thought it
    important to have a mnemonic for what it explains. (Plus it's hardly logical (mathematically)
    even if you know what it's explaining!)

    ob. Puzzle - what was his mnemonic helping him remember? [hint: it's trig related]


    In case anyone was curious...

    |
    |
    Cause | Armpits
    |
    |
    --------------+--------------
    |
    |
    Termites | Smelly
    |
    |

    Reminding us of:

    |
    |
    Cosine | All
    |
    |
    --------------+--------------
    |
    |
    Tangent | Sine
    |
    |

    That's right, it's helping us remember which trig functions are positive in each of the four
    quadrants!

    Um, don't ask....! :)



    What about using cos for x and sin for y therefore:

    cos(0) = 1

    Would be on the "right side" assuming:
    _____________________

    +y
    |
    |
    |
    |
    |
    ^
    -x -----------<0>----------- +x
    v
    |
    |
    |
    |
    -y

    _____________________

    ?

    Yes, the point (x=1, y=0) is where we start measuring our unit circle angle and we measure
    counterclockwise. Looking at my first diagram, I see I actually got two of the quadrants flipped!
    Lol. Should have been
    |
    |
    Smelly | Armpits
    |
    |
    --------------+--------------
    |
    |
    Termites | Cause
    |
    |

    sin is the y-coord and cos is the x-coord. (Easy to remember sin(0) = 0 which is the y-coord... I
    can work out the sign of x,y in the four quadrants without a helpful mnemonic!)

    Mike.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Lawrence D'Oliveiro on Wed Feb 21 00:34:02 2024
    On 2/20/24 18:10, Lawrence D'Oliveiro wrote:
    On Tue, 20 Feb 2024 03:32:19 -0500, James Kuyper wrote:

    On 2/19/24 20:37, Lawrence D'Oliveiro wrote:
    On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:

    Now, can we find a good mnemonic for C's operator precedence levels?

    “RTFM”.

    The standard doesn't describe operator precedence levels. It provides
    grammar rules, and precedence must be inferred from the grammar. I've
    found that it is not widely understood how to infer precedence from the
    grammar.

    Wasn’t BNF covered in one of your undergraduate CS courses?

    No. I'm mostly self-taught in computer programming. My degree was in
    Physics, not CS. I took a few CS courses, but not many. I had planned to
    be a scientist who could write his own data analysis and simulation
    programs. I ended up with a career writing scientific computer programs
    rather than coming up with new scientific theories of my own. I was
    always very good at understanding scientific theories, but I lacked the imagination needed to come up with new ones.

    However, despite lacking a CS background, as I've already said, I have
    no trouble figuring out precedence levels by examining the grammar. My
    point was that I've talked with many people who found it less obvious
    than you or I do.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to James Kuyper on Wed Feb 21 06:20:36 2024
    On Wed, 21 Feb 2024 00:34:02 -0500, James Kuyper wrote:

    My point was that I've talked with many people who found it less obvious
    than you or I do.

    Did they know how to read a BNF grammar?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to bart on Wed Feb 21 06:21:31 2024
    On Wed, 21 Feb 2024 01:57:42 +0000, bart wrote:

    On 21/02/2024 00:45, Lawrence D'Oliveiro wrote:

    On Wed, 21 Feb 2024 00:33:21 +0000, bart wrote:

    On 20/02/2024 23:03, Lawrence D'Oliveiro wrote:

    final PointF ThisMouse =
    ThisMouse1 != null ?
    ThisMouse2 != null ?
    new PointF
    (
    (ThisMouse1.x + ThisMouse2.x) / 2.0f,
    (ThisMouse1.y + ThisMouse2.y) / 2.0f
    )
    :
    ThisMouse1
    :
    ThisMouse2;

    But you wouldn't write that would you?

    I did. That is from actual, working code.

    So why didn't you use 'if' and 'else'?

    Then it couldn’t have been “final”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to bart on Wed Feb 21 09:14:59 2024
    On 20/02/2024 18:20, bart wrote:
    On 20/02/2024 02:19, Tim Rentsch wrote:
    Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

    [...]

    Now, can we find a good mnemonic for C's operator precedence levels?
    Extra credit if left/right associativity is also covered.

    Let me ask, which areas give people the most trouble, or where do
    they find that they need help remembering?  My reason for asking is
    I myself find most of C's expression syntax behaves the way I expect
    without having to think about it, so I need relatively few memory
    aids to feel confident in knowing the whole stack.  But what are the
    stumbling blocks for other folks?


    I like to intuitively think of binary operators as belonging to three
    groups:

      (1) Within expressions (arithmetic, but also bitwise ops)

      (2) Comparisons (with one precedence level)

      (3) Logical and/or (only 2 precedence levels)

    All (1) have higher precendence than (2), which are higher than (3). (In
    my code, groups (2) and (3) mostly occur in conditional expressions such
    as 'f (expr)'.)

    C mixes up some operators between (1) and (2), that's one thing.
    For example, ^ is bizarrely lower precedence than ==.


    I agree that this is strange. I suspect it was the result of the
    historical split of the logical and bitwise operators - it makes sense
    to have logical operators as lower than equality, and bitwise operators presumably stayed there after the split instead of being moved up.

    Even within the same group (1), I think of << and >> as scaling
    operators of the same rank as * and /, since they really do the same job
    (any shift can be implemented with multiple or divide by a power of two).

    I agree on that too (with the caveat that signed division by powers of
    two is not just a shift in C - and that's another decision that could
    certainly be questioned).


    Yet C puts the precedence of << and >> the other side of + and -. This
    means that:

       1 << 2 + 3

    is 1<<(2+3) or 32, not (1<<2)+3 or 7.


    This is why some of us like to put in the "extra" parentheses :-)

    Another one is ?: as in:

         a ? b ? c : d : e     // or:
         a ? b : c ? d : e

    With more complex terms, it's easy to get lost. Although this one is not
    so much about precedence; I wouldn't class it as an operator all, and
    would insist on parentheses so that the boundaries of this 3-way
    construct are absolutely clear.

    With parentheses, I /believe/ the correct grouping that corrresponds is repectively:

         (a ? (b ? c : d) : e)
         (a ? b : (c ? d : e))

    Now I can change 'I believe' to 'I know'.


    That is more about associativity than precedence. There is no way the expressions could mean anything else - if the associativity were
    difference, chaining like your first case would have to be a syntax
    error, and for the second case it would mean the same anyway.


    Remember this is not just about working with C. People may work on
    different languages with their own rules.

    Yes, I agree again. (I think this may be a record?) Again, parentheses
    and splitting up expressions into parts is the way to keep sane and safe.


    `2 + 3 * 4` is near-universally evaluated as 14. With `1 << 2 + 3` most languages I managed to try on rextester.com (which supported infix
    `<<`), also gave C's result of 32.

    This means a lot of languages that have perpetuated C's bad choices.

    A few languages however did not just blindly follow C, such as Pascal,
    Go and Swift; those gave a result of 7.





    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Kaz Kylheku on Wed Feb 21 09:27:39 2024
    On 20/02/2024 18:12, Kaz Kylheku wrote:
    On 2024-02-20, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
    Kaz Kylheku <433-929-6894@kylheku.com> writes:

    On 2024-02-19, Mike Terry <news.dead.person.stones@darjeeling.plus.com> wrote:
    In case anyone was curious...

    |
    |
    Cause | Armpits
    |
    |
    --------------+--------------
    |
    |
    Termites | Smelly
    |
    |

    I learned

    crazy all

    teachers are science

    from a math teacher who was Scottish. Someone in the class piped up
    with "all Scottish teachers are crazy", to great laughter.

    I don't think it worked! I was maybe too subtle in my last post, but
    you have to remember something entirely arbitrary with this sort of
    thing -- where to start and the order of going round (or otherwise
    naming) the quadrants. All the posted examples I've see have the C and
    S quadrants swapped over.

    Like a Chat AI robot, I just followed my interlocutor's example,
    and pretended it's right.

    For a moment, I wondered why the words are going clockwise (negative rotation) but didn't give it a moment's thought beyond that.

    Part of the value of the "all science teachers are crazy" mnemonic is
    that it starts with the first quadrant and follows the positive angle.

    You will not get it wrong, unless you're preloaded with a wrong example
    and don't think about it.

    If you think about it for a millisecond, of course sin() is positive
    over the first 180 degrees, but since cos() starts high, that
    function drops and crosses zero at 90. If you know this simple
    thing, you don't need the mnemonic.


    I don't understand why anyone would feel the need for mnemonics here at
    all. I think it is because people are often taught first that sins and
    cosines are about right-angled triangles. Then they get confused and
    have to unlearn things when the arguments are outside of 0° - 90°.

    Think of the unit circle, and draw an angle θ from the x-axis - going counter-clockwise, as you always do. cos θ is the x coordinate, sin θ
    is the y coordinate. It's now all obvious and easy, and there is no
    need for even a millisecond's thought about signs.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Ben Bacarisse on Wed Feb 21 01:35:33 2024
    Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

    [...]

    On 20/02/2024 01:05, Ben Bacarisse wrote:

    Mike Terry <news.dead.person.stones@darjeeling.plus.com> writes:
    [...]

    Your example shows why I never liked this sort of "help".
    Remembering where to start and what order to label the quadrants
    is harder (for me) than knowing how trig functions work.

    Same for me. The trick to getting the signs of sins right is to
    think of circles, not triangles, when doing trig. Then it is all
    completely obvious.

    Now, can we find a good mnemonic for C's operator precedence
    levels? Extra credit if left/right associativity is also
    covered. (Few! On topic again.)

    [...]

    For me, pretty much the only one I'd have to look up (though only
    in a year or two, since I've recently been reminded!) is ^ vs |.

    There are different kinds of memory aids. The ones that tend to
    work for me are those with some semantic content, not just rote
    memorization or via some cryptic acronym. This idea is similar
    to the first two paragraphs quoted above.

    For the bitwise logical operators, an example of the kind of
    memory aid I find helpful is as follows.

    The result of an & operator can have fewer bits on than its
    operands, but never more;

    The result of an | operator can have more bits on than its
    operands, but never fewer;

    The result of an ^ operator can have either fewer bits on or
    more bits on than its operands (or possibly the same number),
    depending on the values of the operands.

    Hence it makes sense to put ^ between & and |, and that
    is indeed where it is in C's precedence hierarchy --
    fewer, fewer or more, more -- & ^ |.

    (Of course I expect & binds more tightly than |, as is
    conventional in mathematics and hardware design, etc.)

    I can't say I ever had a problem with the relative precedences of
    the bitwise logical operators, but this description probably did
    help cement it for me.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dave_thompson_2@comcast.net@21:1/5 to 433-929-6894@kylheku.com on Mon Feb 26 04:22:06 2024
    On Fri, 9 Feb 2024 22:14:19 -0000 (UTC), Kaz Kylheku
    <433-929-6894@kylheku.com> wrote:

    On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    If I were designing a new language, I'd consider using ":=" for
    assignment, "==" for equality, and not using "=" for anything.

    In (nearly?) all languages I'm aware of, ":=" either doesn't exist or
    means assignment, and "==" either doesn't exist or means equality. I'd avoid "=" because it's ambiguous across languages (and that's almost entirely C's fault, inherited from B).

    Some of the credit must go to classic BASIC!

    I seem to remember than in classic, line-numbered BASICs on 8 bit
    micros, the = token was used both for assignment and comparison!

    300 I = I + 1
    310 IF I = 10 GOTO 340

    BASIC itself predates (B and) C, but 8 bit micros are at least 5 years
    too late.

    If you have a dedicated assignment statement, you can pull this kind
    of stunt. Just like C can distinguish initialization from assignment.

    And I'm pretty sure Dartmouth BASIC required LET var = expr, which
    (more) clearly distinguished it from IF.

    COBOL used = for both one type of assignment (requiring keyword
    COMPUTE) and equality. (The other types of assignment didn't use any
    punctuator at all.) PL/I used it for both, with assignment 'bare'.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to dave_thompson_2@comcast.net on Tue Feb 27 12:40:47 2024
    On 26.02.2024 10:22, dave_thompson_2@comcast.net wrote:
    On Fri, 9 Feb 2024 22:14:19 -0000 (UTC), Kaz Kylheku <433-929-6894@kylheku.com> wrote:
    On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    If I were designing a new language, I'd consider using ":=" for
    assignment, "==" for equality, and not using "=" for anything.

    In (nearly?) all languages I'm aware of, ":=" either doesn't exist or
    means assignment, and "==" either doesn't exist or means equality.

    In Simula you have '=' (equality) and '==' (identity; for references),
    and of course ':=' (value assignments) and ':-' (reference assignments).

    I'd
    avoid "=" because it's ambiguous across languages (and that's almost
    entirely C's fault, inherited from B).

    Some of the credit must go to classic BASIC!

    Don't forget FORTRAN (appearing before BASIC). And here also the syntax ambiguity it had with loops and assignments (but I forgot the details).


    I seem to remember than in classic, line-numbered BASICs on 8 bit
    micros, the = token was used both for assignment and comparison!

    300 I = I + 1
    310 IF I = 10 GOTO 340

    BASIC itself predates (B and) C, but 8 bit micros are at least 5 years
    too late.

    If you have a dedicated assignment statement, you can pull this kind
    of stunt. Just like C can distinguish initialization from assignment.

    And I'm pretty sure Dartmouth BASIC required LET var = expr, which
    (more) clearly distinguished it from IF.

    Not all BASIC dialects "required" 'LET'. (A BASIC pocket calculator
    from the 1970's that I still have allows omitting the keyword. But
    wasn't that quite typical for the BASIC home PCs that came later?)

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to Janis Papanagnou on Tue Feb 27 13:21:11 2024
    On 27/02/2024 11:40, Janis Papanagnou wrote:
    On 26.02.2024 10:22, dave_thompson_2@comcast.net wrote:
    On Fri, 9 Feb 2024 22:14:19 -0000 (UTC), Kaz Kylheku
    <433-929-6894@kylheku.com> wrote:
    On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    If I were designing a new language, I'd consider using ":=" for
    assignment, "==" for equality, and not using "=" for anything.

    In (nearly?) all languages I'm aware of, ":=" either doesn't exist or
    means assignment, and "==" either doesn't exist or means equality.

    In Simula you have '=' (equality) and '==' (identity; for references),
    and of course ':=' (value assignments) and ':-' (reference assignments).

    I'd
    avoid "=" because it's ambiguous across languages (and that's almost
    entirely C's fault, inherited from B).

    Some of the credit must go to classic BASIC!

    Don't forget FORTRAN (appearing before BASIC). And here also the syntax ambiguity it had with loops and assignments (but I forgot the details).

    do 100 i = 1,10
    do 100 i = 1.10

    (FORTRAN ignores embedded white space.) The first is a loop over 1..10 delimited by label 100.

    The second assigns 1.10 to variable `do100i`.

    So it's not really ambiguous, but it is error prone.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Feb 29 21:29:49 2024
    On Mon, 26 Feb 2024 04:22:06 -0500, dave_thompson_2 wrote:

    And I'm pretty sure Dartmouth BASIC required LET var = expr, which
    (more) clearly distinguished it from IF.

    And they brought out their own “True BASIC” which did exactly this, to try to compete against Microsoft BASIC, which they saw as being not “true” to their original idea of BASIC.

    I don’t think it did very well.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)