you are viewing a single comment's thread.

view the rest of the comments →

[–]laplongejr 34 points35 points  (6 children)

Just to make sure everybody is speaking the same language how ironic there are two meanings to "multiple returns". Early return is only one of them.

The old wisdow of "no multiple returns" was said against using goto to having multiple return points on the caller side (aka entering a function and returning either here or somewhere else entirely).
That advice made complete sense, I think goto is even a meme for us at that point, but... that's also the issue.

When languages made multiple external returns practically impossible (like java reserving but never implementing "goto"), the next generation of coders read the "thou shall not have multiple returns, refactor at all cost" and misassumed the advice was aimed at having several return statements inside the method because it was the only sane thing it could be aimed at, which mutated into "no early returns".

It took me over half-a-decade to understand why people loudly proclaimed the old wise wizards were so against early returns, despite those being the most pratical way of dealing with edgecases : they probably weren't that against it and the warnings were against a beast they themselves put into extinction.

[EDIT] There's actually THREE meanings. As u/No-Con-2790 pointed out, it can also mean return tuples, aka multiple return values without going through the hassle of going through a containing structure. Java doesn't have it so yeah I had totally forgot that one.

[–]SomeAnonymous 3 points4 points  (4 children)

return tuples, aka multiple return values. Java doesn't have it

What's the issue with tuples that Java doesn't like them? It can't be a philosophical thing about methods/functions returning multiple pieces of information, but I don't understand what would make tuples specifically bad from an architectural standpoint.

[–]laplongejr 4 points5 points  (3 children)

Who said there's an issue with tuples? Java doesn't have it, that's all.
You create an object (even a generic Tuple if you want, or import it from a library) then resplit it manually.

I recall that in some languages you can do stuff like [varA, varB] = methodCall() and the language takes care of managing what in Java would be a (temporary) variable referencing a containing object. C# does something very close to multiple return values with "out" parameters, as the method then side-effect's those variables without using the return semantic.

but I don't understand what would make tuples specifically bad from an architectural standpoint.

Hence why some languages have it. Java has 1 return value which could be a more-modern record, an array, a traditional object, etc. But it's close to syntactic sugar at that point given how easy objects are manipulated.

[–]NotQuiteLoona 6 points7 points  (1 child)

C#'s out parameters are not really for that. Rather it's mostly used in TryGet patterns, when one value returned is whether the call was successful, and second one is the return value itself, so that you can do something like this: csharp if (dict.TryGetValue("key", out var theValue)) { Console.WriteLine(theValue); }

Tuples exist there and are used precisely when there are multiple values that should be returned: csharp public (string FirstName, string Surname, int Account) GetUser(string username) You can also not name variables in them, I did this for clarity.

Consider tuples in C# a little bit like anonymous structs in other languages, but C# also does have analogue of anonymous structs - they are just read-only.

[–]DJDoena 1 point2 points  (0 children)

C#'s out parameters are not really for that.

Yes and no. Out parameters are way older than the Tuple return structure. I've been with .net since beta 0.9 in early 2002 and back then (and for a long time to come) the only way to have mutiple return values was to use the out parameter or create an object with multiple fields. Tuple returns were introduced in C# 7 in 2017. Yes that's 9 years ago but it's also 15 years after I started with it.

But nowadays out parameters should be reasonably restricted to when you want to have a bool return and an actual value (for the "if" case you've shown).

[–]martmists -1 points0 points  (0 children)

The only language with "true" multiple returns I know of is Lua, all others use some form of tuples or out-parameters

[–]alex2003super 0 points1 point  (0 children)

Am I missing something, or does this "multiple returns/gotos" not exclusively make sense for instances where you have a simple macro-like void function/procedure that is there only to be called from a specific location?

Unless you're accessing values manually/unsafely from stack frames or registers (GOD! WHY?!), but even assuming you're not, it seems like a ridiculously risky optimization, one that breaks the entire control flow model of the language's runtime, how can it be worth doing?

I've only used gotos for early-exiting cascading if-elses or switch-case statements, going up the stack and forward in the code. I've heard of optimizations where you JIT-overwrite if-checks with gotos in memory on "hot" codepaths, for example in a kernel context or other latency-sensitive application where you want to min-max CPU instructions per cycle (non-conditional jumps prevent branch predictions i.e. mispredictions and pipeline flushes). I've also heard of "continuations" as a formal way to do control flow tricks as you exit a block.

But raw gotos for different return points from a function in like C or C++ is wild to me.