4 ms·
This doesn't add anything. You get the same protection in Go with pointers. For example, a `*T` can't be passed to a function taking a `T` without explicitly de
by weberc2 6y ago
This doesn't add anything. You get the same protection in Go with pointers. For example, a `*T` can't be passed to a function taking a `T` without explicitly dereferencing it. The problem of course is that the type system doesn't guarantee that the pointer isn't nil when you go to dereference it, similarly your `Option<T>` doesn't guarantee that the option.Value is set correctly. You need sum types to provide this substantial guarantee.
- alkonaut 6y agoIt guarantees that the value is set if the flag is saying it is set (that's the invariant of the type). It screams "check flag before accessing the value". To compare with references which are also 0-or-1-thing effectively: A reference where you as a developer know it's never null but always a ref to exactly one thing is denoted "* T" and a reference to "one thing or null" is denoted "* T"! There is no difference in the types! so you can accidentally send one that is "0-or-1-things" to a method accepting a * T that MUST be a thing. Type system didn't help you document which case it was. Options, apart from the annotation benefit it also helps making the syntax nicer in many cases, with e.g. "or()" fallbacks etc. let data = get_cached().or(load_from_disk()).or_panic();
- weberc2 6y agoI agree that there are semantic issues with pointers, but my point was to illustrate that you need sum types in Go to get any real benefit out of an Option type. If you need an option type and you aren't content with a pointer, you can use `(T, bool)`, but this is still a far cry from a real Option type.
- alkonaut 6y agoI use Option<T> types very happily in C# without sum types. Most of what would be pattern matching can be done with just methods. Car c = maybeCar.GetValueOr(CreateCar()) // inline fallback maybeDog.Do(d => b.Bark()) // only performs call if present Sailboat s = mybeBoat.As<SailBoat>() // none unless of correct subtype And so on. With nullable reference types C# now has a builtin alternative to this, but it has worked we’ll for many years.
- TheDong 6y agoPointers in go aren't a signal for optionality, they're a signal for stack or heap or optionality. They also don't play nice with interfaces. Let's say I have a hashmap that returns a `&T` and I have a `func foo(s Stringer)`. Because 'Stringer' is an interface, it's possible for it to take both `T` and `&T` without a compile-time complaint. In addition, I may wish to have my function `bar(t &T)` always take a pointer because I want the object to exist on the heap, or to be able to mutate its value for the caller. Since pointers mean so many other things, they're not a good way to have a compile-error indicate optionality. On the other hand, if my caller does `hm.Get` and gets an `Option<s: Stringer>`, it's clear what to do to pass it to foo, and if it's an `Option<&T>`, it's clear both that I want a pointer, and that it should be checked / unwrapped. I agree that `T` / `&T` would be just as powerful as option types in go (without sum types) if pointers didn't already have other substantial meaning, and if they could sensibly interact with interfaces. As it stands, I think you're off the mark though. (note: All the asterisks are & because I dunno how to escape stuff on hn)
- bradfitz 6y ago> Pointers in go aren't a signal for optionality, they're a signal for stack or heap No, a pointer in Go doesn't mean that it's on the heap. The compiler keeps it on the stack if it's safe to do so, regardless of whether you're using pointers. You can even write code like `t := new(T); t.Foo()` that very much looks like you're allocating on the heap, but it can stay on the stack, yet t is then a pointer to the stack. Unlike C, you don't need to worry about the heap-vs-stack in Go. It's never even mentioned in the language spec as a concept people need to be concerned with. It's an implementation detail.
- xyzzy_plugh 6y agoThis is not entirely true. You can exhaust stack headroom by calling functions with very large pass-by-value structs. In these situations, you are then forced to use a pointer, which results in heap allocation.
- littlestymaar 6y ago> Unlike C, you don't need to worry about the heap-vs-stack in Go. […] It's an implementation detail. I'm really surprised to read that: yes a beginner can get his code working without wondering about stack vs heap (and that's one of the big reason why Go is easier to learn than Rust for people coming from non-system language), but as soon as you care about performance (which many Go users do!), you need to write code that reduces allocations to the minimum, because Go's allocator is really slow (compared to Java for instance). Interestingly enough, doing so forces you to think about the ownership and lifetime of your objects, like you'd do in C (or Rust).