1

As summary states. Lets say I want o resolve my ReturnFunction in a ternary operator fashion. Well, as far as I know, as long as my function returning several values (ReturnThreeValues) is placed at LAST position after ReturnFunction's return, the three values it gives should be returned by ReturnFunction if the ternary operator do what I think is the expected here, but for some reason it keeps returning ReturnOneValue's value even when n == nil (because I'm not including it when calling). It can be seen & tryed here:

<script src="//github.com/fengari-lua/fengari-web/releases/download/v0.1.4/fengari-web.js"></script>
<script type="application/lua">

    function ReturnOneValue(t, n)
        n = n or 1
        return t[n]
    end

    function ReturnThreeValues(t)
        return t[1], t[2], t[3]
    end

    function ReturnFunction(t, n)
        return n ~= nil and ReturnOneValue(t, n) or ReturnThreeValues(t)
    end

    local t = {"One", "Two", "Three"}
    local r1, r2, r3 = ReturnFunction(t)

    print(r1, r2, r3)

</script>

Well, basically I don't get why my print result is being: "One nil nil" and not: "One Two Three" as it should be, if the ternary operator was working as (I think is the) expected... Or is there something I'm not taking into account when it comes to resolve a multi-return function in this ternary way?

EDIT:

FTR (and just in case is useful for anyone), after doing some more research I got to find this other question with a possible workaround and turns out it works, as can be seen here:

<script src="//github.com/fengari-lua/fengari-web/releases/download/v0.1.4/fengari-web.js"></script>
<script type="application/lua">

    function ReturnOneValue(t, n)
        n = n or 1
        return t[n]
    end

    function ReturnThreeValues(t)
        return t[1], t[2], t[3]
    end

    function ReturnFunction(t, n)
        return n == nil and {ReturnThreeValues(t)} or {ReturnOneValue(t, n)}
    end

    local t = {"One", "Two", "Three"}
    local r1, r2, r3 = table.unpack(ReturnFunction(t))

    print(r1, r2, r3)

</script>

However, I'm not going to considerate it the right solution to the problem due to in the end it's more convoluted than what I was expecting to find, and I don't think the added complexity would worth after all... It's clear the way to go would be more in the line LMD suggests. Even though, after some consideration, I'm going to mark Nicol's answer as the right one, since he explained very well the why of such behavior and what was really happening under-the-hood, and that's what this question was actually more about. Well, thanks to everyone and I hope it makes sense.

Rai
  • 314
  • 1
  • 2
  • 9

2 Answers2

5

Lua doesn't have a "ternary operator". What Lua has are and and or operators which only consider the values nil and false to be non-true. As such, X and Y resolves to X if X is non-true, and Y otherwise.

However, expressions like and and or cannot handle multiple values. A function call can be used in certain places that can handle multiple variables (the initializer for a series of variables or a table, for example). But if a function call is used in other places (such as being the operand of an expression, like and and or), the return values are truncated down to a single value.

What you're trying to do is not directly possible in Lua. It treats multiple values as a kind of special case circumstance, not one that can survive contact with most expressions.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • So at some point the multi-return gets truncated, that's more or less what I was afraid, but I kinda hoped it could be somehow "patched" by using some kind of parenthesis _trick_ or something... About the ternary, I'm conscious strictly Lua doesn't have it and therefore it has some limitations, but it's been working as expected here in all cases but this one. Well, good to know! I like to solve things in this _ternary way_ when possible, but there're fortunately plenty of ways this kind of functions could be made workable (it will just take some more lines plus maybe an extra variable or so). – Rai Oct 24 '22 at 02:50
  • BTW, is it a bad practice the fact of including a Code Snippet or something? If so, no problem with that... but just wondering why – Rai Oct 24 '22 at 02:53
  • @Ramon0: You'll notice that the tooltip for what you call "Code Snippet" says, "Javascript/HTML/CSS snippet". Lua isn't one of those, so it's not appropriate for that. Just use a regular code block. – Nicol Bolas Oct 24 '22 at 02:55
  • But maybe it's because I failed to include the correct code that make it work with Lua, then I quickly edited and it kept perfectly workable. It could be that maybe you saw it when it wasn't and that's the reason you edited? Sorry, just want to be sure that was not the cause, because they seem to me very useful... – Rai Oct 24 '22 at 03:18
  • @Ramon0: I don't know what to tell you. The thing you're looking at right now is made of Javascript, HTML, and CSS. The tool you're looking at it on is built to execute arbitrary Javascript, HTML, and CSS. That's what the snippet tool does; it makes a webpage that executes those things because that's what browsers do. Lua is not a thing your browser understands. So that tool will not work on it. – Nicol Bolas Oct 24 '22 at 03:22
  • Yeah, I understand that, but I've been using the method/workaround described [here](https://meta.stackoverflow.com/a/394310/2805176) for making it work also with Lua and, besides it seems to always work like a charm here, I don't see disadvantages on using it since, even should it stopped working someday, the relevant piece of code would still continue being visible... Well, I just edited my question so that you can see it, but feel free to re-edit if you still think there could be an issue with it. – Rai Oct 24 '22 at 14:05
5

The fix for the problem as described by Bolas' simply is to use an if and another return; no variables are needed:

function ReturnOneValue(t, n)
    n = n or 1
    return t[n]
end
    
function ReturnThreeValues(t)
    return t[1], t[2], t[3]
end
    
function ReturnFunction(t, n)
    if n == nil then
        return ReturnThreeValues(t)
    end
    return ReturnOneValue(t, n)
end

another advantage of this is that it will correctly deal with falsy return values.

Luatic
  • 8,513
  • 2
  • 13
  • 34