cjbottaro
I’ve been primarily doing Elixir development for the past 6 years or so, and during that time whole heartedly committed to functional paradigms.
But recently I did some Go programming, and I hate to admit it, but working with early returns again was kinda nice.
I’m not a fan of lots of small little functions, and using with seems to necessitate that; a lot of the times I’ll just deal with case/if nesting.
So one day, I threw (pun intended) in the towel and refactored a plug that has many success cases as well as error cases that need to return early, to use throw/catch to emulate early returns… and I was really happy with the results.
But there is this nagging feeling that I’ll be excommunicated from the community if this code ever sees the light of day publicly. I kid, I kid… ![]()
So why are early returns bad? I’ve since wrapped up the throw/catch paradigm into a tiny library that let’s it be used like this:
v = returnable do
if some_condition?()
return "foo"
end
...
end
I understand that early returns make mechanical “refactor into function” difficult, but I think wrapping it up in an expression like above negates the issue. Not sure.
I’ve seen some posts (on Reddit, not here) where people suggest you can use throw/catch to emulate early returns “but you need to be an expert to do it safely and properly.” Why is that? What pitfalls are they alluding to?
As always, thanks for the help and info!
P.S. A little further in that video, he describes a use block that he wishes existed, but doesn’t know any programming language that has something like. I’m nearly positive it can be accomplished with metaprogramming in Elixir… but probably a topic for a separate post.
Trending in Discussions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 50 to 41- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
dorgan
One thing about the particular snippet I posted is that the hypothetic
checkfunction wraps a conditional, to avoid ad hoc patterns like this:so instead you’d do this:
Your snippet assumes you already wrote functions that play nicely with
with, while mine is more about the ad-hoc use cases, like checking for a bunch of predicates that are so mundane extracting them too functions would just add lots of verbosity and noise for the sake of usingwithRelated, I don’t particularly like having a specific tag like
:foo_errorinstead of just:errorwith a more descriptive value because it makes it harder to write helpers that can just assume a normalized ok/error tuple. This is one thing I do find useful about ADTs like some people mentioned early, if you can assume normalized shapes, it’s easier to write composable functions.stevensonmt
It’s really interesting how widely varied the stylistic choices one person might like versus another are. I would find that sort of
checkstyle much worse than tagging the steps of awithclause. I actually kind of love the pattern ofdorgan
(?)
Edit: I don’t personally do this but I do have the muscle memory of writing “checks” to make it easier to use
withand not have to “tag” the stepsAs with anything it’s not always the most ergonomic way and compromises are made
cjbottaro
Yes, that’s what I meant. It reduces the nesting and makes it more readable to me.
Also to recap, I don’t want to use early returns pervasively. As most people, I typically reach for
withor even nestedcasestatements (and my tolerance for nesting is probably higher than most here).But in some cases, I think it helps a lot. In our pretty large codebase, I found only two instances where I found early returns compelling. But imo, it made a big difference in these two cases.
stevensonmt
I’m curious what you mean by “fixes” because I think we are thinking about different issues. I think you mean early returns allow you to avoid nesting conditionals, but I just meant that sprinkling returns throughout the conditional branches does not improve readability. I recognize readability is totally subjective so maybe that is where we differ.
cjbottaro
Early returns fixes it for me in a lot of cases…
This discussion has been helpful to me, even if I don’t agree with a lot of y’all. I think what I’m realizing is that I don’t like having lots of small functions, which seems to be the answer to early returns.
stevensonmt
I disagree with this. I think it’s much less readable having to scan a function/method for
returnwhich could occur at any position or even in multiple positions or not at all (at least in Rust). With Elixir you can just start at the bottom and boom, you know what the return should be. Even in a more complex case where the last expression is a conditional of some form you still only have to look through that conditional expression and not worry about the things that came before it. Of course if you’re nesting conditionals 5 deep this is unreadable but that’s not fixable with early returns.dimitarvp
That usually means the functions are too big. Address that and it gets significantly easier.
D4no0
What? Compared to what language? I have to review code in OOP languages and it is just horrible. A class that inherits from a generic class, that implements some kind of logic and some interfaces.
In elixir you have functions that return some data, of course if the function is 300+ lines I can see how it can get hard very fast.
conradfr
Personally the lack of return keyword is not in the pro column
It’s not only about early returns, I just think it has better readability, especially when reading/interacting with code you didn’t write.
I find reviewing PRs in Elixir harder than other languages for example.
But I prefer to use the idiomatic way of the language to do it rather than use throw or other clever tricks to simulate it.