I subscribe to the common belief that exceptions should be reserved for exceptional situations: actual failures.
You should most certainly profile this code vs. a more traditional approach. I would be surprised if you didn't see a huge performance gap ... throwing an exception is most languages is very costly, and disruptive to the kinds of optimizations that a compiler might make.
I also subscribe to that belief, and it's how I've operated so far in my career in Elixir.
The interesting thing to me about throw/catch in strictly the Elixir context is that I've never actually seen it used for exceptions (or really anything else honestly). Typically the only thing you do with exceptions is rescue them, which isn't common but does come up occasionally. The one example I can think of is that the Bamboo email library until recent versions would raise instead of returning an :error tuple if the third-party email provider like SendGrid didn't send the email successfully, so you were forced to rescue if you wanted to handle an email failure gracefully.
I created a quick Benchee script on your recommendation, and these were the results on my 2013 MBP:
Comparison:
return 6.31 M
throw 3.25 M - 1.94x slower +148.97 ns
**All measurements for memory usage were the same**
Using a throwdoes interfere with tail call optimization, which is one of the tradeoffs you mentioned might be present. It looks like the code with the throw is about half as fast as the one with the return, so there is somewhat of a performance penalty.
I really am not recommending that anyone takes this as a pattern and uses it extensively instead of the usual control flow structures in Elixir. It's just an interesting quirk of the language that a rarely-used BIF plus the elegant syntax for function level catch / rescue handling turns out to implement an early return with surprisingly little ceremony.
EDIT: the original results I posted showed that the throw version was faster, but I realized there was a bug in my script and I was calling the throw version in both cases. I updated it, and the throw version is about twice as slow.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
I subscribe to the common belief that exceptions should be reserved for exceptional situations: actual failures.
You should most certainly profile this code vs. a more traditional approach. I would be surprised if you didn't see a huge performance gap ... throwing an exception is most languages is very costly, and disruptive to the kinds of optimizations that a compiler might make.
I also subscribe to that belief, and it's how I've operated so far in my career in Elixir.
The interesting thing to me about
throw
/catch
in strictly the Elixir context is that I've never actually seen it used for exceptions (or really anything else honestly). Typically the only thing you do with exceptions isrescue
them, which isn't common but does come up occasionally. The one example I can think of is that the Bamboo email library until recent versions would raise instead of returning an:error
tuple if the third-party email provider like SendGrid didn't send the email successfully, so you were forced torescue
if you wanted to handle an email failure gracefully.I created a quick Benchee script on your recommendation, and these were the results on my 2013 MBP:
Using a
throw
does interfere with tail call optimization, which is one of the tradeoffs you mentioned might be present. It looks like the code with thethrow
is about half as fast as the one with the return, so there is somewhat of a performance penalty.I really am not recommending that anyone takes this as a pattern and uses it extensively instead of the usual control flow structures in Elixir. It's just an interesting quirk of the language that a rarely-used BIF plus the elegant syntax for function level
catch
/rescue
handling turns out to implement an early return with surprisingly little ceremony.EDIT: the original results I posted showed that the
throw
version was faster, but I realized there was a bug in my script and I was calling thethrow
version in both cases. I updated it, and thethrow
version is about twice as slow.