News for hackers. Stuff that matters.
Re:Go nulls and SQL by xdfgh1112 on Monday May 23, 2022 @03:23PM (#31483776)
Sane languages have pointers which either can't be null or require you to check explicitly. Rather than leaving it to explode at runtime.
Re:Go nulls and SQL by tedunangst on Monday May 23, 2022 @03:38PM (#31483934)
Tell me more about these unexplodable languages.
Re:Go nulls and SQL by dtech on Monday May 23, 2022 @03:53PM (#31484073)
If this question is in good faith, for example Kotlin differentiates between the nullable T? and the non-nullable T. An if x != null check automatically casts T? to T. You can't call a method on T?, preventing null pointer exceptions. C# and Typescript have similar language support. Other languages push users away from the problem by favoring monadic Optional/Maybe solutions.
Re:Go nulls and SQL by tedunangst on Monday May 23, 2022 @04:28PM (#31484426)
There are some differences here, but you can't for instance use a string pointer with string functions in go either. IMO The distinction between pointer and optional is not as vast as people make it out to be.

(But thanks, I overlooked T? conversions inside if.)

Re:Go nulls and SQL by ricardobeat on Monday May 23, 2022 @08:23PM (#31486544)
No you can't, but Go will happily de-reference the pointer without a null check, and your "string" will blow up in production: https://go.dev/play/p/7EVa7q6VgIM
Re:Go nulls and SQL by akavi on Monday May 23, 2022 @05:37PM (#31485070)
The distinction between pointer and optional is not vast. The distinction between pointer and not optional is.

The whole idea of optional is to make not optional possible.

Re:Go nulls and SQL by morelisp on Monday May 23, 2022 @04:55PM (#31484666)
You can call a value method on a nil pointer and it panics, though, which I think was a mistake.
Re:Go nulls and SQL by nemothekid on Tuesday May 24, 2022 @02:09AM (#31488575)
>The distinction between pointer and optional is not as vast as people make it out to be.

The billion dollar mistake is overblown?

Re:Go nulls and SQL by adastra22 on Monday May 23, 2022 @04:12PM (#31484241)
T? is just syntactic sugar for Optional/Maybe, no?
Re:Go nulls and SQL by shirogane86x on Tuesday May 24, 2022 @03:17AM (#31489014)
I don't think that's quite true. It's sort of the same in how it's used, but the main difference is that T? (or T | null) is a union, and Optional/Maybe/Option is a sum type. Out of all the implementations I've seen, T? can't be nested - you can't have T??, whereas it's quite possible to have a Option<Option<T>> (and it's sometimes useful).
Re:Go nulls and SQL by MrJohz on Tuesday May 24, 2022 @01:19AM (#31488272)
Roughly, yes. But that's the point: an Optional type along with static typing preventing misuse can prevent these sorts of errors entirely.
Re:Go nulls and SQL by dtech on Tuesday May 24, 2022 @06:04AM (#31490069)
It's semantically similar but not syntactic sugar, since it is not translated to Optional or wrapper types, so it also doesn't incur the overhead of Optional.

I actually like the language support more, as it flows a lot better than the (flat)map chain you get in monadic style. Similar to async/await v.s. Future.

Re:Go nulls and SQL by stouset on Monday May 23, 2022 @05:20PM (#31484884)
Type systems can enforce that types always contain a value of that type and cannot be null. There is another type that is either null or a value of the enclosed type.

At any boundary where something might be null, you do the null check. If it's null, you do whatever logic is necessary right there and only right there. That might be to skip the computation, to use a default value, to get the value from somewhere else, to return an error, or whatever. If it's not null, you use the internal value and from then on every user can operate on a guarantee that it's not null.

Re:Go nulls and SQL by saghm on Monday May 23, 2022 @09:33PM (#31487027)
>> Sane languages have pointers which either can't be null or require you to check explicitly. Rather than leaving it to explode at runtime.

> Tell me more about these unexplodable languages.

I don't think anyone else mentioned an entire language being unexplodable, just a pointer type.

Later on the thread you talk about `Option` in Rust, which is not what I think most people would consider a pointer type, but even if it is, it's certainly not the only one. I think GP was talking about the basic reference type (i.e. `&T`), which will not ever be null in safe code, so dereferencing it will not explode.

Re:Go nulls and SQL by adastra22 on Monday May 23, 2022 @04:11PM (#31484235)
Rust being the popular example. But even C++ has this with std::optional, for example.
Re:Go nulls and SQL by tedunangst on Monday May 23, 2022 @04:19PM (#31484330)
So rust doesn't explode if I unwrap None?
Re:Go nulls and SQL by stouset on Monday May 23, 2022 @05:30PM (#31484999)
Only if you want it to.

    #[derive(Default)]
    struct Foo {
        …
    }

    struct Bar {
        …
    }

    fn do_something(foo: Foo) -> Bar {
        # do something with Foo and return a Bar
        …
    }

    fn main() {
        let opt_foo: Option<Foo> = None;

        // panics
        let foo: Foo = opt_foo.unwrap();

        // panics, but with an error message of your choosing
        let foo: Foo = opt_foo.expect("foo was supposed to be there");

        // converts the Option (Some or None) to a Result (Ok or Err,
        // where Err can contain an error type or message and then passed
        // around or returned or whatever)
        let foo: Result<Foo> = opt_foo.ok_or("foo was supposed to be there");

        // replaces it with a value of your choosing if it's not there
        let foo: Foo = opt_foo.unwrap_or(Foo { … });

        // replaces it with the default value the type defines
        let foo: Foo = opt_foo.unwrap_or_default();

        // keeps it as `None`, or if it's actually something then
        // replaces the internal contents with the result of the
        // function call
        let bar: Option<Bar> = opt_foo.map(do_something);

        // does arbitrary logic in the match arm if foo is there
        match opt_foo {
            Some(foo) => { do something with foo },
            None      => { do something else },
        }
    }
There are a few dozen other things you can do with an Option that handle the rarer use-cases, but the above are like 95%+ of what you want.
Re:Go nulls and SQL by imron on Monday May 23, 2022 @09:47PM (#31487126)
Rust gives you options :-)
Re:Go nulls and SQL by Gwypaas on Monday May 23, 2022 @04:58PM (#31484692)
You're explicitly choosing to panic if it is None. Would never pass a code review unless you can in very clear terms tell why it will never now or in the future be none.

The point is that you can't use the inner value without choosing a course of action if it happens to be none.

Re:Go nulls and SQL by avgcorrection on Monday May 23, 2022 @04:27PM (#31484412)
The comment that you respondend to:

> > Sane languages have pointers which either can't be null or require you to check explicitly.

You cannot try to dereference a nullable pointer in safe Rust. It has got nothing to do with Optional (Some/None).

Re:Go nulls and SQL by tedunangst on Monday May 23, 2022 @04:30PM (#31484439)
That would make a rust pointer rather less useful for representing sql null, no?
Re:Go nulls and SQL by avgcorrection on Monday May 23, 2022 @04:58PM (#31484687)
What?

The comment that you -- with aloof disbelief -- replied to only talked about pointers. I don't know what point you think you are proving with these pithy replies. It sure does go above my head. :)

Re:Go nulls and SQL by tedunangst on Monday May 23, 2022 @05:17PM (#31484862)
Well, this is a thread about storing sql null. I'm trying to suss out how sane languages represent sql null in a way that can't go wrong. So far the answers mostly seem to be use a type that can't represent sql null or use a type that explodes when you use it wrong. With a side of real programmers don't let bugs pass code review.
Re:Go nulls and SQL by stouset on Monday May 23, 2022 @05:48PM (#31485194)
With all due respect, it appears as if you have entered this conversation with this belief and have used that perspective as a filter when other commenters have tried to correct that perspective.

It may be surprising to learn that languages without implicitly-nullable types are real, but you should understand that none of these people would be trying to tell you about this if these languages simply exploded any time you used them the wrong way.

Re:Go nulls and SQL by avgcorrection on Monday May 23, 2022 @05:34PM (#31485040)
> I'm trying to [sass] out how sane languages represent sql null in a way that can't go wrong.

There is a difference between a type Pointer where `null` is an instance of that type and a type Box which only has valid (can be dereferenced) values. If the language has e.g. algebraic data types and pattern matching then Option(al)<Box> can be safely matched on and Box can be used in the branch (the pattern match arm) where Some(Box). Meanwhile in a language with Pointer and no flow analysis any dereference of Pointer could lead to some kind of "panic".

Say "unwrap()" all you want but the two approaches are clearly very different.

Re:Go nulls and SQL by winstonewert on Monday May 23, 2022 @11:13PM (#31487611)
Where did anyone anywhere in this thread claim that you could "represent sql null in a way that can't go wrong?"

Yes, Rust options explode if you unwrap a None. But that's explicitly what `unwrap()` does. It a big improvement over any random access potentially implicitly exploding.

Re:Go nulls and SQL by anonymoushn on Tuesday May 24, 2022 @12:10AM (#31487889)
It seems like sql types that include null and non-null values are a union of at least two different types. In general, if you write code to handle a tagged union that has "panic!" in one of the prongs, you'll get panics. Don't do that?
Re:Go nulls and SQL by imron on Monday May 23, 2022 @09:53PM (#31487168)
Correct, which is why you'd use Option<T> instead.
Re:Go nulls and SQL by Dylan16807 on Tuesday May 24, 2022 @02:13AM (#31488600)
The quote is talking about plain pointers being dangerous.

And in turn, the claim above was that some languages have plain pointers that aren't dangerous.

Yes, you can put a pointer into an Option that can fail, but that's a different issue. The point is that "can fail" is not built directly into the pointer type, and you can use pointers that don't have that risk.

And to be clear, that claim is not directly addressing the issue of SQL null. It's a baseline discussion of what pointers actually imply by nature of being pointers. We can then better build upon that knowledge after we separate "refers to a data location" and "might not have contents" into separate attributes.

Re:Go nulls and SQL by anonymoushn on Tuesday May 24, 2022 @12:07AM (#31487870)
Zig encodes optionality separately from pointer-ness, like Rust. You don't have to ask about unwrapping None in cases where None is not a member of &T.
Re:Go nulls and SQL by worik on Monday May 23, 2022 @04:14PM (#31484275)
You cannot use a null pointer in Rust.

I am a Rust novice but I have not found a way to get to uninitialised memory in safe Rust. Yet.

Re:Go nulls and SQL by imron on Monday May 23, 2022 @09:50PM (#31487149)
> You cannot use a null pointer in Rust.

Yes you can: https://doc.rust-lang.org/std/ptr/fn.null.html

You just won't use it unless you're doing FFI or similar things.

Re:Go nulls and SQL by worik on Tuesday May 24, 2022 @03:18PM (#31496377)
FFI is unsafe, by definition.
Re:Go nulls and SQL by imron on Tuesday May 24, 2022 @07:19PM (#31498696)
You can still use null pointers in safe rust (see the link I posted which is 100% safe rust), you just can’t deference then.
Re:Go nulls and SQL by worik on Tuesday May 24, 2022 @09:18PM (#31499538)
Ok.

I meant "using null pointer" means dereference it. But careless language....

Re:Go nulls and SQL by tedunangst on Monday May 23, 2022 @04:20PM (#31484335)
How do you create a pointer to uninitialized memory in go?
Re:Go nulls and SQL by TheDong on Monday May 23, 2022 @05:52PM (#31485231)
All it takes is a specially formatted comment

    /*
    int g() {
     volatile int x;
     return x;
    }
    */
    import "C"

    import "fmt"

    func main() {
     fmt.Printf("%d\n", C.g())
    }

But I know you'll say that 'import "C"' or 'import "unsafe"' is the same thing as using an unsafe block in rust or such, and really shouldn't count against go.

Which is fair and true, but you're chasing down a pointless detail. The point isn't that go is memory unsafe. It's not. The point is that Go's type-system is not powerful enough to express various types of type-safety, and as such it's an error-prone language where you can expect null pointer exceptions frequently.

Re:Go nulls and SQL by Gwypaas on Monday May 23, 2022 @04:45PM (#31484574)
You can't. But a runtime panic also very easily causes an outage. At least it's not as subtle.

Still. Rust is infinitely better in this regard. Go feels like a crude hammer, especially regarding the default interaction between deserialization and missing struct members.

Re:Go nulls and SQL by stouset on Monday May 23, 2022 @05:52PM (#31485232)
You can't. But you can absolutely have a `nil` that will unavoiad runtime panics if you don't check it. And further, you only can't do this because go defines by fiat that the zero-value of a type must be legal. Of course, this is wildly inconvenient and annoying for many types, including those that come bundled in the standard library.

There are other, very convincingly better options to this that many in this thread have been trying to teach you about in the expectation that your responses have been in good faith.

Re:Go nulls and SQL by giraffe_lady on Monday May 23, 2022 @03:42PM (#31483981)
Maybe Some other time.