Live data from Hacker News

Maybe Functions

blog.benwinding.com

81–90 of 103 posts

Re: Maybe Functions

#81
post #37

Earlier quoted context omitted.

> Also, you have to deal with developer mistakes and what happens when they call incorrectly. There is only one safe(ish) way to deal with programmer errors: crash. Hopefully loudly and early enough so it gets discovered in testing.

I assume you don't write device drivers or operating systems? Predicting every possible failure reason for a function is impossible. Every function is a maybe function.

If enumerating every possible failure mode of a function is impossible, then that would underscore the importance of failing fast and dynamically restarting components in order to provide robustness in the face of unforeseeable errors.

Re: Maybe Functions

#82
post #60
post #24

I can't wait for more languages to adopt the "?" operator [1] like the Rust one. It's just syntactic sugar for "if expr null return null" but makes it far easier to write code in a more monadic style. (mostly waiting for this in JS and Go) [1]: https://doc.rust-lang.org/reference/expressions/operator-exp...

I can't wait for more languages to simply not include null at all . It makes trying to spot them in static analysis and runtime checks much easier, because you no longer need either.

In the context of the parent's example, Rust doesn't include null at all, it just has a standard Option type with a None variant. While the other mentioned languages (JS and Go) do have null, they don't necessarily need to remove it to start getting the benefits, they just need to provide standardized alternatives and get the community to follow along (and if, say, a fancy new ? operator only worked on these new types and didn't work on null in general, that would be a strong carrot).

Re: Maybe Functions

#83
post #60
post #24

I can't wait for more languages to adopt the "?" operator [1] like the Rust one. It's just syntactic sugar for "if expr null return null" but makes it far easier to write code in a more monadic style. (mostly waiting for this in JS and Go) [1]: https://doc.rust-lang.org/reference/expressions/operator-exp...

I can't wait for more languages to simply not include null at all . It makes trying to spot them in static analysis and runtime checks much easier, because you no longer need either.

The example of Rust is one where no types are nullable by default, but only if you wrap them in an `Option`.

Given these two function signatures:

    pub fn getUser() -> User

    pub fn getMaybeUser() -> Option
This code won't compile, because `getUser()` cannot return a `None`:

    pub fn foo() -> Option {
        let user = getUser()?;
        return user.name
    }
    
But this code will compile:

    pub fn foo2() -> Option {
        let user = getMaybeUser()?;
        return Some(user.name)
    }

(rust playground link: https://play.rust-lang.org/?version=stable&mode=debug&editio...)

Re: Maybe Functions

#84
post #63

This looks too easy, the first solution. If there is no logged on user, which User object is fetchUser going to return? Which friends? At the top level, if I were to forget to check if someone is logged in, who knows what would happen here. I've worked on codebases where people were so allergic to the "billion dollar mistake" of nulls, that they created empty objects to return instead of returning null. This bit us i…

> This looks too easy, the first solution. If there is no logged on user, which User object is fetchUser going to return? Which friends? At the top level, if I were to forget to check if someone is logged in, who knows what would happen here.

It feels like the most likely thing to happen is that the `getUser()` call would throw a Null Pointer Exception?

I think the author is avoiding the pitfall of the NullObject pattern applied incorrectly with solution #1 because they're not masking the 'null-ness' in the code further down, they're just assuming that `null` will never get passed as a value. If it is, code blows up & then gets patched.

Re: Maybe Functions

#85
post #16

Earlier quoted context omitted.

I think that's true for checked exceptions; in Typescript, I'd rather see that a function may return a null, rather than get surprised by a possible exception that's not telegraphed.

I think that's my biggest problem with exceptions. I have to rely on the doc comments to figure out whether a method can throw exceptions and which and when. And who knows if that covers all the possible exceptions from all the code that method relies on. It entirely sidesteps the type system and means I can't rely on the input/output types when using a method.

> I have to rely on the doc comments to figure out whether a method can throw exceptions

But you still have to rely on the docs to tell if a function can abort execution (say, by calling std::optional::value() when there's no value). And an unhandled exception would abort just the same. Where do you see there being a difference?

> and which and when.

Maybe types don't tell you that either, you still need documentation for that.

Even worse, Maybe types cannot tell you that unless they're leaf-ish functions. Because they may call opaque functions (such as your own callbacks) for which they have no such knowledge to begin with. Thus they have to support propagating some type-erased error type... which is exactly what exceptions do.

So, again: how is the situation different?

Re: Maybe Functions

#86
post #54
post #8

Agreed with this essay, and I think it rhymes with two others that I've found pretty influential over the past five years: 1. Parse, don't validate ( https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va... ) 2. Pipeline-oriented programming ( https://fsharpforfunandprofit.com/pipeline/ ) In my experience, the "best" code (defining "best" as some abstract melange of "easy to reason about", "easy to modify", "e…

Isn't parsing itself a maybe function?

No. Maybe functions aren't the result of simply returning different results. It's doing or not doing something, abstracted into a function.

Parsing is determining whether you should do it or not- it's about setting up a boundary from which you never attempt something that would be a maybe.

Re: Maybe Functions

#87
post #17

Earlier quoted context omitted.

I am for exceptions but it should not be used for basic control flow. Many techs will treat all exceptions as errors.

Interestingly, Python uses exceptions for basic control flow, like end of for-loop.

Well it uses exceptions in the case your generator is at the end, not usually at the end of a for loop because a for loop by definition iterates over a list until the list is finished.

The exception actually occurs when you call next() on a generator which cannot return any more values, or is finished, in which case `StopIteration` is usually raised.

Re: Maybe Functions

#88
post #52

> “Functions should do something, not maybe do something…” But it did do something, it checked if the user logged was logged in first.

Wirth entered the chat:

Procedures should do something. Functions should return something.

https://en.wikipedia.org/wiki/Command%E2%80%93query_separati...

By the way, I have never understood the practice of using a verb in the name of a (pure) function; naming the function after its result using a noun or adjective phrase makes much more sense.

Re: Maybe Functions

#89
post #57
post #22

I feel like there's a whole genre of essays (red vs green functions is the worst example) that could be summarised as: * Monads naturally arise out of many problems in programming. * But I don't want my language to support monads. * So here's something you can do to stay in denial about how much you need monads. At least this example only involves writing hard-to-analyse code and doesn't lead to you trying to invent…

The kicker here is that the author implemented a functor and called it a monad. So of course readers are going to think "the monad approach" is confusing and stay away.

I mean even if you implement a more standard Monad interface plenty of functional programmers still find working with Monads to be ugly. It's really not a solved area.

Re: Maybe Functions

#90
Great point, but I want to bring up another one I'm seeing all the time:

Maybe functions that don't have maybe in their name and just silently don't do something without informing the caller.

This is extremely common and the source of many bugs. If your function is a maybe function, name it accordingly.

Post reply on HN