DEV Community

Discussion on: Language Features: Best and Worst

 
idanarye profile image
Idan Arye

Yes, exceptions makes sense. I agree with that. Using the returned value for error handling also makes sense - but only if you don't use exceptions. If the language supports exceptions, and not just aborts/panics - actual exceptions you are expected to catch because they indicate things that can reasonably happen and you need to handle - then you can't argue that using the returned value makes everything clear and deterministic and safe and surprises-free - because some function down the call-chain can potentially throw an exception.

So, if that function can potentially throw, you already need to code in exception-friendly way - specifically put all your cleanup code in RAII/finally/defer/whatever the language offers. And if you already have to do this for all cases - why not just use exceptions in all cases and not suffer from the confusion that is multiple error handling schemes?

Thread Thread
 
isaacrstor profile image
Isaac Yonemoto • Edited

You don't have to cleanup. That's the point. I can't explain it except to say, if you watch enough IT crowd, you might start to agree that sometimes it's okay to just "turn it off and back on again".

If your system is designed to tolerate thread aborts, it's really refreshing and liberating. Let's say I was making a life-critical application. In the event of a cosmic ray flipping a bit, I would much rather have a system that was architected where, say, of the less important subprocesses just panics and gets automatically restarted from a safe state, with the critical subprocesses still churning along, than a system that brings down everything because it expects to have everything exactly typechecked at runtime.

Thread Thread
 
idanarye profile image
Idan Arye

There is still cleanup going on. Something has to close the open file descriptors and network connections. You may not need to write the cleanup code yourself, as it happens behind the scenes, but as you have said - you need to design your code in a way that does not jam that automatic cleanup. For example, avoid a crashing subprocess from leaving a corrupted permanent state which the subprocess launched to replace it won't be able to handle.

One of the main arguments of the "exceptions are evil" movement is that having all these hidden control paths makes it hard to reason about the program's flow, especially cleanup code that needs to run in case of error. But... if you already need to design your program to account for the possibility of exceptions, you are losing the benefit of explicit flow control while paying the price of extra verbosity.

This convention in Elixir to prefer returning a tuple seems to me as more trendy than thoughtful...

Thread Thread
 
isaacrstor profile image
Isaac Yonemoto • Edited

You really don't have to worry about it. The VM takes care of it for you. Unlike go, there are process listeners that keep track of what's going on. File descriptors are owned by a process id, and if the id goes down it gets closed.

As a FP, most stuff us stateless and in order to use state you have to be very careful about it,so there usually isn't a whole lot of cleanup to do in general. As I said, I wrote some sloppy code in three days as a multinode networked testbench for an internal product and it was - it had to be - more stable than the code shipped by a senior dev (not in a BEAM language)

There is zero extra verbosity because you write zero lines of code to get these features.

As for the tuples, I wouldn't call it trendy since it's inherited from erlang, which has had it since the 80s.

I think you have been misinformed about elixir or erlang and suggest you give it a try before continuing to make assertions about it.

Thread Thread
 
idanarye profile image
Idan Arye

You really don't have to worry about it. The VM takes care of it for you. Unlike go, there are process listeners that keep track of what's going on. File descriptors are owned by a process id, and if the id goes down it gets closed.

Yup - higher level languages do that basic stuff for you. But it can't do all cleanup for you. For example, if a subprocess needs to write two files, and it crashed after writing the first file due to some exception, there will only be one file on the disk. You need to either account for the possibility there will only be one file (when you expected there to be zero or two) or do something to clean up that already-written file.

There is zero extra verbosity because you write zero lines of code to get these features.

I talked about verbosity in the no-exceptions style error handling, not the one in the exceptions style.

As for the tuples, I wouldn't call it trendy since it's inherited from erlang, which has had it since the 80s.

Erlang had tuples, but didn't use them for returned value based error handling. At least, not from what I could see with a quick google. Elixir does use them for error handling.

I think you have been misinformed about elixir or erlang and suggest you give it a try before continuing to make assertions about it.

My "assertions" about Elixir is that it uses both exceptions and pattern-matching-on-returned-values for error handling. Is this incorrect?

Thread Thread
 
isaacrstor profile image
Isaac Yonemoto • Edited

At least, not from what I could see with a quick google

ok tuples and error tuples are literally everywhere in erlang. The result type for gen_server start function, for example, is {ok, Pid} | ignore | {error, Error}.