I was really annoyed that, apparently, I accidentally deleted the message you're replying to, immediately after writing it.
I agree with you about being possibly surprised by values of outside of an expected range. The benefit of the above is merely that accessing it is guaranteed to be checked before dereferencing, converting a panic to a possibly invalid value. When using it, if the quality of value matters, you can check for quality of the value instead of both existence and quality of the value. The reference to TypeScript's traced types was to point at how that kind of behavior is built into the type system, and can't would require modifying one or more steps in the Go compilation process to implement. As for the approach, check out the sync/atomic package. It's a very similar interface. On Monday, March 28, 2022 at 1:37:08 AM UTC-5 axel.wa...@googlemail.com wrote: > On Mon, Mar 28, 2022 at 12:39 AM Sam Hughes <sam.a....@gmail.com> wrote: > >> @Axel, I really did mean what I said. >> > > So did I. > > FTR, if OP would have asked for changes to the type-system to be able to > represent non-nilable types, my response would have been different. I > didn't read their original message as asking for that. > > I didn't say "it's impossible" or "it's a bad idea" to have a programming > language which is more strict about nil-references. I said that it's > impossible to have the Go compiler force you to check for nil-pointers and > a bad idea to have vet do it. I consider every discussion on this list as > starting from the language as it is today. > > The more convenient approach is to implement a type like below. If you >> disagree? So help me....I'll.... I'll disagree with you? >> >> ```Go >> type Box[T any] *T >> >> func (ptr Box[T]) Raw() *T { >> return (*T)(ptr) >> } >> >> func (ptr Box[T]) IsNil() bool { >> return ptr.Raw() == nil >> } >> >> func (ptr Box[T]) Value() (checked T) { >> if blind := ptr.Raw(), ok := !IsNil() bool; ok { >> checked = *blind >> } >> return checked >> } >> > > To me, this seems like it reduces robustness for most programs (assuming > you meant to write `Box[T any] struct { p *T }`, otherwise it's at best the > same). For one, if you have a pointer, you usually want to do something > with that value - getting a new value every time it is dereferenced would > make it really easy to write broken programs. It's also easy for functions > to have non-sensical behavior when applied to the zero value of some type. > > In short, the semantics of "nil-pointers dereference to a new zero-value > of the type" seems extremely brittle and a bad idea to me. > > >> >> I recently saw a talk called "It's all about Tradeoffs". This is an >> excellent example of that. Maybe the above could be improved by static >> checking and optimization, but it's never as cheap as just trusting there's >> something there, so long as there actually is something there. >> > On Friday, March 25, 2022 at 1:41:07 PM UTC-5 Michael Toy wrote: >> >>> The discussion is quite informative for me to read, thanks for >>> responding. Go uses nil in a way which I don't quite yet grok, and so I had >>> no idea if it was even a reasonable thing to wish for. Today I am writing >>> in Typescript, and the way null is integrated into the type system now >>> (after a while) feels natural and helpful to me. >>> >>> Sam is correct, there is bug in my Go snippet in the post. For humor >>> value only, I would like to point out that the imaginary Go compiler I was >>> wishing for would have found that bug! >>> >>> I think Brian gets to the heart of my question, which is "If I really >>> understood Go, would I want something like this". I am hearing, "No, you >>> would not" >>> >>> I think if I were to have a long conversation with Axel about "what is >>> it that makes programs robust and maintainable" we'd go round in circles a >>> bit, as should happen any time you talk about something complex and >>> important. I think I disagree with some statements, but even the >>> disagreement is super helpful. >>> >>> Thanks for the discussion! >>> >>> -Michael Toy >>> >>> On Thursday, March 24, 2022 at 12:22:44 AM UTC-10 Brian Candler wrote: >>> >>>> The OP hasn't said specifically which language or feature they're >>>> comparing with, but I wonder if they're asking for a pointer type which is >>>> never allowed to be nil, enforced at compile time. If so, a normal >>>> pointer-which-may-be-nil would have to be represented as a Maybe[*T] or >>>> union { *T | nil }. To use such a pointer value at runtime you'd have to >>>> deconstruct it via a case statement or similar, with separate branches for >>>> where the value is nil or not-nil. I am sure there have been proposals >>>> along those lines floated here before. >>>> >>>> I don't think this would negatively affect code readability, because a >>>> function which takes *T as an argument can be sure that the value passed >>>> in >>>> can never be nil (the compiler would not allow a value of type Maybe[*T] >>>> to >>>> be passed). Conversely, a function which accepts Maybe[*T] as an argument >>>> is explicitly saying that the value passed may legitimately be nil, and >>>> hence it needs to check for this. >>>> >>>> I like this idea in principle, but in the context of Go it would mean >>>> that *T does not have any valid zero value, so you would not be able to >>>> use >>>> it in any variable or struct which is not explicitly initialized. This >>>> would definitely not be Go any more. >>>> >>>> type T .... >>>> var t T // ok >>>> >>>> var p1 Maybe[*T] // ok >>>> var p2 *T = &t // ok >>>> var p3 *T // fails to compile (no zero value is available) >>>> >>>> type A struct { >>>> a Maybe[*T] >>>> } >>>> var q1 A // ok >>>> >>>> type B struct { >>>> b *T >>>> } >>>> var q2 B = B{b: &t} // ok >>>> var q3 B // fails to compile (cannot create zero-valued instance of >>>> this struct, because it includes a member which cannot have a zero value) >>>> >>>> On Thursday, 24 March 2022 at 09:41:23 UTC axel.wa...@googlemail.com >>>> wrote: >>>> >>>>> One thing to be clear: It is very different if we are talking about >>>>> "emit a warning if a value is known to be nil" and "emit a warning unless >>>>> a >>>>> warning is known not to be nil". The former seems fine to me - it is IMO >>>>> fine for this code to cause a vet-failure: >>>>> >>>>> var x *int >>>>> y := *x >>>>> >>>>> What I'm opposing is the original idea, for this code to cause a >>>>> vet-failure: >>>>> >>>>> func (x *int) { *x } >>>>> >>>>> Importantly, whether or not a value is `nil` is *always* going to be >>>>> a heuristic <https://en.wikipedia.org/wiki/Halting_problem>. >>>>> If we complain about "known to be nil", every finding will always be a >>>>> bug. I don't think it's objectionable to find them statically. >>>>> If we complain about "not known not to be nil", a significant number >>>>> of findings will be non-bugs, leading to changes as OP suggested. So, I'm >>>>> assuming that's the situation we are talking about. >>>>> >>>>> On Thu, Mar 24, 2022 at 9:40 AM Sam Hughes <sam.a....@gmail.com> >>>>> wrote: >>>>> >>>>>> @axel, it my feel counter-intuitive, but a possible runtime panic >>>>>> converted to a compiler error is an increase in how robust the code is. >>>>>> >>>>> >>>>> Of course. But that's not what we are talking about. We are converting >>>>> *some* runtime bugs into compiler errors (really, vet checks, we can't >>>>> fail >>>>> to compile because of backwards compatibility). >>>>> But most of them, where it's not clear from the code that a particular >>>>> pointer is going to be nil, will get the treatment suggested by OP. Which >>>>> ends up exploding the state-space of possible behaviors of a program, >>>>> making it exponentially harder to know what it's doing. >>>>> >>>>> That's IMO the less intuitive thing. People tend to think "crashing >>>>> code is unreliable". But really, crashing is quite a safe and easy to >>>>> reason about behavior. But having to constantly program against any >>>>> possible bug leads to unmaintainable, brittle, impossible to reason about >>>>> code. If every index-expression, every pointer-dereference and every >>>>> method >>>>> call needs to be wrapped in a conditional, it becomes impossible to >>>>> really >>>>> understand where a failure is coming from and how a program behaves in >>>>> different failure modes. >>>>> >>>>> The weird part, at least, why it might feel weird, is that you might >>>>>> never encounter the issue as a runtime panic, but as a compiler error, >>>>>> it >>>>>> will hit you every time. This will make exploring and experimenting with >>>>>> unfamiliar imports, features, and patterns more complicated, but it is >>>>>> the >>>>>> entire point, to my mind, of having a type-system. >>>>>> >>>>>> P.S. Bug in the snippet given by OP? I expected to see "x != nil" >>>>>> instead of "x == nil", or else change comments around. >>>>>> >>>>>> >>>>>> On Wednesday, March 23, 2022 at 4:15:13 PM UTC-5 >>>>>> axel.wa...@googlemail.com wrote: >>>>>> >>>>>>> Personally, I think this leads to very unreadable code, for no real >>>>>>> benefit. >>>>>>> If a nil-pointer dereference happens unexpectedly, that's always a >>>>>>> bug. A panic is the correct signal to tell me about that bug, so I can >>>>>>> go >>>>>>> ahead and fix it. So, making my code less readable to get less robust >>>>>>> code >>>>>>> seems like a lose-lose proposition to me. >>>>>>> >>>>>>> Of course, people can always choose to write/use whatever static >>>>>>> checker they want. I'm not opposed to this existing. I just don't think >>>>>>> it >>>>>>> should be in the compiler or in `go vet`. >>>>>>> >>>>>>> On Wed, Mar 23, 2022 at 10:01 PM 'Michael Toy' via golang-nuts < >>>>>>> golan...@googlegroups.com> wrote: >>>>>>> >>>>>>>> I barely understand Go, so this is likely a stupid idea. Since Go >>>>>>>> uses nil for a lot of things, lots of things can be nil. >>>>>>>> >>>>>>>> I am not a huge fan of the null safe accessor. ( >>>>>>>> https://github.com/golang/go/issues/42847 ) >>>>>>>> >>>>>>>> I am a huge fan of the compiler telling me the places where I have >>>>>>>> not checked for nil ... It took me a while to get used to languages >>>>>>>> which >>>>>>>> do this, but now I can't imagine living without it. >>>>>>>> >>>>>>>> Is it crazy to wish for ... >>>>>>>> >>>>>>>> if x == nil { >>>>>>>> // this does not produce an error because x is known not to be nil >>>>>>>> x.interfaceFunc() >>>>>>>> } >>>>>>>> // this DOES produce an error/warning if y is possibly nil >>>>>>>> y.interfaceFunc() >>>>>>>> >>>>>>>> -- >>>>>>>> You received this message because you are subscribed to the Google >>>>>>>> Groups "golang-nuts" group. >>>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>>> send an email to golang-nuts...@googlegroups.com. >>>>>>>> To view this discussion on the web visit >>>>>>>> https://groups.google.com/d/msgid/golang-nuts/5a700cd9-9274-4756-80a6-9d322232afebn%40googlegroups.com >>>>>>>> >>>>>>>> <https://groups.google.com/d/msgid/golang-nuts/5a700cd9-9274-4756-80a6-9d322232afebn%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>> . >>>>>>>> >>>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "golang-nuts" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to golang-nuts...@googlegroups.com. >>>>>> >>>>> To view this discussion on the web visit >>>>>> https://groups.google.com/d/msgid/golang-nuts/14f6ade8-fe5b-4876-b692-ed98764eaa55n%40googlegroups.com >>>>>> >>>>>> <https://groups.google.com/d/msgid/golang-nuts/14f6ade8-fe5b-4876-b692-ed98764eaa55n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>> . >>>>>> >>>>> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts...@googlegroups.com. >> > To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/adb3260f-d6a8-4672-9a42-52d39a6a3bd9n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/golang-nuts/adb3260f-d6a8-4672-9a42-52d39a6a3bd9n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/4fb90959-0efd-402f-a4d4-3b2c45da81e1n%40googlegroups.com.