3

Consider this test case.

function test()
    return 1, 2, 3
end

-- OK: prints 4 1 2 3
print (4, test())

-- NOT OK: prints 1 4
print (test(), 4)

Why do values returned from a function in a function call expression (already pushed to stack) are discarded and narrowed down to a single one, when combined with another value on the right. While at the same time, nothing is discarded when combined with another value on the left.

Is it even possible to extend a set of values returned from a function call to the right, without resorting to table. Because tables have their own issues like counting size by first nil. While nil is a totally reasonable value to pass as function argument as well as return from function, along with some other values.

Subsequently, it's not even possible to do things like this:

local ret = {test()}

-- NOT OK: still prints 1 4
print (table.unpack(ret), 4)
2
  • 1
    "Could not find any mentions of this behavior in official docs" from lua.org/pil/5.1.html: "We get all results only when the call is the last (or the only) expression in a list of expressions" Commented Aug 27 at 7:00
  • @Ivo, thanks. My bad that I have failed to find this. Commented Aug 27 at 7:04

1 Answer 1

4

The design of Lua VM resulted in allowing any number of return values only for function call at the end of the parameter list. This behavior is described in the Lua manual section 3.4.12 – Lists of expressions, multiple results, and adjustment.

Lua VM is known to be register based, unlike stack based VMs, its instructions require specifying registers. For example, calling print (test(), 4) involves the following steps:

  1. Load the print function into R0
  2. Load the test function into R1
  3. Call the test function and save the return value into R1
  4. Load the number 4 into R2
  5. Call the print function

It can be seen that if the test function is allowed to return any number of values, the arrangement of these return values becomes a problem. You can choose:

  1. Load the number 4 into R2 and save the return value of test to R3, R4, ..., but when calling the print function, you have to consider the issue of parameter order, which is obviously too complicated.

  2. Save the return value of test to R1, R2, ..., and then load the number 4 to a dynamic location based on the number of return values (eq to PUSH), but this turns Lua into a stack based VM.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for a detailed explanation of the reasoning behind this choice.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.