logoalt Hacker News

norirtoday at 3:32 PM3 repliesview on HN

I have a personal aversion to defer as a language feature. Some of this is aesthetic. I prefer code to be linear, which is to say that instructions appear in the order that they are evaluated. Further, the presence of defer almost always implies that there are resources that can leak silently.

I also dislike RAII because it often makes it difficult to reason about when destructors are run and also admits accidental leaks just like defer does. Instead what I would want is essentially a linear type system in the compiler that allows one to annotate data structures that require cleanup and errors if any possible branches fail to execute the cleanup. This has the benefit of making cleanup explicit while also guaranteeing that it happens.


Replies

simonasktoday at 3:44 PM

If you dislike things happening out of lexical order, I expect must already dislike C because of one of its many notorious footguns, which is that the evaluation order of function arguments is implementation-defined.

About RAII, I think your viewpoint is quite baffling. Destructors are run at one extremely well-defined point in the code: `}`. That's not hard to reason about at all. Especially not compared to often spaghetti-like cleanup tails. If you're lucky, the team does not have a policy against `goto`.

ameixasecatoday at 4:01 PM

> I have a personal aversion to defer as a language feature.

Indeed, `defer` as a language feature is an anti-pattern.

It does not allow the abstraction of initialization/de-initialization routines and encapsulating their execution within the resources, transferring the responsibility to manually perform the release or de-initialization to the users of the resources - for each use of the resource.

> I also dislike RAII because it often makes it difficult to reason about when destructors are run [..]

RAII is a way to abstract initialization, it says nothing about where a resource is initialized.

When combined with stack allocation, now you have something that gives you precise points of construction/destruction.

The same can be said about heap allocation in some sense, though this tends to be more manual and could also involve some dynamic component (ie, a tracing collector).

> [..] and also admits accidental leaks just like defer does.

RAII is not memory management, it's an initialization discipline.

> [..] what I would want is essentially a linear type system in the compiler that allows one to annotate data structures that require cleanup and errors if any possible branches fail to execute the cleanup. This has the benefit of making cleanup explicit while also guaranteeing that it happens.

Why would you want to replicate the same cleanup procedure for a certain resource throughout the code-base, instead of abstracting it in the resource itself?

Abstraction and explicitness can co-exist. One does not rule out the other.

dapperdraketoday at 8:38 PM

Failure is inherently "non-linear" in this sense, unless there is exhaustive case-analysis. That sounds a lot like "just never program a mistake."