lua-users home
lua-l archive

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


On Wed, Jan 6, 2021 at 6:00 PM Egor Skriptunoff <egor.skriptunoff@gmail.com> 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 "a|b&c" the calculation starts from bitwise AND.
But sometimes a Lua programmer might be confused by default precedence.

I wouldn't call "a|b&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<<k-1"
 
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<<(k-1)" 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 short-circuit, rewriting it as "test2 or not test1" is more readable and eliminates the need for parentheses.