lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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, ...).
You might have formulas like (in case email list does not keep the formatting, LaTeX:  p(t)=\frac{gt^2}{2z} - try https://www.latex4technics.com/):

         g  t²
p(t) = ---------
         2  z            

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 non-trivial 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 <egor.skriptunoff@gmail.com> 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%2-x%3  is not  -x%3-x%2
1<<n-1    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?