• Operator precedence

    From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Thu May 23 16:13:33 2024
    From Newsgroup: comp.lang.awk

    After reading an old article in the Algol bulletin about questions
    and issues with operator precedences I tried this with (Gnu) Awk

    $ awk 'BEGIN { a=5; print a^2, -a^2, 0-a^2 }'
    25 -25 -25

    and shell (Ksh)

    $ a=5 ; print $(( a**2 )) $(( -a**2 )) $(( 0-a**2 ))
    25 25 -25

    and Algol 68

    $ a68g -p 'INT a=5; (a^2, -a^2, 0-a^2)'
    +25 +25 -25

    I don't want to value the different results (based on precedence),
    but I'm interested in your comments/thoughts about the differences.

    Janis
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.awk on Thu May 23 16:49:15 2024
    From Newsgroup: comp.lang.awk

    On 2024-05-23, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    After reading an old article in the Algol bulletin about questions
    and issues with operator precedences I tried this with (Gnu) Awk

    $ awk 'BEGIN { a=5; print a^2, -a^2, 0-a^2 }'
    25 -25 -25

    and shell (Ksh)

    $ a=5 ; print $(( a**2 )) $(( -a**2 )) $(( 0-a**2 ))
    25 25 -25

    and Algol 68

    $ a68g -p 'INT a=5; (a^2, -a^2, 0-a^2)'
    +25 +25 -25

    I don't want to value the different results (based on precedence),
    but I'm interested in your comments/thoughts about the differences.

    There is no question that we want the exponentiation operator
    to have a higher precedence than plus or minus, even including
    the unary forms. It's the "E" in the BEDMAS acronym that
    English-speaking children learn in some places in the world: brackets, exponentiation, division, multiplication, addition, subtracation.

    If -a**2 is not parsed as -(a**2), you're messing with the BEDMAS.

    Furthermore exponentation between on an intermediate precedence
    level between unary minus and regular minus is simply insane.

    You might think you're out of the woods with Lisp, where you don't
    have precedence. But some math operations have variadic arguments,
    so associativity comes into play.

    Common Lisp restricts expt to exactly two arguments:

    (expt 5 2)
    25
    (expt 5 2 3)

    *** - EVAL: too many arguments given to EXPT: (EXPT 2 5 3)

    I made it n-ary in TXR Lisp:

    (expt 5 2)
    25
    (expt 5 2 3)
    390625

    Look, it's a right-to-left reduction, unlike addition, or multiplication:

    (expt (expt 5 2) 3)
    15625
    (expt 5 (expt 2 3))
    390625

    In other words (expt a b c ...) denotes

    ...
    c
    b
    a

    rather than

    b c ...
    (.. ((a) ) )
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Axel Reichert@mail@axel-reichert.de to comp.lang.awk on Thu May 23 19:14:44 2024
    From Newsgroup: comp.lang.awk

    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    Furthermore exponentation between on an intermediate precedence level
    between unary minus and regular minus is simply insane.

    This is a very good argument! Prior to reading it I was kind of
    indifferent (at least in infix programming languages, but not in typeset mathematics).

    I made it n-ary in TXR Lisp:

    (expt 5 2)
    25
    (expt 5 2 3)
    390625

    ... so conforming to the habit of typeset mathematics, which is based on
    the fact that

    c
    b
    a

    could be written as

    bc
    a

    if meant to be left-associative. So having it right associative is the
    more terse convention.

    For further reading,

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

    is informative, while

    https://en.wikipedia.org/wiki/Graham%27s_number
    https://en.wikipedia.org/wiki/Knuth%27s_up-arrow_notation

    are curiosities. Have fun!

    Axel
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Fri May 24 01:53:52 2024
    From Newsgroup: comp.lang.awk

    On 23.05.2024 19:14, Axel Reichert wrote:
    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    Furthermore exponentation between on an intermediate precedence level
    between unary minus and regular minus is simply insane.

    This is a very good argument! [...]

    I'd be interested why you think so. Unfortunately, and opposed to
    the statement, I think there was no actual "argument" presented in
    this quoted sentence.[*] - Please don't get me wrong; I'm really
    interested in a relatable argument, and I also try to be unbiased!

    If I understand Kaz' comment correctly, the ordering of the three
    operators should be different? Are you saying that the order
    unary minus
    exponentiation
    binary minus
    is somehow "wrong"? - Yet, I don't see why.
    Moreover, what seams reasonable (to me) is that _unary_ operators
    should (typically/always?) bind tighter than _binary_ operators!
    This would imply that exponentiation does not bind higher than the
    unary minus. (And that the order of the upthread posted Shell and
    Algol 68 expressions would thus fit better.)

    Different languages also differ in their implementation choice as
    shown; besides languages mentioned I read that (for example) Eiffel
    implements it the way that GNU Awk has chosen. - That's now 2:2,
    but counting majority is of course also no convincing argument.

    OTOH, exponentiation is (typically/always?) right associative, so
    it's may be somehow sensible to be handled differently compared to
    the other [commutative] binary operators?

    You see I'm still undecided, and still looking for explanations.
    OTOH, given that this had been discussed by computer scientists
    and mathematicians without clear answer, it may boil down to just
    be an opinion to be decided in one way or the other.

    It is interesting what the [German] Wikipedia[**] says about that.
    Specifically that there's (besides exponentiation, multiplication/
    division, addition/subtraction) additional categories in programming
    languages; the [unary] sign that normally has a yet higher priority
    than the exponentiation. - Well...

    Janis

    [*] "simply insane" doesn't contribute to a substantial argument.

    Also the upthread mentioned "BEDMAS" sort of rule doesn't seem
    to apply since unary operators are not mentioned (and there's a
    difference between subtraction and negation). In our schools we
    also learned such simplified rules, in our case it was "Punkt vor
    Strich" (meaning multiplication and division comes before addition
    and subtraction). And we had also the practice that exponentiation
    has a tighter binding than a unary minus sign (as Kaz suggested).

    [**] https://de.wikipedia.org/wiki/Operatorrangfolge

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Fri May 24 04:41:11 2024
    From Newsgroup: comp.lang.awk

    After pondering a bit more I think this is my personal resume...

    On 24.05.2024 01:53, Janis Papanagnou wrote:
    [...]
    Moreover, what seams reasonable (to me) is that _unary_ operators
    should (typically/always?) bind tighter than _binary_ operators!

    An example may make things probably more apparent; in the expression

    5 * -3 ^ 2

    it would never occur to me to not consider the "-3" as an entity.
    Because of the typical inherently tight coupling of unary operators.

    (Assuming an interpretation of

    5 * -(3 ^ 2)

    would look just wrong to me.)

    This would imply that exponentiation does not bind higher than the
    unary minus. (And that the order of the upthread posted Shell and
    Algol 68 expressions would thus fit better.)

    BTW, Unix 'bc' also behaves that way

    $ bc -l <<< " 5 * -3 ^ 2 "
    45


    <off-topic>
    Let me add an Algol 68 anecdote (sort of)... You can of course adjust
    the operator precedences in that language to fit your preferences.
    And since you have more than one representation for the exponentiation
    in Algol 68 - in the Genie compiler for example '^', 'UP', and '**' -
    you can even change just one of them (if you like), for example

    BEGIN
    PRIO UP = 5;
    INT a=5;
    print ((a ^ 2, - a ^ 2, 0 - a ^ 2, newline));
    print ((a UP 2, -a UP 2, 0-a UP 2, newline));
    print ((a ** 2, -a ** 2, 0-a ** 2, newline));
    SKIP
    END

    produces
    +25 +25 -25
    +25 +25 +25
    +25 +25 -25

    Scary! :-)

    Janis

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.awk on Fri May 24 03:45:50 2024
    From Newsgroup: comp.lang.awk

    On 2024-05-23, Axel Reichert <mail@axel-reichert.de> wrote:
    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    Furthermore exponentation between on an intermediate precedence level
    between unary minus and regular minus is simply insane.

    This is a very good argument! Prior to reading it I was kind of
    indifferent (at least in infix programming languages, but not in typeset mathematics).

    I made it n-ary in TXR Lisp:

    (expt 5 2)
    25
    (expt 5 2 3)
    390625

    ... so conforming to the habit of typeset mathematics, which is based on
    the fact that

    c
    b
    a

    could be written as

    bc
    a

    if meant to be left-associative. So having it right associative is the
    more terse convention.

    Yes. Also, in the left associative semantics, we have a choice. We can
    do the exponentation earnestly as if by:

    (expt (expt 5 2) 3)

    Or we can take advantage of the identity:

    (expt 5 (* 2 3))

    The former could be important in some situation involving
    floating-point: you can't always use simplifying identities.

    The latter is favored when efficiency is more important.

    A left associative n-ary expt function would have to make one of those
    two choices: either doggedly do the exponentiations (such that the
    function would be avoided by anyone looking for efficiency), or else
    serve as a syntactic sugar for the exponent raised to the product
    of the remaining arguments (which provides low value as a syntactic
    sugar, and yet has to be avoided by someone who can't use that identity
    for whatever reason).

    I felt that the n-ary semantics of expt provided the best value
    when right associative. It's not something obtainable by a ready
    identity, and there is one obvious way to do it.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.awk on Fri May 24 04:32:16 2024
    From Newsgroup: comp.lang.awk

    On 2024-05-24, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    After pondering a bit more I think this is my personal resume...

    On 24.05.2024 01:53, Janis Papanagnou wrote:
    [...]
    Moreover, what seams reasonable (to me) is that _unary_ operators
    should (typically/always?) bind tighter than _binary_ operators!

    An example may make things probably more apparent; in the expression

    5 * -3 ^ 2

    it would never occur to me to not consider the "-3" as an entity.
    Because of the typical inherently tight coupling of unary operators.

    (Assuming an interpretation of

    5 * -(3 ^ 2)

    would look just wrong to me.)

    That interpretation is required if - 3 ^ 2 is to correspond to:

    2
    -3

    Indeed the ^ circumflex is intended to mean "we don't have support
    for superscripts in this notation, but pretend that the 2 is raised up".

    (In TeX/LaTeX, ^ is used for marking up superscripts: x^y.)

    Now in the C grammar, we have multiplication also occuping a
    precedence rung between unary plus/minus and additive expressions.

    Thus -A*B means (-A)*B, whereas X - A*B means X-(A*B).

    In this case it doesn't matter because the unary minus is
    a kind of product. -A can be regarded as a shorthand for (-1)*A.

    More importantly the identity (-A)*B = -(A*B) holds.

    This creates a problem if we naively wedge exponentiation into
    the grammar, by sticking it into a precedence level above
    multiplication, but below unary.

    The identity does not hold in exponentiation: (-A)**B
    is not -(A**B).
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Axel Reichert@mail@axel-reichert.de to comp.lang.awk on Sat May 25 13:09:35 2024
    From Newsgroup: comp.lang.awk

    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    in the left associative semantics, we have a choice. We can do the exponentation earnestly as if by:

    (expt (expt 5 2) 3)

    Or we can take advantage of the identity:

    (expt 5 (* 2 3))

    The former could be important in some situation involving
    floating-point: you can't always use simplifying identities.

    I cannot readily imagine a scenario in which simplifying is not possible
    or is disadvantageous. Could you please elaborate?

    I felt that the n-ary semantics of expt provided the best value
    when right associative. It's not something obtainable by a ready
    identity, and there is one obvious way to do it.

    Full ACK.

    Best regards

    Axel
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Axel Reichert@mail@axel-reichert.de to comp.lang.awk on Sat May 25 13:34:25 2024
    From Newsgroup: comp.lang.awk

    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    Now in the C grammar, we have multiplication also occuping a
    precedence rung between unary plus/minus and additive expressions.

    Thus -A*B means (-A)*B, whereas X - A*B means X-(A*B).

    In this case it doesn't matter because the unary minus is
    a kind of product. -A can be regarded as a shorthand for (-1)*A.

    More importantly the identity (-A)*B = -(A*B) holds.

    This creates a problem if we naively wedge exponentiation into
    the grammar, by sticking it into a precedence level above
    multiplication, but below unary.

    The identity does not hold in exponentiation: (-A)**B
    is not -(A**B).

    Very nice explanation, many thanks. I will likely pass it to a friend (geodesist), who had a heated argument with the math teacher of her son
    about whether

    2
    -3

    is -9 or +9. I think the mathematical conventions are clear (and
    probably established for centuries), but the teacher might be confused
    and think Excel is the reference, see

    https://en.wikipedia.org/wiki/Order_of_operations#Unary_minus_sign

    It would be interesting to learn about the motivation for spreadsheets
    and "bc" to deviate from the mathematical convention.

    Best regards

    Axel
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Sat May 25 23:31:26 2024
    From Newsgroup: comp.lang.awk

    On 25.05.2024 13:34, Axel Reichert wrote:

    It would be interesting to learn about the motivation for spreadsheets
    and "bc" to deviate from the mathematical convention.

    It's not only these two program types. As noted upthread it's
    also Ksh and Algol 68 (for example), and it seems quite common
    in computing according to the cited Wikipedia article.

    Janis

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Sat May 25 23:31:54 2024
    From Newsgroup: comp.lang.awk

    On 24.05.2024 06:32, Kaz Kylheku wrote:
    On 2024-05-24, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    After pondering a bit more I think this is my personal resume...

    On 24.05.2024 01:53, Janis Papanagnou wrote:
    [...]
    Moreover, what seams reasonable (to me) is that _unary_ operators
    should (typically/always?) bind tighter than _binary_ operators!

    An example may make things probably more apparent; in the expression

    5 * -3 ^ 2

    it would never occur to me to not consider the "-3" as an entity.
    Because of the typical inherently tight coupling of unary operators.

    (Assuming an interpretation of

    5 * -(3 ^ 2)

    would look just wrong to me.)

    That interpretation is required if - 3 ^ 2 is to correspond to:

    2
    -3

    Indeed the ^ circumflex is intended to mean "we don't have support
    for superscripts in this notation, but pretend that the 2 is raised up".

    (In TeX/LaTeX, ^ is used for marking up superscripts: x^y.)

    Now in the C grammar, we have multiplication also occuping a
    precedence rung between unary plus/minus and additive expressions.

    Thus -A*B means (-A)*B, whereas X - A*B means X-(A*B).

    In this case it doesn't matter because the unary minus is
    a kind of product. -A can be regarded as a shorthand for (-1)*A.

    More importantly the identity (-A)*B = -(A*B) holds.

    So far so good, only it doesn't (IMO) provide a rationale for
    exponentiation.

    This creates a problem if we naively wedge exponentiation into
    the grammar, by sticking it into a precedence level above
    multiplication, but below unary.

    The identity does not hold in exponentiation: (-A)**B
    is not -(A**B).

    Looks like a non-sequitur to me.

    Janis

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Sun May 26 00:03:02 2024
    From Newsgroup: comp.lang.awk

    On 25.05.2024 23:31, Janis Papanagnou wrote:
    On 25.05.2024 13:34, Axel Reichert wrote:

    It would be interesting to learn about the motivation for spreadsheets
    and "bc" to deviate from the mathematical convention.

    It's not only these two program types. As noted upthread it's
    also Ksh and Algol 68 (for example), and it seems quite common
    in computing according to the cited Wikipedia article.

    WRT the second question ("deviate from the mathematical convention")
    I suppose it's because it's not the best fit for the formalization.

    Tight binding of monadic operators appears just natural (to me), so
    their "motivation" is quite obvious (to me).

    (Mind my remark that mathematicians and computer scientists were
    involved in the Algol 68 definition, and that this topic had been
    discussed there, and despite the old mathematical convention they
    decided to consistently streamline the definition. Frank Pagan's
    Algol 68 book, for example says that _every_ monadic operator has
    higher precedence than any dyadic operator. And that makes sense;
    also in my opinion. I consider Algol 68 also a landmark due to its extraordinary formal definition, that's why I emphasize it here as
    an outstanding paragon.)

    (Yet I haven't seen any convincing counter argument. But maybe we
    should just agree to disagree, since this topic (as I've read) had
    often lead to heated disputes and that's the least I wanted to have
    provoked with my post.)

    People should be anyway aware of the operator precedences in the
    various programming languages since there are obviously yet worse
    definitions than the one we've been discussing here.

    Janis

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.awk on Sat May 25 22:20:42 2024
    From Newsgroup: comp.lang.awk

    On 2024-05-25, Axel Reichert <mail@axel-reichert.de> wrote:
    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    in the left associative semantics, we have a choice. We can do the
    exponentation earnestly as if by:

    (expt (expt 5 2) 3)

    Or we can take advantage of the identity:

    (expt 5 (* 2 3))

    The former could be important in some situation involving
    floating-point: you can't always use simplifying identities.

    I cannot readily imagine a scenario in which simplifying is not possible
    or is disadvantageous. Could you please elaborate?

    I'm simply not enough of a numerical analyst to be able to rule such a situation as nonexistent.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.awk on Sat May 25 22:26:40 2024
    From Newsgroup: comp.lang.awk

    On 2024-05-25, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    (Mind my remark that mathematicians and computer scientists were
    involved in the Algol 68 definition, and that this topic had been
    discussed there, and despite the old mathematical convention they
    decided to consistently streamline the definition. Frank Pagan's
    Algol 68 book, for example says that _every_ monadic operator has
    higher precedence than any dyadic operator. And that makes sense;
    also in my opinion. I consider Algol 68 also a landmark due to its extraordinary formal definition, that's why I emphasize it here as
    an outstanding paragon.)

    What they are effectively saying is that the dyadic power operator A**B
    (or A^B or whatever it is) bears no syntactic relation to the 2D notation involving a superscript. I.e. it is a completely different syntactic
    interface to the same abstract operation. As such, it can have its own precedence rules, not hinged to the superscript power notation.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.awk on Sun May 26 01:29:11 2024
    From Newsgroup: comp.lang.awk

    On 2024-05-25, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    This creates a problem if we naively wedge exponentiation into
    the grammar, by sticking it into a precedence level above
    multiplication, but below unary.

    The identity does not hold in exponentiation: (-A)**B
    is not -(A**B).

    Looks like a non-sequitur to me.

    Yes; the only point here is to explain why we don't notice this
    issue, which is mirrored in multiplication: Given -A*B,
    we can cheerfully stick a 0 on it to make 0-A*B. The value
    does not surprisingly change. Yet, the underlying precedence
    relationships are parallel to those in -A**B vs 0-A**B, where
    there isn't an identity which masks the issue.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Christian Weisgerber@naddy@mips.inka.de to comp.lang.awk on Sun May 26 00:37:29 2024
    From Newsgroup: comp.lang.awk

    On 2024-05-25, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    People should be anyway aware of the operator precedences in the
    various programming languages since there are obviously yet worse
    definitions than the one we've been discussing here.

    Which is why BSD has had an operator(7) man page about "C operator
    precedence and order of evaluation" since 1990.
    --
    Christian "naddy" Weisgerber naddy@mips.inka.de
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.awk on Sun May 26 02:06:40 2024
    From Newsgroup: comp.lang.awk

    On 2024-05-26, Christian Weisgerber <naddy@mips.inka.de> wrote:
    On 2024-05-25, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    People should be anyway aware of the operator precedences in the
    various programming languages since there are obviously yet worse
    definitions than the one we've been discussing here.

    Which is why BSD has had an operator(7) man page about "C operator
    precedence and order of evaluation" since 1990.

    This discussion has convinced me that unary operators must not be
    clumped together and put into a single precedence level.

    For instance, if we have the C-like expression

    -*p/*q

    it should ideally be

    -(*p/*q)

    and not as it is now:

    (-*p)/(*q)

    due the unary minus being clumped with dereference.

    Unary minus should not be a distinct operator from binary minus.
    Unary minus should denote the elision of an identity element term,
    so that - X not only means the same as 0 - X, but is considered
    to be the same notation, just with the additive identity element not
    show. We could correctly parse it as a binary minus by putting the
    element back in.

    This can make a difference easily. Consider that the unsigned types
    in C have a definition for unary minus. If *p is of type unsigned
    int, and its value is 1, then (-*p) is UINT_MAX. *q is 4 then
    we get UINT_MAX / 4. Under the proposedd rule, we would get
    something else: 1/4 producing 0, and that negating to 0.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Thu May 30 06:59:57 2024
    From Newsgroup: comp.lang.awk

    On 26.05.2024 00:26, Kaz Kylheku wrote:
    On 2024-05-25, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    (Mind my remark that mathematicians and computer scientists were
    involved in the Algol 68 definition, and that this topic had been
    discussed there, and despite the old mathematical convention they
    decided to consistently streamline the definition. Frank Pagan's
    Algol 68 book, for example says that _every_ monadic operator has
    higher precedence than any dyadic operator. And that makes sense;
    also in my opinion. I consider Algol 68 also a landmark due to its
    extraordinary formal definition, that's why I emphasize it here as
    an outstanding paragon.)

    What they are effectively saying is that the dyadic power operator A**B
    (or A^B or whatever it is) bears no syntactic relation to the 2D notation involving a superscript. I.e. it is a completely different syntactic interface to the same abstract operation. As such, it can have its own precedence rules, not hinged to the superscript power notation.

    There's three power operators in Algol 68 ('UP', '^', '**') each with
    the same default precedence (and each individually changeable.

    What the Algol 68 report says on priorities is:

    Priority-declarations are used to specify the priority of operators.
    Priorities from 1 to 9 are available.
    Since monadic-operators have effectively only one priority-level, which
    is higher than that of all dyadic-operators, monadic-operators do not
    require priority-declarations.

    Formulas are either dyadic or monadic: e.g., x + i or ABS x. The order
    of elaboration of a formula is determined by the priority of its
    operators; monadic formulas are elaborated first and then the dyadic
    ones from the highest to the lowest priority.

    https://jmvdveer.home.xs4all.nl/en.post.algol-68-revised-report.html

    This is IMO a very clear and sensible definition. It resembles the
    property that I upthread mentioned as "tight binding" of monadics.
    (I know your mileage varies.)

    Janis

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Thu May 30 07:06:23 2024
    From Newsgroup: comp.lang.awk

    On 26.05.2024 02:37, Christian Weisgerber wrote:
    On 2024-05-25, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    People should be anyway aware of the operator precedences in the
    various programming languages since there are obviously yet worse
    definitions than the one we've been discussing here.

    Which is why BSD has had an operator(7) man page about "C operator
    precedence and order of evaluation" since 1990.

    And this is why my old K&R book had got from the beginning a
    bookmark affixed at the page with the table of operators. :-)

    Janis

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Thu May 30 07:26:11 2024
    From Newsgroup: comp.lang.awk

    On 26.05.2024 04:06, Kaz Kylheku wrote:
    On 2024-05-26, Christian Weisgerber <naddy@mips.inka.de> wrote:
    On 2024-05-25, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    People should be anyway aware of the operator precedences in the
    various programming languages since there are obviously yet worse
    definitions than the one we've been discussing here.

    Which is why BSD has had an operator(7) man page about "C operator
    precedence and order of evaluation" since 1990.

    This discussion has convinced me that unary operators must not be
    clumped together and put into a single precedence level.

    That's the way it goes. With proceeding discussion and studies of
    yet more literature sources I came exactly to a different result,
    and confidence in my (initially not that strong) view.

    For instance, if we have the C-like expression

    -*p/*q

    it should ideally be

    -(*p/*q)

    and not as it is now:

    (-*p)/(*q)

    due the unary minus being clumped with dereference.

    I won't comment on the dereferencing operator in C; it's a low
    level construct of a low level language that you don't find in
    Algol (the language mentioned as reference) or Awk (the language
    this NG is dedicated to), nor in 'bc' or spreadsheets, I suppose,
    which have also been mentioned.

    A note on the upthread also mentioned Ksh (which also shows this
    precedence). Earlier versions of Ksh did not support '**' in
    arithmetic expressions, it was added later. And (as opposed to
    C's misplaced &, |, and ^ operators) they deliberately inserted
    it between dyadic and monadic '-', which makes me confident that
    they thought well about the appropriate place where to insert it.
    (But this is of course just a detail, not a formal reasoning.)


    Unary minus should not be a distinct operator from binary minus.

    This is a statement I really find scary.

    Unary minus should denote the elision of an identity element term,
    so that - X not only means the same as 0 - X, but is considered
    to be the same notation, just with the additive identity element not
    show. We could correctly parse it as a binary minus by putting the
    element back in.

    But this reasoning is just artificial. Only because we can use
    transformations 0-X or -1*X for -X that doesn't mean that a
    subtraction is the same as a negation.

    We have dedicated syntax trees for monadic and dyadic operations.


    This can make a difference easily. Consider that the unsigned types
    in C have a definition for unary minus. If *p is of type unsigned
    int, and its value is 1, then (-*p) is UINT_MAX. *q is 4 then
    we get UINT_MAX / 4. Under the proposedd rule, we would get
    something else: 1/4 producing 0, and that negating to 0.

    (Again low level C.)

    Janis

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Axel Reichert@mail@axel-reichert.de to comp.lang.awk on Thu May 30 10:17:04 2024
    From Newsgroup: comp.lang.awk

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    Are you saying that the order
    unary minus
    exponentiation
    binary minus
    is somehow "wrong"?

    It certainly feels like this to me. When thinking about the "why", I
    could see two "arguments":

    1. Unary and binary minus, while not identical operators, at least
    visually are identical. Hence it reduces the cognitive load on the
    reader of source code, who does not need to remember that unary minus
    and binary minus are "on opposite sides of the 'exponentiation fence'".

    2. Mathematical programming is algorithms (often beautifully typeset
    with (La)TeX) transformed into more mundane ASCII-text representations
    (which I see as a technical limitation). Using different operator
    precedence depending on the visual representation is certainly confusing
    if not dangerous (error-prone coding). Also, I do not see the benefit of deviating from the mathematical convention.

    With the rather new trend to use UTF characters in source code (lambda
    and other greek letter, arrows) the visual distinction between printed
    math and written source gets smaller, so it makes less and less sense to
    use different conventions for the two.

    Best regards

    Axel
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Axel Reichert@mail@axel-reichert.de to comp.lang.awk on Thu May 30 10:22:01 2024
    From Newsgroup: comp.lang.awk

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    People should be anyway aware of the operator precedences in the
    various programming languages

    Sure. I have neither problems with prefix notation as in Lisp or postfix notation as in Factor. It is the infix languages (which boast as an
    advantage to be closer the usual mathematical notation) where I think it
    is crucial to stay close to the mathematical notation, otherwise the
    purported advantage vanishes immediately.

    Axel
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Axel Reichert@mail@axel-reichert.de to comp.lang.awk on Thu May 30 10:24:20 2024
    From Newsgroup: comp.lang.awk

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    There's three power operators in Algol 68 ('UP', '^', '**') each with
    the same default precedence (and each individually changeable.

    As you have mentioned upthread, changing the precedence is scary.
    Obfuscated Algol contest ... (-:

    Axel
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Fri May 31 17:08:23 2024
    From Newsgroup: comp.lang.awk

    On 30.05.2024 10:24, Axel Reichert wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    There's three power operators in Algol 68 ('UP', '^', '**') each with
    the same default precedence (and each individually changeable.

    As you have mentioned upthread, changing the precedence is scary.
    Obfuscated Algol contest ... (-:

    Yes, indeed.

    OTOH, folks who dislike some precedence (cf. '**', as discussed
    here) might then "fix" it to match their own preferences.

    Defining precedences for programmer-defined operations is a good
    thing, but standard operators for standard expressions (however
    they are defined) should be excluded from change; this would be
    my preference.

    Janis

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Fri May 31 17:16:32 2024
    From Newsgroup: comp.lang.awk

    On 30.05.2024 10:22, Axel Reichert wrote:
    [...] It is the infix languages (which boast as an
    advantage to be closer the usual mathematical notation) where I think it
    is crucial to stay close to the mathematical notation, otherwise the purported advantage vanishes immediately.

    Obviously there's other serious opinions differing from this view,
    as we've seen. (It's certainly more comfortable to stay with old
    conventions. Sometimes it's necessary to jettison something if it
    got inappropriate or if there's new aspects that changes weight.)

    Janis

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.awk on Fri May 31 17:46:30 2024
    From Newsgroup: comp.lang.awk

    On 30.05.2024 10:17, Axel Reichert wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    Are you saying that the order
    unary minus
    exponentiation
    binary minus
    is somehow "wrong"?

    It certainly feels like this to me. When thinking about the "why", I
    could see two "arguments":

    1. Unary and binary minus, while not identical operators, at least
    visually are identical. Hence it reduces the cognitive load on the
    reader of source code, who does not need to remember that unary minus
    and binary minus are "on opposite sides of the 'exponentiation fence'".

    I sort this "argument" (quotes borrowed from your text) into the same
    category as "[old] mathematical convention". IMO it doesn't withstand
    the slightest analysis. To explain I'm going back to "Computer Science
    101" as taught in the 1980's (and probably even before)...
    You model expressions with Kantorovic trees (using a homonym '-' here)
    a b c
    \ / |
    '-' '-'
    but what I depicted are different operations, as can obviously be seen.
    Their evaluation in a stack automaton will happen like
    push(a); push(b); subtract() and push(c); negate() respectively.
    If there wouldn't be a distinction and we had, say, a single 'minus()' operation there'd be no indication to reduce that part of expression.

    Same glyph doesn't tell anything in an area (mathematics, but also CS)
    that is meanwhile highly overloaded with symbols.

    In CS we have even more complex situation depending on involved types.
    '**' is a good example also here; 'a**b' is depending on the involved
    types; try (for example in Awk)
    c = 2 ; d = 2.0 ; e = 2.0000000001 ; f = -2.3
    print f^c, f^d, f^e
    There's not one '**' function but actually two under one name
    exp: numeric x int -> numeric
    exp: numeric x real -> real


    2. Mathematical programming is algorithms (often beautifully typeset
    with (La)TeX) transformed into more mundane ASCII-text representations
    (which I see as a technical limitation). Using different operator
    precedence depending on the visual representation is certainly confusing
    if not dangerous (error-prone coding). Also, I do not see the benefit of deviating from the mathematical convention.

    In the first part you seem to just repeat your "argument" 1. above.

    Deviation from conventions makes sense when appropriate. (This had
    been discussed with examples and I think it's worth pondering about.
    I'm glad that the "Burning Witches" convention has been superseded,
    and that "Newton" got fixed by Relativity and Quantum Mechanics. :-)

    Janis


    With the rather new trend to use UTF characters in source code (lambda
    and other greek letter, arrows) the visual distinction between printed
    math and written source gets smaller, so it makes less and less sense to
    use different conventions for the two.

    Best regards

    Axel


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Axel Reichert@mail@axel-reichert.de to comp.lang.awk on Sat Jun 1 09:11:17 2024
    From Newsgroup: comp.lang.awk

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:

    On 30.05.2024 10:17, Axel Reichert wrote:
    1. Unary and binary minus, while not identical operators, at least
    visually are identical. Hence it reduces the cognitive load on the
    reader of source code, who does not need to remember that unary minus
    and binary minus are "on opposite sides of the 'exponentiation fence'".

    I sort this "argument" (quotes borrowed from your text) into the same category as "[old] mathematical convention". IMO it doesn't withstand
    the slightest analysis. To explain I'm going back to "Computer Science
    101" as taught in the 1980's (and probably even before)...
    You model expressions with Kantorovic trees (using a homonym '-' here)
    a b c
    \ / |
    '-' '-'
    but what I depicted are different operations, as can obviously be seen.
    Their evaluation in a stack automaton will happen like
    push(a); push(b); subtract() and push(c); negate() respectively.
    If there wouldn't be a distinction and we had, say, a single 'minus()' operation there'd be no indication to reduce that part of expression.

    How does the low-level computational model of a stack automaton
    invalidate my claim about the reduced cognitive load? When reading
    source code (in an supposedly infix language), I certainly think neither
    about Kantorovic trees nor about an Forth-like (RPN) evaluation model.

    Deviation from conventions makes sense when appropriate.

    Sure. If you can agree with the summary that the disagreement is about "conventions copied from the domain modelled, in this case maths (awk,
    ...) versus consistency (Algol, ksh)", than we can end this (very
    interesting!) discussion.

    By the way, of the latter (consistency), I am a big fan, hence some
    programming language's syntax excessions drive me crazy: "Was it
    'foo(bar)' or 'bar.foo()' or 'foo bar'?" Which is why I have a weak spot
    for Lisps and Forth/Factor. No more earmarks in books with operator
    tables. (-:

    I'm glad that the "Burning Witches" convention has been superseded,
    and that "Newton" got fixed by Relativity and Quantum Mechanics. :-)

    I know what you mean, but rest asured that Newton has NEITHER been
    wronged NOR superseded in the domain relevant to daily life. I would
    have used the wording "extended" rather than "fixed", but can live with
    your choice. (-:

    Thanks and best regards!

    Axel
    --- Synchronet 3.20a-Linux NewsLink 1.114