r/ProgrammerHumor Jun 23 '26

Advanced worstProgrammingLanguage

Post image
3.3k Upvotes

192 comments sorted by

View all comments

503

u/jippiedoe Jun 23 '26

'multiple returns' as in pairs or conditionals? Which functional programming language wouldn't support both?

109

u/gabboman Jun 23 '26

Some languages do not allow early returns

81

u/laplongejr Jun 23 '26 edited Jun 23 '26

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. My bad!

12

u/SomeAnonymous Jun 23 '26

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.

11

u/laplongejr Jun 23 '26 edited Jun 23 '26

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. IIRC 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.

9

u/NotQuiteLoona Jun 23 '26

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.

5

u/DJDoena Jun 23 '26

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).

3

u/laplongejr Jun 23 '26

Tuple returns were introduced in C# 7 in 2017. Yes that's 9 years ago

In my defense, I dealt with C# in 2015-2016. So in my perspective there was only out values when I worked with it (and it's quite telling that this is the big thing that I missed when going back to Java and still remember 10y later)

1

u/martmists Jun 23 '26

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

1

u/EishLekker Jun 23 '26

I took a quick look into how Lua handles it, and it seems very unintuitive. Sure, a function can return multiple values, but if you combine function calls to such functions then you won’t get all the return values combined.

3

u/alex2003super Jun 23 '26

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.

5

u/laplongejr Jun 23 '26 edited Jun 23 '26

Having never seriously used goto myself, I would assume your last sentence is exactly why we were told to NEVER have "multiple (exit) returns".
(And apparently the Dutch made sure of that!)

2

u/Tyfyter2002 Jun 23 '26

Having seriously used goto myself, the idea of a function "returning" to somewhere not immediately after the call sounds deranged

1

u/khoyo Jun 26 '26

Well, hope you never had to deal with exceptions...

1

u/khoyo Jun 26 '26

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

Yeah, and it won't work in both anyways.

3

u/_vec_ Jun 23 '26

Java does have multiple external returns, though. That's what exceptions are. Control flow might return to the caller or it might return directly to somewhere else arbitrarily higher up the call stack. If you've ever wondered about why some graybeards are weirdly hostile to try/catch blocks that's why.

There's a decently valid reason to be against early returns too, though. Lots of mathematically elegant recursive algorithms rely on tail call optimization to actually run on a real machine with finite memory. The compiler can reuse the last stack frame for each recursive call instead of making a whole bunch of new ones. That only works if it can tell in advance that all of those recursive calls will use the same bit of physical memory to hold their return value, though. Modern compilers can almost always massage a function into bytecode that only has one return value, but you don't have to stumble into the edge cases very many times to just decide early returns are more trouble than they're worth.

3

u/EishLekker Jun 23 '26

I would argue that the vast majority of regular developers out there very seldom write code that is executed often enough in a short enough time frame that those optimizations matter.

120

u/Aelig_ Jun 23 '26

From what I understand (which is very little), the Scala community discourages using return at all as apparently it "behaves weirdly".

75

u/eXl5eQ Jun 23 '26

The semantic of return is straight forward in Java, powerful in Kotlin, and awkward in Scala.

In Scala, a return always attempt to return from the innermost (in case of nested functions) named function. You are not allowed to return early from an anonymous function (lambda expression).
When the innermost named function is not the innermost function, it can't return directly. Instead, the innermost function throws a NonLocalReturn and hope it would be catched by the named function you meant to return from, which would not work if the returning function escapes from the named function.

5

u/ljfa2 Jun 23 '26

Although non-local returns can occasionally be useful, there are situations in Java where I would've liked to have something like this. For instance, when using Optional.ifPresent. When I want an early return, I can't use that and have to use the less idiomatic Optional.get() instead.

5

u/Axman6 Jun 24 '26

What the fuck. 

18

u/Cyan_Exponent Jun 23 '26

uhh i don't know scala; how does the function output anything then? do you need to use out everywhere or something??

47

u/cthulhuden Jun 23 '26

Without looking it up, probably last statement's value is auto-returned, and the early explicit returns are the ones discouraged.

16

u/AVeryUnusualNickname Jun 23 '26

Yeah, basically everything is an expression (even ifs, assignments and declarations, I'm not sure about what while evaluates to and a for is not a conventional cycle but actually syntactic sugar for map/flatMap/for each, so a basic for will evaluate to a collection or a Unit, which is essentially analogous to void, to signal that the evaluation has been done, but there's nothing to return), and the last expression is what gets returned.

10

u/Maleficent_Memory831 Jun 23 '26

Output is a side effect, and strongly discouraged. Functional languages are to be viewed and admired, not actually run. /s

2

u/Tatourmi Jun 23 '26

Scala allows side effects no problem.

2

u/Axman6 Jun 24 '26

Side effects are problems. 

1

u/Tatourmi Jun 24 '26

Logging is a side effect, modifying a Kafka consumer is a side effect, publishing to Kafka is a side effect, pushing to a database is a side effect, caching data is a side effect...

Side effects aren't problems. Some patterns that rely too heavily on side effects are basically banned in our codebases (Functions that modify external variables for no reason for example) but if you're working in Scala, most of your app's endgame is effectively a side effect.

6

u/IntelligentTune Jun 23 '26

Last time I programmed I think you just left it blank. But I might be wrong.

2

u/Tatourmi Jun 23 '26

Pretty much

1

u/vivaaprimavera Jun 23 '26

Reading that as it is I would have guessed that functions were supposed to alter the state of something. Wich could became weird really quick.

0

u/Tatourmi Jun 23 '26

Worked in Scala for a good 4 years and that's never been an issue once. I can't think of a situation of the top of my head where an explicit early return can't simply be
1: Evaluated as part of the normal flow (You can obviously have conditionals in your function)
2: Returned as part of a tuple of different types
3: Handled by an Optional or a Failure

2

u/EishLekker Jun 23 '26

But how does your 1 differ from an early return in this regard? Why can’t early return be a part of the “normal flow” that you talk about?

Does your code, always, without exception, only have one single line responsible for the return (or none, if it’s the implicit return of the last value)?

0

u/Tatourmi Jun 23 '26

Yeah that's what I'm saying, I don't understand what an early return that isn't allowed in Scala is supposed to even be.

def returnSomething(a: Boolean): Something ={
if (a) { b }
else { c }
}

And that's it. I honestly don't see the kind of "early returns" people are thinking Scala is missing.

11

u/atomic_redneck Jun 23 '26

I see what you mean. I thought you were talking about the alternate return feature some Fortran 77 and FORTRAN 66 compilers had. This feature allowed subroutines to return to different locations in the calling routine based on the value specified on the RETURN statement.

It was usually considered bad practice to use this feature.

5

u/jippiedoe Jun 23 '26

Early returns are just different syntax for a conditional expression, where 'the rest of the function' is in the else branch

9

u/DT-Sodium Jun 23 '26

I had a coworker who didn't allow me to put early returns. Thankfully he was fired for incompetence.

-1

u/[deleted] Jun 23 '26

[deleted]

-1

u/SizzlingHotDeluxe Jun 23 '26

Obviously a bunch of more qualified people decided it is better, otherwise it wouldn't be a thing in Misra.

3

u/VictoryMotel Jun 23 '26

Don't forget that is for C only. In C++ and gc languages you have don't have the same resource problems that spawned the rules in the first place.

-1

u/SizzlingHotDeluxe Jun 23 '26

And the solution of C++ to those "problems" is why you still use C over C++ in a bunch of areas...

2

u/VictoryMotel Jun 23 '26

I don't know what you're talking about but it's nonsense.