Hacker News new | past | comments | ask | show | jobs | submit login
Rust, Ruby, and the Art of Implicit Returns (earthly.dev)
3 points by todsacerdoti 7 months ago | hide | past | favorite | 5 comments



I'm fluent in Ruby, and have nearly zero experience in the other languages featured in this article. The `implicit return` is often something people find rather willy-nilly when first learning Ruby. As such, I always thought that was a feature explicit to Ruby and its peers (historical influences like Lisp, Smalltalk, and futures like Elixir and Crystal).

I am surprised and delighted to learn that in fact, many modern languages have been doing this. Particularly seeing this in Rust raised my eyebrows, given how system-focused it is. I'm curious from the Rustaceans out there: Is it common to use the conversational nature of expressions and implicit returns? Or does it frequently create unwelcome dissonance?

Whenever I switch to Python, JS, C#, the explicit returns catch me for a day or two. I always think "We're already reserving this value in memory to evaluate that last line, why don't you let me do something with it if I want?". But I know folks who swing the other direction and feel quite the opposite -- things feel out of place and not-obvious.

Either way, thanks for the well-written article. It has added influence to my "I think I want to look at Rust -- it feels familiar."


GNU C did it decades ago (but of course the GNU project is laced with Lisp influence).

In GNU C, if a braced compound statement is put into parentheses, it becomes an expression. The value of the last expression in the compound is implicitly returned:

  // c receives 5

  int c = ({ int a = 2, b = 3; a + b; })
Never mind that; the standard C macro preprocessor has "implicit return":

  // not return #define max(x, y) return ((x) > ...

  #define max(x, y) ((x) > (y) ? (x) : (y))
Note that the "implicit return" in Lisp is just from mathematics:

  f(x, y) = x^2 - y^2
Not:

  f(x, y) { return x^2 - y^2 }
the return keyword is kind of a disease/blemish, introduced by way of Blub programming languages.

"Implicit return" is like saying "face with implicit warts" in reference to a face that is perfectly smooth and never had a blemish.

In functional languages, there is only one expression which makes up the body of a function and of course that expression's value is yielded; it's the definition of the function.

Explicit return is a form of goto; it's required only in imperative programming, and even there we can leave it out for the last statement.

The C preprocessor doesn't have a return operator because it's a functional, term rewriting language. Every definition has one replacement in which there are no side effects or goto.


The problem is that "implicit return" is the wrong mental framing. Expressions evaluate to a value. That's true in every language that supports expressions. Some just go more all-in on expressions than others do. This is important because

> Is it common to use the conversational nature of expressions and implicit returns?

I have found that most people who do not have experience in expression-oriented languages end up confusing themselves because of it. They'll ask how you're supposed to know where a function returns, when a return can just happen anywhere. But it can't! That's not how it works!

Like any new concept, it can take some time to wrap your head around how it influences how you write code. But I think that the end result is far better. Compare this lambda in C++:

  [](int n, int x) { return n < x; }
to this closure in Rust:

  |n| { n < x }
there are multiple reasons why the Rust is shorter here, and you can argue some of them are better or worse, but not needing the return and semicolon here makes it easier to read, at least for me.

But I think that sometimes people who learn about "implicit returns" write things like iterator chains, that take closures, not even realizing that they're using "implicit returns" in that circumstance. It just feels natural, especially in simple cases like this.

But also, I've been mainly writing in expression-oriented languages for the majority of my professional career, so of course it makes sense to me.


I think that's a great argument to consider when framing this concept to someone the first time. Avoid the `implicit return` language altogether. Instead focus on the expressions. `Implicit` triggers mental responses like "I prefer explicit over implicit" but you're right, that's just a side effect of what's really going on here.


Thank you, and yeah, I didn't even think about that aspect of it too, but you're right. I think the reason it's a popular formulation of the semantic is that it's kind of like, trying to describe it from a statement-oriented viewpoint, and there's certainly value in trying to help bridge an understanding gap by relating it to things that you know. But I worry that it either gives the wrong impression (heck I would hate true "implicit returns" too!) or that people tend to stop there as opposed to truly making the mental shift. This stuff is hard!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: