Hacker News new | ask | show | jobs
by hmmdar 1641 days ago
Another way to do `Option` without pointers could be similar to the following with a struct with two members.

  type Option[T any] struct {
      v T
      isSet bool
  }
  
  func NewOption[T any](v T) Option[T] {
      return Option[T]{
          v: v,
          isSet: true,
      }
  }
  
  func (o Option[T]) Get() (v T) {
      if !o.isSet {
          return v
      }
      return o.v
  }
  
  func (o Option[T]) IsSet() bool { return o.isSet }

With this pattern you're able to use `Option` as a value without pointers.

  var o Option[int32]
  
  o = NewOption(int32(1))
  
  fmt.Println("value:", o.Get())
  fmt.Println("is set:", o.IsSet())
Alternative separate `Get` and `IsSet` methods, is to combine them into one, similar to map look up pattern.

  func (o Option[T]) Get() (v T, isSet bool) {
      if !o.isSet {
          return v, false
      }
      return o.v, true
  }
  
  var o Options[int32]
  v, ok := o.Get() // zero, false
  
  o = NewOption(int32(1))
  v, ok = o.Get() // 1, true
2 comments

I agree with `Get` returning `(T, bool)` I don't see why one would want to return an `error`.
I don't understand your example, `isSet` is always true and can never be false. Missed something?
It works because it's false when uninitialized (as default value). So if not initialized it represents Nothing value. When it is initialized it's Just T.
The only time `IsSet` would be false is when `NewOption` was not used to initialize the value.

e.g.

  var o Option[int32]
or could have `None` helper

  func None[T any]() Option[T] { return Option[T]{} }

  o := None[int32]()