Remix.run Logo
galaxyLogic 2 days ago

The way to do functional programming in imperative languages is to handle the side-effects as high up in the call-chain as possible. That would mean that you return an instance of Error from lower-level and decide in some higher caller what to do about it.

That as an alternative to throwing the error. This way you get the benefit of being able to follow the flow of control from each called function back to each caller, as opposed to control jumping around wildly because of thrown errors.

In a statically typed imperative language that would need support for sum-types, to be able to return either an error or a non-error-value. Then you would be less likely to ignore the errors by accident because you would always see the return value is maybe an error.

Isn't this also basically how Haskell does it, handling side-effectful values as high up as as possible which in Haskell means moving them into the runtime system above all user-code?

wesselbindt 2 days ago | parent [-]

Right, I understand. But my question is, how do you _ensure_ a failure value is dealt with by clients? In purely functional languages, your clients have no choice, they'll have to do something with it. In imperative languages, they can just ignore it.

tubthumper8 2 days ago | parent | next [-]

In Rust, there's a `#[must_use]` attribute that can be applied to types, such as Result, and on functions. This triggers if the return value is not used. It's only a warning though, but you could imagine a hypothetical imperative language making this a hard error

nextaccountic 2 days ago | parent [-]

#![deny(must_use)] on the root of your crate makes it a hard error for your whole crate.

Typically what happens is that having this set on is very annoying while developing code, because we often want to test incomplete code without proper error handling before we finish it. So sometimes people will block on this kind of issue in CI, but not error out during development (a warning is more than enough)

galaxyLogic 2 days ago | parent | prev [-]

Failing to detect a result as error-value is a good failure case to be aware of. But I think if you throw an error it is also possible for a client to fail to handle it properly. No Silver Bullet.