So it has been quite a few months since I have dove deep into LUA coding, so excuse any inaccuracies, but I'll do my best to draw out an example.
LUA has a feature that is kind of uncommon in other programming languages called "Multiple Returns" or "Multiple Results". This allows a function to pass back more than one piece of data. This opens a lot of doors to your style of programming. Here is a link to the LUA guide on the topic:
https://www.lua.org/pil/5.1.htmlIt goes something like this. Let's say I write a simple function to return my current coordinates "whereAmI()". Traditional programming might need to specify which axis you want such as xPos = whereAmI(x) and yPos = whereAmI(y), but LUA allows you to do a much more compact call to that function that looks like this xPos, yPos = whereAmI().
The comma denotes each variable that is being assigned a returned value. If you accidentally give it too many variables to return to (such as xPos, yPos, zPos = whereAmI() if the function only returns X and Y), the extra variables will be assigned a value of nil. You do not need to capture all the return values either (such as xPos = whereAmI(), discarding the returned value for Y), however if you want a value that isn't the first one, then you need to capture the first value in a dummy variable (dummy, yPos = whereAmI() ). For this reason it is smart to make sure that your function returns data in the order of importance or likelihood of use.
To get a function to return multiple values, you would enumerate the values on the same return line, delimited by commas. The order of the returned variables will be the same as the order of the function returns. I will show a simple example program below:
local x = 0
local y = 0
local z = 0
x, y, z = myFunction()
print(x..", "..y..", "..z)
function myFunction()
local a = 1
local b = 2
local c = 3
return a, b, c
end
We would expect the output to be "1, 2, 3". This is because the value of "a" has been returned and assigned to "x", "b" to "y", and "c" to "z".
If you don't follow this, let me know and we can discuss deeper.
I'm going to also attach one real function of mine to this if it is helpful. I wrote several modules to work together to handle continuous serial communications with my servo drives to pull diagnostic data. One function (part of the servo communication module) was tasked with reading the DC bus voltage on the servo drive and reporting the number to Mach.
function mcServo.GetBusVoltage(address)
--Test Function to read and return Bus Voltage
--Returns Error String and Bus Voltage as a number
local ES = "" --Error String
local RS = "" --Return String
local RV = 0 --Return Value
local parameter = "08B"
local function = "0"
local serialError = "0"
local busVoltage = 0
local busVoltString = ""
local xmtStr = ""
RS, xmtStr = mcSerial.AppendChecksum(address..parameter..function)
if (RS ~= "") then; ES = "E010101:"..RS ; busVoltage = 0; return ES, busVoltage; end
RS, busVoltString = mcSerial.WriteRead(xmtStr)
if (RS ~= "") then; ES = "E010201:"..RS ; busVoltage = 0; return ES, busVoltage; end
RS, busVoltage = mcSerial.Hex2Num(busVoltString)
if (RS ~= "") then; ES = "E010301:"..RS ; busVoltage = 0; return ES, busVoltage; end
return ES, busVoltage
end
I defined 3 strings "ES" which is a string that may either be empty (no error) or contain an error code that will help me track where the error originated from, "RS" the same error string returned from lower level functions, and "RV" a numerical value returned by Mach 4 functions. Notice after every function call, I check if the RS is empty. If it is, I know the function worked correctly and the data it good. If it is not empty, I append the error string with new information (the location and cause of the error) and return early.
Notice the last line in the code says "return ES, busVoltage". This means I am first returning the error code (hopefully an empty string "") and then the number data for the measured bus voltage.
Whenever I want to know the bus voltage on my address 0 drive, I use the function call errorCode, voltage = mcServo.GetBusVoltage("00"). I must collect the error code first (since it was the first returned value) to determine if the value returned by the function is any good. Sometimes the serial packet comes late and there is an error. By using multiple returns I am able to track when an error occurs and decide what to do about it (I log all the error codes that are returned in case I need to troubleshoot).
This is a rather complicated example of error codes and multiple returns (actually more so than the way NFS handles them) but it gave me a great way to troubleshoot what ended up being some very complicated code.