
12

Hi!
Usually the order of operations in a Lua expression is quite obvious for a human:
in "a+b*c" the multiplication is calculated first,
in "ab&c" the calculation starts from bitwise AND.
But sometimes a Lua programmer might be confused by default precedence.
For example, I'm still making errors like "1<<k1"
Obviously, it's a good idea to include extra parentheses to improve code readability.
I want to ask your opinion about when redundant parentheses are useful and when they are not.
The following matrix shows my guess of when parentheses should be used.
There are 12 types of operators listed in the "Precedence" section of the Lua manual.
Row = the type of operator being calculated first,
Column = the type of operator being calculated second.
1st\2nd or and ==  ~ & << .. + * unary ^
+
or   ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
and    ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
==    YES ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
      ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
~     YES  ( ) ( ) ( ) ( ) ( ) ( ) ( )
&        ( ) ( ) ( ) ( ) ( ) ( )
<<        YES ( ) ( ) ( ) ( ) ( )
..     YES YES YES YES  ( ) ( ) ( ) ( )
+     YES YES YES YES YES  ( ) ( ) ( )
*     YES YES YES YES YES   ( ) ( )
unary     YES YES YES YES YES    ( )
^     YES YES YES YES YES    YES
"" = parentheses are not needed, the correct order of operations is obvious for any Lua programmer
"YES" = it's recommended to use syntactically redundant parentheses to avoid possible confusion
"( )" = the parentheses are mandatory due to the first operation has lesser priority than the second one
For example,
for "(1<<k)1" the row is "<<" and the column is "+", the cell is "( )".
for "1<<(k1)" the row is "+" and the column is "<<", the cell is "YES".
for "(a and b) or c" the row is "and", the column is "or", the cell is "".
What would you change in the matrix according to your favorite coding style?


On Wed, Jan 6, 2021 at 6:00 PM Egor Skriptunoff < [hidden email]> wrote: Hi!
Usually the order of operations in a Lua expression is quite obvious for a human:
in "a+b*c" the multiplication is calculated first,
in "ab&c" the calculation starts from bitwise AND.
But sometimes a Lua programmer might be confused by default precedence.
I wouldn't call "ab&c" obvious. Yes, I was taught in discrete math class as a freshman that "and" has precedence over "or". But it's not obvious, and not something drilled into every middle school student with mnemonics like "Please Excuse My Dear Aunt Sally" and used unconsciously for years in high school. It's something only comes up occasionally in my experience and so I frequently forget, and now as a college senior, seeing "and" and "or" operations (either logical or bitwise) together without parentheses almost always sends me to the operator precedence section of the documentation to refresh my memory. So I always use parentheses with two or more unlike logical or bitwise operations.
For example, I'm still making errors like "1<<k1"
Obviously, it's a good idea to include extra parentheses to improve code readability.
I want to ask your opinion about when redundant parentheses are useful and when they are not.
The following matrix shows my guess of when parentheses should be used.
There are 12 types of operators listed in the "Precedence" section of the Lua manual.
Row = the type of operator being calculated first,
Column = the type of operator being calculated second.
1st\2nd or and ==  ~ & << .. + * unary ^
+
or   ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
and    ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
==    YES ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
      ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
~     YES  ( ) ( ) ( ) ( ) ( ) ( ) ( )
&        ( ) ( ) ( ) ( ) ( ) ( )
<<        YES ( ) ( ) ( ) ( ) ( )
..     YES YES YES YES  ( ) ( ) ( ) ( )
+     YES YES YES YES YES  ( ) ( ) ( )
*     YES YES YES YES YES   ( ) ( )
unary     YES YES YES YES YES    ( )
^     YES YES YES YES YES    YES
"" = parentheses are not needed, the correct order of operations is obvious for any Lua programmer
"YES" = it's recommended to use syntactically redundant parentheses to avoid possible confusion
"( )" = the parentheses are mandatory due to the first operation has lesser priority than the second one
For example,
for "(1<<k)1" the row is "<<" and the column is "+", the cell is "( )".
for "1<<(k1)" the row is "+" and the column is "<<", the cell is "YES".
for "(a and b) or c" the row is "and", the column is "or", the cell is "".
What would you change in the matrix according to your favorite coding style?
Mainly just the bitwise/logical operations mentioned above. I would also use parentheses like so: "(not test1) or test2" (and the same with "and") to avoid it being accidentally misread as "not (test1 or test2)" (which is a valid English interpretation of the phrase, if not a valid programming interpretation). Of course, if it's not important to shortcircuit, rewriting it as "test2 or not test1" is more readable and eliminates the need for parentheses.


On Thu, Jan 7, 2021 at 2:30 AM Jonathan Goble wrote: "and" has precedence over "or". But it's not obvious
It's obvious because AND has precedence over OR in every programming language.


You seem to have forgotten the presence of NOT : "NOT a AND b" is not evident in common English where it could mean NOT(a AND b), while programming languages most often mean "(NOT a) AND b". Replace "AND" by "OR", this is the same.
With the additional parentheses at least, you won't be fooled by common English, even if "NOT a AND b" has a single interpretation in most programming languages where unary operators like NOT take precedence to binary operators (which is not completely true in Lua, with the exponentiation operator "^" which has higher precedence than the unary minus "", so that "2^2" means "(2^2)" (i.e. the negative value "4") and not "(2)^2" (i.e. the opposite value "+4").
Usually however, we don't need extra parentheses with "(NOT a) AND b" as we are reading a program and not an English book.
Lua however is quite strange with the precedence given to "<<" for bit shifts (wich are comparable to an multiplication with a power of 2), and the concatenation of strings with ".." which has higher precedence than other arithmeric operators "+", "", "*", "/" (but not the power "^") : this is clearly different from other comparable languages and very counterintuitive, but it forces you to surround your numeric expressions into parentheses before concatenating the string converted from the numeric expression.
So you have to write: "0"..(1+2) in Lua to get the string value "03"; with "0"..1+2, you'd get the numeric value 3 and the expression "x="..1+2 would not return "x=3" but a type mismatch error from an attempt to numerically add the string "x1" (not convertible to a number) and the number 2. Le jeu. 7 janv. 2021 à 00:47, Egor Skriptunoff < [hidden email]> a écrit : On Thu, Jan 7, 2021 at 2:30 AM Jonathan Goble wrote: "and" has precedence over "or". But it's not obvious
It's obvious because AND has precedence over OR in every programming language.


On Thu, Jan 7, 2021 at 2:30 AM Jonathan Goble wrote: What would you change in the matrix according to your favorite coding style?
I would also use parentheses like so: "(not test1) or test2"
I agree that "(not x) or y" would look nicer with parentheses.
It seems the "unary" type should behave differently for its two subsets: (#) and ( ~ not)
1st \ 2nd  or and ==  ~ & << .. + * unary ^
+
or   ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
and    ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
==    YES ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
      ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
~     YES  ( ) ( ) ( ) ( ) ( ) ( ) ( )
&        ( ) ( ) ( ) ( ) ( ) ( )
<<        YES ( ) ( ) ( ) ( ) ( )
..     YES YES YES YES  ( ) ( ) ( ) ( )
+     YES YES YES YES YES  ( ) ( ) ( )
*     YES YES YES YES YES   ( ) ( )
unary  ~ not YES YES YES YES YES YES YES YES YES YES YES ( )
unary #             ( )
^     YES YES YES YES YES    YES


There is a thorough Lua coding convention from the LuaRocks project
Is the problem really not that much?
Should I just memorize the Lua precedence rules and stop whining about "operator precedence hell"? :)


On Thu, Jan 07, 2021 at 02:00:05AM +0300, Egor Skriptunoff wrote:
> Obviously, it's a good idea to include extra parentheses to improve code
> readability.
You should include extra parentheses whenever a situation turns up that
needs you, or somebody else who may have to maintain your code in
future, to remember a list of operator precedence to otherwise
understand.
B.


Parentheses are free
In any programming language, as well as plain text documentation, I almost always use parentheses to indicate the exact order of things.
As a corollary, if the parens would end up making the expression unwieldy or too complex then I take that as an indication that the original expression is too complex and I try to rewrite it.
Frank


Since this is probably a matter of opinion, let me add one:
Always add parentheses, except for +, , * and ^, since these are the only ones everybody is supposed to learn in school.
Even / can lead to confusion: a*b/c*d  Usually read by programmers as (((a*b)/c)/d)  Sometimes read by mathematicians as ((a*b)/(c*d)), with / as fraction line
Once you know multiple programming languages with different paradigms, it becomes pointless knowing all precedence rules.
Sometimes you copy some code from one language to another (e.g., prototype with Lua but finally copy some mathematical algorithms to C for performance reasons).
repeat
until (l > (a + b*c));
No bracket required, but readable in one second.
Also properly placed spaces significantly improve readability.
Parentheses are free
In any programming language, as well as plain text documentation, I almost always use parentheses to indicate the exact order of things.
As a corollary, if the parens would end up making the expression unwieldy or too complex then I take that as an indication that the original expression is too complex and I try to rewrite it.
Frank


Hi:
On Fri, Jan 8, 2021 at 10:51 AM bel < [hidden email]> wrote:
> Even / can lead to confusion: a*b/c*d
>  Usually read by programmers as (((a*b)/c)/d)
>  Sometimes read by mathematicians as ((a*b)/(c*d)), with / as fraction line
Am I missing something or did you make a typo ?
Because both the "usually" and "sometimes", ignoring underflow issues,
seem the same to me ( and different from the "even" line ).
Francisco Olarte.


On Fri, 20210108 at 11:09 +0100, Francisco Olarte wrote:
> Hi:
>
> On Fri, Jan 8, 2021 at 10:51 AM bel < [hidden email]> wrote:
> > Even / can lead to confusion: a*b/c*d
> >  Usually read by programmers as (((a*b)/c)/d)
> >  Sometimes read by mathematicians as ((a*b)/(c*d)), with / as
> > fraction line
>
> Am I missing something or did you make a typo ?
> Because both the "usually" and "sometimes", ignoring underflow
> issues,
> seem the same to me ( and different from the "even" line ).
>
> Francisco Olarte.
It seems to me that the first one was meant to read as
 Usually read by programmers as (((a*b)/c)*d)
which is what this expression indeed does as written.

v < [hidden email]>


Hi:
On Fri, Jan 8, 2021 at 2:29 PM v < [hidden email]> wrote:
> On Fri, 20210108 at 11:09 +0100, Francisco Olarte wrote:
> > Am I missing something or did you make a typo ?
...
> It seems to me that the first one was meant to read as
>  Usually read by programmers as (((a*b)/c)*d)
> which is what this expression indeed does as written.
Yep, that's why I asked the OP for clarification.
FOS


On Fri, Jan 8, 2021 at 12:51 PM bel wrote: Since this is probably a matter of opinion
Yes, it is opinionbased.
And I want to know the mean opinion among Lua programmers.
+, , * and ^, since these are the only ones everybody is supposed to learn in school.
Opinions may differ significantly: Schoolkids know nothing except +  * ^
Experienced Lua programmers might get used to all Lua precedence rules.
I want to find the "happy medium" which could be used as a reasonable coding style guide (and be implemented as the default option in a Lua code formatter)
Always add parentheses, except for +, , * and ^
I doubt that overparenthesizing improves code readability. What about the standard chain of bitwise operators:  & <<
and logical operators: or and
IMO, every programming language has their priorities arranged in the same way.
So, even if you're a Lua newbie, but have a strong background in another language, such priority chains look natural to you, so no extra parentheses are needed.
Even / can lead to confusion: a*b/c*d  Sometimes read by mathematicians as ((a*b)/(c*d)), with / as fraction line
"ab/cd" is really treated as "(a*b)/(c*d)" by mathematicians.
Do they use the star character for multiplication?
Sometimes you copy some code from one language to another (e.g., prototype with Lua but finally copy some mathematical algorithms to C for performance reasons).
Facilitating a code migration to another language is not a task for a coding style guide.
There should be special utilities to automate such conversions.
repeat
until (l > (a + b*c));
No bracket required, but readable in one second.
IMO, this code is overparenthesized. The usual Lua format until l > a + b*c
is more readable to me.
Also properly placed spaces significantly improve readability.
What does "properly placed" mean? Are you talking about contextdependent insertion of spaces?
Input example:
f(a+b*c)+g(x*y^z)
Usual rules output: f(a + b * c) + g(x * y ^ z)
each binary operator is surrounded by spaces
Contextindependent rules output: f(a + b * c) + g(x * y^z)
low priority operators + * are surrounded by spaces, highpriority operator ^ is not.
Contextdependent rules output: f(a + b*c) + g(x * y^z)
ranking of operators into low and highpriority depends on the current expression


> > Since this is probably a matter of opinion
> >
>
> Yes, it is opinionbased.
> And I want to know the mean opinion among Lua programmers.
My personal take is as follows. In general, I assume that the following
rules are well known and don't need parentheses:
 Arithmetic (bar exponentiation) and concatentation operations between
them.
 posfix > prefix > arithmetic/bitwise > comparisons > logical (and/or)
(Posfix operations among them have no ambiguity; idem for prefix.)
Everything else is more complex. Some specific cases:
 and vs. or: sometimes I would like to not use parentheses in this
case, but I am not sure how common is this knowledge among average
programmers.
 exponentiation: in Lua, it follows the usual mathematic rules, so
that x^2 is equivalent to x². Again, I am not sure how common
is this knowledge, so I am not always comfortable writing that
without parentheses. Idem for x^y^z (although that case is rare).
 bitwise operations: the rules for bitwise operations among them and
against arithmetic operations are far from obvious. Some could be
considered broken, due to the inheritance from C (where the rules for &,
are "broken" for historical reasons). So, mostly anything in this case
are better written with parentheses.
 comparisons among them (e.g, a > b == (c < d)): comparisons probably
should be non associative, but that is difficult to implement when
the parser is based on precedence tables, as is the case in Lua.
Anyway, we should always use parentheses in those cases: (a > b) == (c < d).
When in doubt whether some expression is clear, it is better to err on
the side of extra parentheses.
 Roberto


On Fri, Jan 8, 2021 at 10:41 AM Roberto Ierusalimschy
< [hidden email]> wrote:
>  exponentiation: in Lua, it follows the usual mathematic rules, so
> that x^2 is equivalent to x². Again, I am not sure how common
> is this knowledge, so I am not always comfortable writing that
> without parentheses. Idem for x^y^z (although that case is rare).
The knowledge may be there, but many (early) computer languages
(Fortran, Algol 68, Ada) did not have any right associative operators
outside of assignments, and unary operators had the highest priority.
Fortran, Algol68 and Ada interpret x**2 as (x)². Python uses the
same interpretation as Lua (for the ** operator). Languages with a C
style syntax (C, C++, Java, Go, C#) don't bother with an
exponentiation operator.
These are not the only things that can trip you up: the "not" operator
in Python has a low priority, just above "and", whereas the "not" in
Lua and the equivalent in most languages has the high priority of all
unary operators. "not a < b" is interpreted as "(not a) < b" by Lua,
and "not (a < b)" by Python. Fortran is similar to Python here.
I would suggest using parentheses when in doubt, because
mathematicians generally agree on the interpretation of expressions,
but programming language designers do not.

Gé


In reply to this post by Roberto Ierusalimschy
On Fri, Jan 8, 2021 at 9:41 PM Roberto Ierusalimschy wrote: exponentiation: in Lua, it follows the usual mathematic rules
BTW, this is my top 3 pitfalls of Lua precedence rules (in the order of decreasing surprise): #str^2 is not (#str)^2 x%2x%3 is not x%3x%2 1<<n1 is not (1<<n)1
I assume that the following rules are well known and don't need parentheses: Arithmetic (bar exponentiation) and concatentation operations between
them.
"Arithmetic with concatenation between them" is intuitively clear.
But I can't wrap my head around concatenation vs bitwise precedence. "message..x+7" is OK, but "message..x&7" is not OK What use cases did you have in mind?


You can always follow the rule:
When confused and in doubt,
Use parentheses all about.
(Taken from Robert Heinlein's
"When in trouble and in doubt,
Run in circles, scream and shout" )
I got taught "Please Excuse My Dear Aunt Sally". Paren, exponent,
multiply, divide, addition subtraction, so that is easy,
If it's code for just me, then parens when needed, if I'm teaching
beginning programmers or someone else may read what I wrote, then all
the parens needed to make it clear the order I/they were thinking.
Taking seconds to add extra parens to save hours is a pretty simple choice.
Foster


Sorry if I first email was confusing.
> Even / can lead to confusion: a*b/c*d
>  Usually read by programmers as (((a*b)/c)/d)
>  Sometimes read by mathematicians as ((a*b)/(c*d)), with / as fraction line
Maybe I should explain in more detail with a real example:
Your coworker might be an engineer, technical mathematician, ... someone who works more with equations than programming (their "home
programming language" is something like Mathcad, Mathlab, Maple, Mathematica, Maxima, ...). g t²
p(t) = 
All variables are double precision floating point numbers (Lua numbers, not integers).
Translating this to:
function p(t) return g * t^2 / 2*z; end
without parentheses contains a bug that is easily overlooked when comparing formula and code.
function p(t) return g*t^2/2/z; end
is correct, but hard to read
function p(t) return ((g * t^2) / (2 * z)) end
is correct, and much easier to read. This seems to be the best form for a review comparing formula and code.
It gets far less obvious if your equations contain compound fractions, or multiple fraction lines of any form.
Fraction lines constitute an implicit bracket not seen in the equation.
Why did I post this example: ) To illustrate even apparently trivial operations such as floating point division might already benefit from additional parentheses
) This is a real world issue. It occurred with graduate professionals working in an interdisciplinary team.
) It is the reason why I consider only the arithmetic operations +  * and one ^ to be innocuous enough, as stated in the my first post.
) Maybe it's an edge use case (starting with an algebra system, developing and stabilizing numerical algorithms in Lua, and maybe transferring them to C afterwards for performance reasons), but it involves 3 different programming languages and transferring algorithms between them (that's what I meant with "copy code" in my first post).
) The resulting code might be used for 20+ years (since the underlying physics does not change), so it's quite likely other people than the original developer will end up maintaining it. ) I know that adding brackets to divisions might be considered extreme or uncommon, so I wanted to provide this point of view.
So, that's my opinion on parentheses in arithmetic and the reason why.
When working in a different environment, you may come to different conclusion.
Regarding bit operations: They are not "every day" operations, unless you develop hardware drivers, network protocols, compression algorithms, etc. (and this is often done in C anyway).
My opinion: Always use parentheses.
Comparisons: See post from Roberto > Anyway, we should always use parentheses in those cases: (a > b) == (c < d).
Another maybe non obvious concept:
If an expressions involves different data types and nontrivial implicit type conversion, use parentheses whenever the data type changes.
#str1..str2>"3" and something
>
(((#str1) ..
str2) > "3") and something or even
((tostring(#str1) ..
str2) > "3") and something
of course #str1 > 3 does not need parentheses
On Sat, Jan 9, 2021 at 2:22 AM Egor Skriptunoff < [hidden email]> wrote: On Fri, Jan 8, 2021 at 9:41 PM Roberto Ierusalimschy wrote: exponentiation: in Lua, it follows the usual mathematic rules
BTW, this is my top 3 pitfalls of Lua precedence rules (in the order of decreasing surprise): #str^2 is not (#str)^2 x%2x%3 is not x%3x%2 1<<n1 is not (1<<n)1
I assume that the following rules are well known and don't need parentheses: Arithmetic (bar exponentiation) and concatentation operations between
them.
"Arithmetic with concatenation between them" is intuitively clear.
But I can't wrap my head around concatenation vs bitwise precedence. "message..x+7" is OK, but "message..x&7" is not OK What use cases did you have in mind?


On Sun, Jan 10, 2021 at 6:23 PM bel wrote: > Even / can lead to confusion: a*b/c*d
>  Usually read by programmers as (((a*b)/c)/d)
>  Sometimes read by mathematicians as ((a*b)/(c*d)), with / as fraction line
Your coworker might be an engineer, technical mathematician, ... someone who works more with equations than programming
This is a real world issue. It occurred with graduate professionals working in an interdisciplinary team.
I see two different problems here. Problem #1 An engineer has modified the code of your project. He had "(a*b)/(c*d)" in his mind, but he has written "a*b/c*d" in the code because he is unaware of Lua precedence rules. But an engineer would probably be unaware of your coding style guides too. So, the problem #1 would be unsolvable by introducing the rule about parentheses and division. Problem #2 You are modifying the project, and you want the engineer from your team to understand math formulas in the code correctly. So, instead of "a/b*c" you are writing "(a/b)*c". This will surely solve the problem #2, but not the problem #1. Conclusion: Despite having newbiefriendly rules about parentheses, an engineer should better avoid writing code :)
A possible solution is to write LaTeXtoLua converter and use the code like the following: local function p(t) local g = .... local z = .... return latex_to_lua_func([[
\frac{gt^2}{2z}
]], "t, g, z" ) (t, g, z) end
The "latex_to_lua_func()" is a memoized converter. Your engineer should modify only the LaTeX string.


So, instead of "a/b*c" you are writing "(a/b)*c".
AFAIU this rule should not be also applicable to the floor division,
because the symbol "//" is not used in math software for division.
For example, in Wolfram Mathematica "x//f" means postfix notation of "f[x]".

12
