Ternary operator for luau

Ternary in lua is bad. Any time you do a ternary operation you are interacting with an implicit boolean which can introduce unwanted behaviors if you aren’t paying attention. Also, since lua ternary uses logic operators and and or, it can be difficult to tell at a glance if logical operation is just a ternary operation.

Consider the canonical lua ternary structure:

result = condition and success or failure

This structure doesn’t support a false or nil success value, because it will be overridden by the or failure. Another failure of this structure is that it must evaluate both success and failure when condition succeeds, adding unnecessary processing time. This can be significant if your success and failure values are function calls.

So my suggestion is to add a typical ternary operator to luau:

result = condition ? success : failure

In a traditional ternary structure, failure will not even be evaluated if condition is true. The code branches within the structure so that unintended evaluations and logical operations are avoided.

40 Likes

This can creates ambiguities
Should the piece of code

result = condition?a:b():c():d()

be interpreted as this

result = condition ? (a:b()) : (c():d())

…or this?

result = condition ? (a:b():c()) : d()

I’d suggest Python 2.5’s if else if Luau adopts the ternary conditional

result = success if condition else failure

or ALGOL 60’s (and Ada’s) syntax for this:

result = if condition then success else failure 
9 Likes

That could also be interpreted as

result = condition?(a):(b():c():d())

This syntax is quite complicated to parse, Python was likely able to use it because of how it handles new lines.

local a = b
if c+d+e+f+g+h == i then print(1) end

This is currently valid, and is two separate statements (or three when counting the statement inside of the if).

local a = b
if c+d+e+f+g+h == i else print(1)

Using the Python syntax for ternary conditionals, this would be a single statement. The parser would need to look arbitrarily far ahead to find the disambiguating token (the then or else token) for the if, as an expression would be expected after the if in both cases.

3 Likes

This is incorrect - failure is only evaluated when condition and success is falsy.

But yes, we know this is a problem otherwise and plan to fix it with if expression syntax, e.g. result = if condition then success else failure

30 Likes

Any chance you could be convinced to use the Python-esque success if condition else failure? IMO using only two keywords looks cleaner.

1 Like

We’ve evaluated all sorts of syntactic variants, including this one. There’s two problems with this:

  • The order is all wrong. Only Python does this tmk, and at least in my experience it’s pretty difficult to get used to especially if Python isn’t the only language you use day to day.
  • More objectively, this makes the grammar more difficult to parse, as pointed out by @Halalaluyafail3 above. It requires infinite lookahead or backtracking during parsing, and we do neither as a rule of thumb to keep parsing simple and fast.
7 Likes

P.S. And yeah seeing as the syntax comes from Algol which is also the language family that Lua is broadly in, this felt fitting. Ada requires parentheses around the expression if I recall, which we decided to not require for simplicity.

5 Likes

This is great! It’s certainly better than:
result = (function() if condition then return success; end return failure; end)()

Might I suggest:
result = condition then success else failure

We’re going to type it thousands of times, and that form has fewer tokens to process. Otherwise I might be tempted to use ‘a and b or c’ in some cases (like when b is a truthy constant) because it’s concise with fewer and shorter keywords.

3 Likes

This syntax would be quite complicated to parse inside of if conditions.

if true then print(1)
else print(2) end

This is currently a valid if statement.

if true then print(1)
else print(2)
then print(3) end

Using this syntax, this would be a valid usage of the ternary operator inside of an if statement, but the parser can’t figure this out at the then token, it could be ending the if condition. The parser would have to look ahead to find the end token to be sure that print(3) is the actual code branch (the second then could be another ternary). A more egregious example:

if print(1) then print(2) else print(3)
then print(4) then print(5) else print(6)
else print(7) then print(8) else print(9)
then print(10) end
3 Likes

That’s a very good point.

I would prefer a concise 2 token ternary operator, but I don’t see that happening without it either being either:

  1. Complex to parse.
  2. Not intuitive, with keywords that are not commonly used in this way.
2 Likes

This was also proposed internally and also rejected for the same reason @Halalaluyafail3 brought up.

5 Likes

Would this be valid with the proposed syntax?
result = if condition1 then success1 elseif condition2 then success2 else failure
It would be equivalent to:
result = if condition1 then success1 else if condition2 then success2 else failure

1 Like

Yes luau/syntax-if-expression.md at master · Roblox/luau · GitHub

6 Likes