lua-users home
lua-l archive

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


an _expression_ can be viewed mathematically as needing a "definition" of the subexpressions used. the _expression_ (x=f()) is still an _expression_ that can be used as a subexpression that must be evaluated only once like in (x=f() and x or 0), which cannot be written equivalently as  (x=f() and x=(f) or 0) because f() would be called twice

So we have to break the whole _expression_ in several parts using a prior statement (possibly within a "begin...end"); this seriously complicates the use of chained exclusive branches (with if...elsif... elsif...else...end) that must be written in embedded subblocks to perform intermediate assignments needed for tests.

Not allowing "if(x=0)" is then clearly not an "issue" (and C/C++/Java compilers or IDE's already help programmers detecting it by seeing that it generates a value that is constant, making one branch of the "if" to be never or always taken: they provide easily warnings, and there's a way to write it explicitly so that this is the intended goal of the programmer and not an unexpected bug), and in fact very useful to get clear code without excessive intrication and embedding of subblocks.
This prohibition in Lua does not really make the code more "readable" and "errorproof" (the risk of programming errors is just moved by forcing them to use a syntax  that is even more errorprone). It just makes the code longer than necessary.

But allowing it now in Lua would cause some problems in some existing instructions, including in simple assignments like: "x, y = 0, z = 1" which assigns 0 to x, and the value of (z=1) to y...

And I still think that the following in Lua: "local x = 0, y = 1" is far superior and much more readable than "local x,y = 0,1" which uses "_expression_ lists" to "explode" them from the first one up to the trailing ones kept in a temporary virtual array that is then "virtually" garbage collected ; actually the array is in a closure (itself in the call stack), not in a Lua table, so there's no garbage collection as the sie of the closure is predetermined.

When Lua functions return multiple values, there's no way to call these functions as subexpressions because it will drop the multiple values (except the first one), you have to use a separate assignement instruction to assign multiple variables from the function call. This means that function calls are not really "legit" subexpressions, using a function call as a subexpression transforms the call by silently applying a destructive typecast (that changes the multivalued type into a single-valued type).

The support of expressions in Lua is in fact quite deceptive, inferior to mathematics, as they are not generalized to all types (the multivalued type in Lua is not a real type we can use, it is bound to the source syntax, just like the special _expression_ "..." which is unusable as a subexpression without silently typecasting it to a single-valued type).

This also made the syntax parsing of Lua expressions more tricky than needed (e.g. for parsing table constructors with "{...}", or for assignments like "x,y=..." allowed but not "x,y=...,0").
This forced Lua to treat specially the "_expression_ list" (created syntaxically with ",", or returned by "..."), and not allowing it as an "_expression_ statement".



Le jeu. 6 juin 2019 à 05:08, Coda Highland <chighland@gmail.com> a écrit :

On Wed, Jun 5, 2019 at 10:01 PM Philippe Verdy <verdy_p@wanadoo.fr> wrote:
The "if(x=0){ ... }" is an "issue" only because the assignment uses the operator "=" which is easily confused with "==" for the equality test.

It was still possible to write the assignment with ":=" (like in Pascal) and still use "==" for the equality test and still not "=" (unlike Pascal), to avoid the second issue with "x=0;" which would have been an _expression_ statement testing x but not using the result.

The final solution was to use ":=" for the assignment, "=" for the equality test, but allow _expression_ statements only after a keyword marking the fact we don't need to store the result, such as "void := x=0;" (needlesss) or "void := f();"; in that case "if(x=0){...}" is correctly performing a test of equality, and "if(x:=0){...}" is an assignment (whose result is false for if so that the block after it is not executed).

That "issue" is not really one, it does not "affect" the langages using "=" and "==". Assignments in the middle of expressions are very useful, and saves lots of lines of code.

That's debatable, and it's also irrelevant. I'm not saying this as a direct "this is bad so it shouldn't be allowed" statement. I actually like assignments as expressions.

But what I described is the history of Lua and the rationale that went into it. Is there another way that it could have been addressed? Sure. But that's not the decision that was made.

It's also a debate that has no bearing on the fact that f(x=0) isn't allowed because assignment is a statement, not an _expression_. The ability to chain function calls has nothing to do with it.

/s/ Adam