Is RETURN essential at end of scene script?

Ever since i?ve had my veralite, over 6 years now on UI5, i?ve not included return at the end of my lua script unless i want it to act on a device, ie check some conditions this then return true/false to enable/disable/ignore device X,Y,Z, etc.

Some of my code does not trigger devices, perhaps just executing script and completing its task completely within the lua.
Should i still put return at the end of the lua script even if no further action is required?
It seems to have run fine for all these years but maybe this acounts for very occasional errors or perhaps its just good programming practice? (Maybe the system allows for this?)

Can anyone confirm please

[quote=“UKsub, post:1, topic:200423”]Ever since i?ve had my veralite, over 6 years now on UI5, i?ve not included return at the end of my lua script unless i want it to act on a device, ie check some conditions this then return true/false to enable/disable/ignore device X,Y,Z, etc.

Some of my code does not trigger devices, perhaps just executing script and completing its task completely within the lua.
Should i still put return at the end of the lua script even if no further action is required?
It seems to have run fine for all these years but maybe this acounts for very occasional errors or perhaps its just good programming practice? (Maybe the system allows for this?)

Can anyone confirm please[/quote]

In theory, with only Lua in the scene and no actions, there’s no problem it could cause. In practice, you are at the mercy of Vera’s implementation, which is unseeable and therefore unverifiable.

It will not cause problems, and likely avoid them, to always return true or false from scene Lua. I’ve seen things go wrong in this context without a return value, but I’ve never seen code with a boolean return value do something unexpected.

Learning something here. Most of my lua code actually does not close with a return statement and I have never seen anything bad from it. Then they are almost all on openLuup so it might be different. The only return statements I have are conditionals for the entire scene.

openLuup we can see and verify. The version I’m running (2018.11.21) has the following test of the scene Lua return value (which it receives into the local variable [tt]ok[/tt]): [tt]if ok == false[/tt]

This means that the scene Lua return value has to be exactly boolean type value false (and nothing else) to prevent the scene actions from running. Anything else returned, including nothing/nil, will allow the scene to run. So akbooer has, predictably, chosen the safest implementation.

But that may not be Vera’s implementation, and perhaps some testing will reveal clues about what they do. If their test of the return value is, for example, [tt]if not sceneReturnVal[/tt], then Lua would stop the scene actions for boolean false, but also stop it if the scene returned nothing/nil. It would run the scene actions if the scene returned 1 or “1”, which are common Luup values meaning true/on, but it would also run them if the scene Lua returned 0 or “0” (common Luup values meaning false/off) because in Lua (5.1) all logical operators accept false or nil as false and anything else as true.

So, I’m diving a bit here, but where I’m going is this, back to my original statement, if you always return true or false, the result is always predictable and safe (on both Vera and openLuup).

Thanks for the replies.

Similarly, is it valid or might it cause a problem to close script with just return without being followed by true or false?

@rigpapa

As described, boolean [tt]false[/tt] is the ONLY return value which will stop a scene. openLuup is like this because Vera does this.

As per standard Lua, [tt]return[/tt] at the end of a function is implicit, and the same as writing [tt]return nil[/tt].

Yes, I’ve now confirmed this via testing, so that is the definitive answer: IT IS NOT NECESSARY FOR A SCENE TO RETURN TRUE; IT MAY RETURN FALSE.

I stand corrected that returning true is necessary. I still think it’s advisable/good style, but it’s not strictly necessary.

As per standard Lua, [tt]return[/tt] at the end of a function is implicit, and the same as writing [tt]return nil[/tt].

Actually, this statement is not correct, and I think it was you who actually previously identified where in Luup this is troublesome, but to clarify:

It depends entirely on how the code receiving the return values is structured. A [tt]return[/tt] at the end of a function (implicit or otherwise) with no return values returns nothing, and that is different from returning nil. A more correct statement would be: all functions return a list of values, which may be empty. If the function has a return statement with no values, or contains no return statement (implicit return), then the return list is empty (zero length). Otherwise, the return list has length equal to the number of values in the return statement, and nil is a valid value. Thus [tt]return[/tt] on its own returns a list of zero length, but [tt]return nil[/tt] returns a list of length==1, where the one value is nil.

The fact that you get [tt]nil[/tt] when receiving return values into variables is an artifact of how the return list is assigned to the variables. All return variables are assigned ordinally–the first return value to the first receiving variable, the second return value to the second variable, etc. If a return variable’s ordinal position exceeds the length of the return list, it is explicitly assigned [tt]nil[/tt]; if the return list is longer than the receiving variables list, the excess return values are simply ignored.

[code]function test()
return “a”, “b”
end

local a,b,c,d = test()
print(a,b,c,d) – prints: A B nil nil[/code]

But in other contexts, the realities of Lua implementation are apparent. Take the case of a function wrapping another function, like: [tt]tostring( test2() )[/tt]:

[code]function test2()
return – nothing
end

– This fails!
print( tostring( test2() ) ) – runtime error: stdin:1: bad argument #1 to ‘tostring’ (value expected)

– But this works, because the receiver is assigned nil by list assignment
returnval = test2()
print(returnval) – prints: nil[/code]

So you can see that by receiving the function return into a variable (or variables), it APPEARS to return nil, but that’s not actually what is happening, and the fact that [tt]returnval[/tt] gets nil is an artifact/side-effect of the code structure, not how Lua actually returns values from a function.

And a further example showing this (adding code to the previous example):

[code]function howmany(…)
print(“I see”, #arg, " arguments!")
end

howmany( test2() ) – prints: I see 0 arguments![/code]

Again, I believe it was you that pointed out at least one example in Luup where an empty return list (nothing) is returned, rather than nil. I don’t recall what function that was, but I know [tt]luup.variable_get()[/tt] is such a culprit–if you request a variable for which the service or variable does not exist in user_data, the function returns nothing, and passing that directly to another function (like [tt]tostring()[/tt]) will get you into hot water. And of course, that same function is troublesome for functions like [tt]tonumber()[/tt] for a similar reason: it returns more than one value, but most people ignore that, and so many code examples people pass around receive only the first return value that I think most people aren’t even really aware that the function returns multiple values. But they quickly find out when they attempt to do the apparently sensible but actually incorrect [tt]tonumber( luup.variable_get( service, name, devnum ) )[/tt] (which doesn’t work as expected and should never be done).

Yes, you’re right that I did.