← Back to context

Comment by RantyDave

15 hours ago

"A simple cache returns None both for a missing key and for a key that maps to None."

No, it returns KeyError. Or at least it should.

it’s maybe less “pythonic” but at $dayjob we’ve very actively moved away from exceptions for things in favor of things that are statically type checked. too many things that become runtime bugs instead of type checking bugs.

with match now being available, we even return explicit error objects and the ergonomics are pretty good (reminds me of rust).

  • How are these two things related? If you don't use exceptions, you just have to implement them yourself by manually bubbling up the error, all the way up the stack, rather than using the dedicated side channel to do so.

    The problem I see is there's no way to enforce the check that you actually handled/bubbled up the error. With exceptions, you just crash if you don't handle it, which is much preferred if determinism is the goal. Is there some way to use the type system to do this? Maybe incoming are UnhandledResult outgoing are some HandledResult or something like that?

    • If you're going to use the returned value you'd probably return the moral equivalent of Rust's Result/Haskell's Either/etc. types. As long as the returned types don't happen to share the necessary API(s) the type checker should yell at you if you don't branch on the returned value.

      I don't think Python has the equivalent of C++'s [[nodiscard]] or Rust's #[must_use], though, so if there are cases where the return value can legitimately be ignored then return values risk missing errors that would show up under exceptions.

Perhaps the author has had their fair share of run-ins with libraries that didn't think their API through like that. But yes, they should.

  • Very many people have been taught that exceptions are bad and should be avoided, because google avoids them.

    • The adverse knee-jerk hate for exceptions far predates Google also saying they're bad, but certainly that didn't help.

    • Very many people have learnt that exceptions are bad and should be avoided, because they are bad and should be avoided. Some of those people work at Google.

> No, it returns KeyError. Or at least it should.

Surely you meant _raises_? Or did you literally mean to return an exception class?

The author’s example chose to use the syntax that returns None on missing. If they wanted clarity the standard API does raise.

  cache = {“key”: “value”, “some input”: None}
  cache.get(“missing_key”)

Vs

  cache[“missing_key”]

There are better examples that could have been highlighted.