How do you feel about exceptions? I always disliked exceptions in C++ and found
comfort in C, which lacks them.
Yet, when I found Nim I realized that exceptions aren't so tricky. Perhaps this
is because of 2 really important features:
* The GC: In C++ you must take extra care to write exception safe code. RAII
and exceptions must go hand-in-hand, and it's a tiring mental overhead. In Nim,
Stuff Just Gets Deallocated (tm). I always associated exceptions with GC
languages, so they fit better into Nim than C++. Of course, we are now
developing a new run-time that will do away with many GC complexities. This
shouldn't affect the exception system though, am I correct? The refcounting
will just be deterministic instead of deferred and cycle-resolving??
* The `defer` keyword: Really this makes resource management doable. Until
destructors are 100% ready it's really The Way to handle non-`ref` types, since
these types can't be "finalized".
So I'm not against exceptions in principle for Nim specifically. However it
would be a good idea to note that many targets of a "systems language" don't
favor exceptions, because they both change control flow and can be expensive
(since Nim targets C++ we can use zero cost exceptions and performance isn't an
issue). The only issue then is philosophical: how does one handle errors? Is it
at the call site w/ a return value (no exceptions - my favorite in general),
through unwinding exceptions (current state of things), through multiple return
values (like Go), through unrecoverable panics (terrible) or through some state
like `errno` (really terrible).
IMO, the only alternative is something like `Result<T, E>` in Rust or Go-like
tuple return values. We would **need** a chaining solution like the `?` in
Rust. I don 't want this:
try:
obj.getInner().upgradeToRwChannel().attachListener(callback)
except Something:
echo getCurrentExceptionMsg()
handle()
... to turn into this:
let inner = obj.getInner()
if inner.isErr:
handle()
let upgrade = inner.upgradeToRwChannel()
if upgrade.isErr:
handle()
let res = upgrade.attachListener(callback)
if res.isErr:
echo res.msg
handle()