Hacker News new | ask | show | jobs
by Mawr 1488 days ago
Great, except:

1. The type is merely a weak hint that you should check .Valid before you use the value, there's no enforcement: https://go.dev/play/p/nS8RxGujMBk

It's much better when the struct members are private and the only way to access the value is through a method that returns (value, bool):

  if value, ok := optional.Get(); ok {
    // value is valid
  } else {
    // value is invalid
  }
This is a strong hint that you should check the bool before using the value. It's also a common go pattern - checking for existence of a key in a map is done this way.

2. We have generics now. Why use type-and-sql-specific wrappers when you could use a generic Option? Example implementation: https://gist.github.com/MawrBF2/0a60da26f66b82ee87b98b03336e....

1 comments

Your comment is helpful, so this sarcasm isn't directed at you. However, this looks like an extremely cumbersome way to wish your language had the Result monad.
I upvoted both your comment and GP. Here, hopefully this helps your comment feel more productive: this is a Result type, albeit yes not a Monad. It’s (AFAIK) the idiomatic way the type is expressed in Go, so maybe cumbersome to implement but trivial to adopt.

It’s also something I realized was lost in the JS progression towards Promise APIs and eventually async/await. Promises have ergonomic benefits over callback hell, but damn if the Node convention of cb: (error, result) => { /* … */ } wasn’t a Result type sitting there begging to be embraced. Again, not a Monad, but it’s a shame the good API design was thrown out with the inconvenient API design.

> extremely cumbersome

I'd say the opposite. I'd say it beats the hell out of Rust syntax, as Rust would force you to have staircase code here. No thank you.

FWIW, that's because Rust also doesn't have a Result monad, it merely has a Result type: in Haskell, you would provide the actual operations of the Monad trait for your Result type--the way in which values are converted into and used from within the type: two functions called return and (>>=)--which would allow you to delegate the execution of that abstracted boilerplate to the language's do-notation.