• Subject: Re: Ternary operator patch
• From: David Manura <dm.lua@...>
• Date: Sat, 11 Sep 2010 00:13:04 -0400

```On Fri, Sep 10, 2010 at 5:15 PM, Patrick Donnelly <batrick@batbytes.com> wrote:
> a = b then x else y

That is problematic, as pointed out by Fabien [1].  Compare:

if a then b() else c() then d() end -- confusing
if if a then b() else c() then d() end -- ok

> a = x when b else y
> That messes up the usual order so it's unlikely to be accepted.

This form also implies we can't use the "elseif" keyword in the usual way:

return x if a else
y if b else
z

> The "b and x or y" idiom is just too confusing to
> newcomers. Most don't ever learn what it really means and get bitten
> by bugs when x is false/nil.

I don't disagree, but the ternary operator might not eliminate such
idioms.  Looking at my own code, I have used and may continue to use
things like

x = x or 1
-- i.e. if x==nil then x = 1 end
-- i.e. x = if x then x else 1

local s2 = s and s:gsub(" ", "")
-- i.e. local s2; if s ~= nil then s2 = s:gsub(" ", "") end
-- i.e. local s2 = if s then s:gsub(" ", "") else nil

print(t and t[1] and t[1].tag or 'notag')
-- i.e. local v='notag'; if t and t[1] and t[1].tag then
v=t[1].tag end; print(v)
-- i.e. if t and t[1] and t[1].tag then t[1].tag else 'notag'
-- Here: the intention *is* to print 'notag' if t[1].tag is nil.

The ternary operator does lengthen the syntax, though not greatly and
not at the expense of clarity.

All forms do suffer, however, from the different problem of
reevaluation: in a chain of "<expr1> and <expr2> and <expr3> and ...",
we would prefer to allow expressions to refer to temporaries in
previous expressions:

print(if t and t[1] as t1 and t1.tag as tag then tag else 'notag')
-- explicit naming
print(if t and _1[1] and _2.tag then _3 else 'notag') -- implicit naming
(Note: 5.2.0-work4 anonymous closure caching helps speed but not syntax.)

What about expression lists in ternary operators?  There's a question
of relative precedence to the comma:

function f() return 1,2 end; return if x then f() else z, f()

That also deceptively looks like a "postfix if" [2] as in Perl (i.e.
"f() if x" means "if (x) { f() }").  It's doable though.

[1] http://lua-users.org/wiki/TernaryOperator
[2] http://lua-users.org/wiki/MetaLuaRecipes

```