At the top of the Functions page, it says:
You can specify the return value with a
return
statement, but if your function doesn’t have areturn
statement it will return the last value on the stack.
This is confusing because as far as I can see, this is the only place the documentation refers to "values on the stack", so its unclear what it actually means.
Lower down it repeats this with different wording:
All functions return values in Monkey C. You can explicitly set the return value by using the
return
keyword:<example>
The expression is optional. Functions without a return statement automatically return the last value operated on.
The introduces a couple of new sources of confusion.
First it says "The expression is optional"; but then it goes on to tell you what happens if you leave the statement out altogether (rather than explaining what it does if you leave out the optional expression).
But then what does "the last value operated on" actually mean? Especially as side-effect free expressions aren't allowed at the top level in monkeyc. It sounds a bit clearer than "the last value on the stack", but it still isn't obvious what it would mean in various scenarios.
It turns out that Perl actually has a similar rule for function return values, but it allows you to say things like "$x + 2;" as a statement. So ending a function with an expression is the same as returning that expression. But monkeyc doesn't let you do that (except for function calls). But perl really does use the last evaluated expression as the return value (if you don't give an explicit return statement), so I tried:
function foo() {
var x = 0;
if (x != 0) {
System.println("foo");
}
}
In perl, the last expression evaluated would be "x != 0" so it would return false for the corresponding function written in perl... but no - in monkeyc it returns null. In fact, no matter what code I put in foo (without including a return statement!), it always seems to return null.
So the documentation appears to be wrong on that one.
But what about if you do have a return statement, but don't provide a return expression?
Well again, I found that it pretty much always returns null. With one exception: if you put a "return;" inside a switch statement (anywhere), it returns the value that was switched on.
so eg
function baz(x) {
switch (x) {
default:
return;
}
}
Always returns x. Changing it to
function baz(x) {
switch (x) {
default:
break;
}
return;
}
goes back to returning null (!)
And it still returns null if you remove the return, and just drop off the end of the function
So I'm not quite sure how to resolve this. Maybe the simplest would be to say that a function with no return statement returns null, and that a function that returns via a return statement with no expression, returns an unspecified value? Or that both cases return unspecified values. At any rate, references to the "last value on the stack" and "last value operated on" should probably be removed (or explained).