On Mon, Mar 28, 2022 at 12:39 AM Sam Hughes <sam.a.hug...@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+unsubscr...@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/CAEkBMfE8omAVr%3DKV1K6my9fckwFp_LEKDWn4hSUFsCz5O_rmxg%40mail.gmail.com.