Hacker News new | past | comments | ask | show | jobs | submit login

I've been really enjoying using Rust because it has no NULL. You have to instead use the semantics of Some(x) / None()and handle both cases. I'm not sure how you work around the fact that an empty string is Null.

The problem with Null is that it can be either a value or show the lack of presence, and in JS because both undefined and null are values you can't depend on them being used for their semantics either (you can try to enforce their use but it that's no guarantee).

SQL suffers this exact same problem. I wonder what SQL would look like without Null.

    Select id, Option (key)
    From table
 

    Insert... Some(5), None::Int
From this perspective it still seems that empty string should not be None, but I think you're right that many people do use a code like "N/A", but you can just add a supplemental Boolean field which is cleaner for set / not set.

Interesting




> SQL suffers this exact same problem. I wonder what SQL would look like without Null.

As a base table value, it's easy to mechanically avoid NULL in SQL. Every nullable column is, in the most general case, simply a column that doesn't belong in the table but in a different table whose primary key is alsona foreign key referencing the original table’s primary key.


Your solution works, but I would hardly describe having a new table for every nullable column is "easy". It also would not be nice for maintenance -- often I want to add a new column as null initially, then soon after write a migration to convert it to non-null once it's populated. Having to create / remove a new table every time would be a pain.


>The problem with Null is that it can be either a value or show the lack of presence

No, the trouble with null is that it's a supertype that breaks the type systems -- if you actually wanted to have safe code in the sense you expect typesafety to give you, you should be checking for NULLs everywhere. Because a codebase can be changed from never-null to sometimes-null, and the type system is happy to let it go through, because never-null was not actually a thing -- we just imagined it for our convenience.

The problem with null is that, in general, if you didn't implement an explicit handling for it, then it's presence will do the wrong thing.

The primary benefit of rust's Option is that you can safely not check for null.

SQL is in fact the same problem -- we just don't bother to handle the null until it bites us in the ass. For example, booleans don't actually exist, because really a bool has values (True, False, Null). Which breaks your Boolean logic because you're using trinary values (with unintuitive results, because there isn't really a good answer). Which leads you to innocent queries including both false positives and false negatives, silently, when nulls are present in your data [0]

SQL does however allow for the column constraint NOT NULL, but there's nothing that actually enforces your queries to handle the possibility of nulls correctly (because, by default, everything is nullable, and your queries would be horrificly verbose) so queries tend not to handle the case correctly until they run into the problem.

The problem people tend to not understand is that we should be checking for nulls everywhere, and we only don't do so because it would be insanity. The primary benefit of moving nulls into an Enum is that we can now safely specify that thing is NOT NULL (and our compiler will enforce it). And as it turns out, most of your data does not need, or want, to be nullable

[0] https://www.google.com/url?q=https://sigmodrecord.org/public...


This still doesn't fix the user input Null, versus this value is not set. I think in that case you'd want a nullable boolean companion field that can then express set, actively not set and passively not set (when that matters) but it's a bit ugly.


Value isn't set? Use Nothing. Data has been collected and the user didn't input anything? Use Just "".

If you really wanted to, in Haskell you could do something like:

    data AdvancedMaybe a = Just a | Nothing | PassiveNothing


Interesting example. I certainly think the just use empty "" is fine and the coercion to NULL is not great.

I think Allowing "empty" values, and not allowing Null would be better.

If SQL had Option (Maybe) branch matching it would be an interesting replacement, and then coalesce would not be needed.

    SELECT id, MATCH k WITH (
      SOME(k) THEN k,
      NONE THEN default,
    END) AS something
    FROM ...
I can see it's terse, and it is just a wrapper around data that would be stored like NULL but it kind of makes for interesting semantics.

Just spitballing for fun on what it might look like.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: