Some syntactic sugar, like Python’s “with” should help with that, shouldn’t it?
What I meant was something like this (could also be done with `contextlib`, but it's also verbose)
seen_names = {}
class EnsureUnique:
def __init__(self, name: str):
self.name = name
def __enter__(self):
if self.name in seen_names:
raise ValueError(f"Duplicate name: {self.name}")
seen_names.add(self.name)
def __exit__(self, exc_type, exc_value, traceback):
seen_names.remove(self.name)
def bar():
with EnsureUnique("foo"):
do_something()
...
With defer this could be simplified to static seen_names: HashSet<&[u8]> = HashSet::new();
fn bar() {
if !seen_names.insert("foo") {
panic!("Duplicate name: foo")
}
defer seen_names.remove("foo");
do_something();
}Maybe it’s just I’ve never used defer before but I do use python with whenever I get a chance. Not like that, I don’t really understand what the code is trying to achieve by removing the name at the end, but to close resources at the end of the block. And even then only if it makes sense for what I’m doing.
Using a context manager like your example is just busywork IMHO, easier to just write the code out linearly like the defer example.
The most common problem that defer is trying to solve is cleanup when the function returns early (ususally because of an error). Writing the cleanup code inline before the early return results in code duplication.
C#/Java/Javascript have try/finally for this, C has the "goto cleanup" idiom, and C++ and Rust have the guard objects. Go and Alumina have defer.