6 ms·
> non-nilness Ah, I still remember this thread: https://groups.google.com/g/golang-nuts/c/rvGTZSFU8sY/m/R7El8FKhmPQJ https://groups.google.com/g/golang-nuts/c
by LudwigNagasena 2y ago
> non-nilness
Ah, I still remember this thread:
https://groups.google.com/g/golang-nuts/c/rvGTZSFU8sY/m/R7El8FKhmPQJ https://groups.google.com/g/golang-nuts/c/rvGTZSFU8sY/m/R7El...
- yencabulator 2y agoEveryone just keeps repeating the same old gripe, without bothering to read the responses. Go needs a null-like thing because the language forces every type to have a zero value. To remove the concept of zero value from Go would be a major change.
- unscaled 2y agoThe responses from Ian and the Go fans are not very well-thought. To begin with, zero values were never a great idea. It sounds better than what C does (undefined behavior), but zero values can also hide subtle bugs. The correct approach is to force values to always be initialized on declaration or make use-before-initialization an error. Having said that, it was probably too late to fix zero values by 2009, when Go was released to the public, and this is not what the thread's OP suggested. He referred to Eiffel, which is an old language from the 1990s (at least?) that didn't initially have null-safety (or "void-safety" in Eiffel's case), but released a mechanism to do just that in 2009, shortly after Tony Hoare's talk at QCon London 2009 (no idea if they were influenced by the talk, but they did mention the "Billion Dollar Mistake" in the release notes). Eiffel's added nullability and non-nullability markers to types (called "detachable" and "attached"), but it's also using flow-sensitive typing[1] to prevent null-dereferencing (which is the main cause for bugs). The thread OP didn't ask to eliminate zero values or nullable types, but rather requested to have a non-nullable pointer type, and flow-sensitive typing. If structs need to be zero-initialized, a non-nullable pointer could be forbidden in structs, or alternatively Go could make explicit initialization mandatory for structs that have non-nullable pointers. At the very least, Go could support non-nullable pointers as local stack values, and use flow-sensitive typing to prevent null dereference. [1] https://en.wikipedia.org/wiki/Flow-sensitive_typing https://en.wikipedia.org/wiki/Flow-sensitive_typing
- yencabulator 2y agoIf there's a non-nullable type, then there's types without zero values, and that means some basic properties of Go no longer hold. I don't know how many times that can be said differently. Whether something is in a struct or not is not relevant.
- LudwigNagasena 2y agoWhat basic properties no longer hold?
- yencabulator 2y agoUninitialized variables are zero. Composite literals may omit fields, and they'll be zero. Map accesses for nonexistent keys return zero values. Channel receives from closed channels return zero values. make returns zero-valued slices. Comma-ok style type assertions return zero values. Slices are fat pointers where the zero value avoids an allocation for data.
- LudwigNagasena 2y agoThat would still hold. Those things just wouldn’t be typed as non-nullable.
- yencabulator 2y agoNow you're creating a flavor of types that cannot be used in many places. Or worse, a flavor of types that when added to a struct breaks existing uses. That'd be a major change.
- LudwigNagasena 2y ago> Now you're creating a flavor of types that cannot be used in many places. Yeah, that’s the entire point. Type safety.
- deergomoo 2y ago> "Go doesn't have nullable types in general. We haven't seen a real desire for them" Ouch, who were they asking? There are so many problems from even the most simple CRUD apps where "lack of a value" must be modelled, but where the zero-value is a valid value and therefore an unsuitable substitute. This is probably my single biggest pain point with Go. Using pointers to model nullability, or other "hacks" like using a map where keys may not be set, feel completely at odds with Go's stated goal of high code clarity and its general disdain for trickery. I know with generics it's now trivially easy to implement your own Optional wrappers, but the fact that it's not part of the language or even the standard library means you're never going to have a universal way of modelling this incredibly basic and common requirement across projects. It also means you're never going to have any compile-time guarantees against not accidentally using an invalid value—though that's also the case with the ubiquitous (value, error) pattern and so is evidently not something the language is concerned with.
- p1necone 2y agoWow, that discussion is infuriating. I'm shocked that many people on there don't seem to understand the difference between compile time checks and runtime checks, or the very basics of type systems.
- skybrian 2y agoI think people do understand the basics of static type systems, but disagree about which types are essential in a "system language" (whatever that is). An integer range is a very basic type, too, conceptually, but many languages don't support them in the type system. You get an unsigned int type if you're lucky.
- fooker 2y ago> An integer range is a very basic type, too, conceptually Just signed vs unsigned makes this a complex topic.
- edflsafoiewq 2y ago> An integer range is a very basic type, too Not really, its semantics get hairy almost instantly. Eg does it incrementing it produce a new range?
- randomdata 2y agoThe semantics are always complex. The same type of question arises for all basic types. For example, what does adding a string to an integer produce? Or do you give up on answering that and simply prevent adding strings and integers? When one wants to add them they can first manually apply an appropriate type conversion. That is certainly a valid way to address your question – i.e. don't allow incrementing said type. Force converting it to a type that supports incrementing, and then from that the developer can, if they so choose, convert it back to an appropriate range type, including the original range type if suitable. Of course, different languages will have different opinions about what is the "right" answer to these questions.
- thayne 2y agoWow, that's painful to read. Separating the concept of pointers and nullable types is one of the things that I think go having from the beginning would have made it a much better language. Generics and sum types are a couple of others.
- ahoka 2y agoFalse things programmers believe: All reference types should be able to take a null value. It's impossible to write complex and performant programs without null. It's impossible to write complex and performant programs without pointers. References always hold a memory address in a linear address space. (Not even true in C!) Every type is comparable. Every type is printable. Every type should derive from the same common type. All primitive types should support all kind of arithmetic the language has operators for. The only way to extend an existing type is to inherit from it. What else?
- bayindirh 2y ago> It's impossible to write complex and performant programs without pointers. Well, I'd rather not copy around a multi-hundred-megabyte (or gigabyte) 3D object around to be able to poke its parts at will. I'll also rather not copy its parts millions of times a second. While not having pointers doesn't make impossible, it makes writing certain kinds of problems hard and cumbersome. Even programming languages which do not have pointers (cough Java cough), carry pointers transparently prevent copying and performance hits.
- marcosdumay 2y agoWell, looks like the GP missed a very common false fact: The operations written in a program must literally represent the operations the computer will execute. This one stops being true on high-level languages at the level of x86 assembly.
- bayindirh 2y agoExactly. A MOV is reduced to a register rename. An intelligent compiler can rewrite multiply/divide by 2 as shifts if it makes sense, etc. "Assembly is not a low level language" is my favorite take, and with microcode and all the magic inside the CPU, it becomes higher level at every iteration.