Live data from Hacker News

What is wrong with NULL

lucidchart.com

91–100 of 147 posts

Re: What is wrong with NULL

#91
post #10

Uglier than a Windows backslash, odder than ===, more common than PHP, more unfortunate than CORS, more disappointing than Java generics, more inconsistent than XMLHttpRequest, more confusing than a C preprocessor, flakier than MongoDB, and more regrettable than UTF-16, the worst mistake in computer science was introduced in 1965. That could be the greatest intro sentence ever seen on Hacker News.

Pretty good, but I've never had a problem with an XMLHttpRequest being inconsistent. Everything else seems spot-on though.

You've probably started using it more recently, but if you want to see what it used to be like, check out this XMLHttpRequest wrapper and see how many browser bugs it fixes:

https://github.com/ilinsky/xmlhttprequest/blob/master/XMLHtt...

Re: What is wrong with NULL

#92
lol the null / undefined issue in javascript is further exacerbated by the fact there is no int type and everything is just a "number".... yet the number 0 is still treated the same as null/undefined by js special forms like "if" and "==". This is particularly hilarious because it leads to some null-check bugs like:

if ( user.getScrollPosition() ) { whatever(); } else { die(); }

99% of the time, the code would be fine, but if the user scrolls just right, the whole thing would die. Stuff like this is literally death to debug because this bug is effectively indeterministic and can't be reproduced.

Re: What is wrong with NULL

#93
post #56

Earlier quoted context omitted.

If you have a language with enum types (Haskell, ML, etc., or any of the languages inspired by them like Rust, Scala, etc.), that's straightforward. In e.g. Rust, you'd have enum Connection { ValidConnection {fd: RawFd, address: SockAddr, ...}, BadAddr, BadPort, ... } In fact Rust's representation of the maybe type is just a generic enum Option { Some(T), None, } so all you're doing is getting rid of the two layer Op…

You shouldn't have to specify the error states in each method, this is why what I'm advocating is different than a simple enum: - You don't need to define a constructor to take the error string - You don't need to implement method dispatch (all methods of an error state instance automatically throw, like null does) Enums are close, but not quite right.

Rust's error handling (try! and error-interoperability) do this well.

Re: What is wrong with NULL

#94

NULL is okay as long as you pretend it doesn't exist. I mean, in these languages, uninitialized variables exist at some point (fields start uninitialized in constructor bodies, etc), and that's why there's null, instead of defining them with some garbage value that has undefined behavior. But the right solution for users is to just pretend that it can't exist, and that uninitialized variables have a garbage value. Of…

> The right language design decision for these languages (managed languages like Java) might have been to make uninitialized references have a garbage value that reliably throws an exception when used (i.e. null) -- you can copy the reference and pass it around, but you can't compare it for equality and any attempt to inspect its value results in an exception. That's just a different kind of null. You still have the…

That is not an option. Things like arrays need to be allocated with a default initialization and then filled.

Re: What is wrong with NULL

#95
post #76
post #10

Uglier than a Windows backslash, odder than ===, more common than PHP, more unfortunate than CORS, more disappointing than Java generics, more inconsistent than XMLHttpRequest, more confusing than a C preprocessor, flakier than MongoDB, and more regrettable than UTF-16, the worst mistake in computer science was introduced in 1965. That could be the greatest intro sentence ever seen on Hacker News.

I also don't think a C preprocessor is at all confusing, it's quite a simple program, both to write and to program. Including less used features such as concatenation or stringification.

This is what you have to do to concatenate a string with another macro:

    #define VARIABLE 3
    #define NAME2(fun,suffix) fun ## _ ## suffix
    #define NAME1(fun,suffix) NAME2(fun,suffix)
    #define NAME(fun) NAME1(fun,VARIABLE)

    int NAME(some_function)(int a);
From:http://stackoverflow.com/questions/1489932/how-to-concatenat...

C preprocessor can be confusing at times.

Re: What is wrong with NULL

#96

Earlier quoted context omitted.

In dynamically typed languages, there are still problems with flat Null/Nil/None that are addressed by optional values (the biggest comes when you use multiple operations that can return null but the single null value loses the source of the null; using optional values these often are differentiated easily as being either an "outer" null -- e.g., None -- or an "inner" null -- Some(None).) In fact, the example in the…

But as the writer mentions, optionals are a lot like lists with either zero or one elements, so it seems like many of these issues could be dealt with by simply returning a list, which would have zero elements if (in that example) the key was missing, or one element is the key was present. (And that single element would be nil if that was the value for that key.)

Sure, lists make a decent "poor man's Maybe"; and many dynamic languages have facilities that make that a decent solution. In dynamic OO languages, there's some Maybe/Optional-specific operations you might want to have to more clearly express certain patterns which make it with having specific types.

Re: What is wrong with NULL

#97
Here is what is wrong with Option.

option.ifPresent(x -> System.out.println(x));

So instead of just checking to see if it is NULL you want me to create an instance of a specialized class that holds my variable that has a method that acts like an "if" statement that I need to pass an anonymous function to that receives the value I already have?

Why not just do:

x && System.out.println(x)

or:

System.out.println(x) if x

Or if you want to skip over the rest of the logic if it is null:

return unless x

System.out.println(x)

I don't see why I need to introduce a new type system and complicate things.

For default values you want me to create an instance of specialized class that holds my variable and has a method that allows me to get my value or return a default value?

option.orElseGet(5)

So instead of a memory lookup I now need the overhead of an entire function call?

Why not just do:

x ||= 5

Or better yet, just put it in your function declaration as a default value:

myFunc = (x=5, y, z) -> ...

The one benefit I see is type safety but it is extremely rare for experienced programmers working in dynamic languages to have bugs related to type.

You are layering on abstractions and forcing programmers to go through hoops just to get at their data. It is more complicated and increasing the cognitive load.

There's also the fact that you are going through functions and classes instead of just memory accesses. This makes code less performant as well.

Re: What is wrong with NULL

#98
post #57
post #7

Earlier quoted context omitted.

Rust, too! Edit: Btw, I disagree with how the article categorizes Rust in comparison to Haskell. It shows that Rust has std::ptr::null, but neglects the fact that Haskell has Foreign.Ptr.nullPtr. Either both should be "5 stars" or both should be "4 stars".

Came here to say this. In fact, I think every language that they give 5 stars to has some form of "foreign pointer", "raw pointer", "unsafe pointer" or the like that is nullable, for FFI and other low level tasks. I think that anything which has no null in normal, idiomatic code, outside of "unsafe", "ffi", or similar subsets, should get 5 stars. The distinction is really about whether you need to worry about any pos…

> Likewise, I think that in Scala and Swift, null is only present for compatibility purposes, and idiomatic code does not use them. I'm not sure about F#.

I believe though that with the exception of Swift, null can infect these language's quite easily via the FFI, and the guarantees aren't as strong. I haven't used them much though, so I could be wrong.

Re: What is wrong with NULL

#99
post #7

Earlier quoted context omitted.

Rust, too! Edit: Btw, I disagree with how the article categorizes Rust in comparison to Haskell. It shows that Rust has std::ptr::null, but neglects the fact that Haskell has Foreign.Ptr.nullPtr. Either both should be "5 stars" or both should be "4 stars".

Author here. I didn't know that about Haskell. Admittedly, the "rating" is pretty rough, maybe even a bad idea. I've seen std::ptr::null more than I ever have Foreign.Ptr.nullPtr. But really, both are usually used for compatibility with external libraries/programs/runtimes, not for idiomatic language programming. Both great languages in my book :)

> I've seen std::ptr::null more than I ever have Foreign.Ptr.nullPtr.

Probably because we need to work with the C API a great deal right now, but that should change as more and more things are written in Rust. Still, the unsafe boundary helps by removing the ability to dereference a raw pointer in safe code - something that Haskell doesn't have.

Re: What is wrong with NULL

#100

We don't need to get rid of null, we need more, type-specific and context-carrying nulls: types need a way to signal various error states via an enumeration of instance constants that carry the error state in a type-compatible manner without some syntactically crappy mechanism like Maybe. class Connection { //Error instances BAD_ADDR("The given address was not correct...") ... } These constants should throw, just lik…

I don't think enumeration is the problem with handling error states, I think handling error states is the problem with error states.

That is to say, there's nothing wrong with null: There's something wrong with null-as-error, but it's not the blankness of the null that's the problem.

The user is frustrated by this: Errors are fixable, so more important than more types and more maybes is that the errors communicate how to resolve them and what happens next:

    connection new_connection(address) {
      if(!address_valid(address)) return new_connection(prompt("The given address was not correct...", address));
      ...
Look: The user is prompted to correct the address in an interactive implementation, but a non-interactive (command-line) instance can implement prompt() as a combination of perror() and exit().

Then consider the following:

* Start writing a large file * Run out of disk space * Delete the whole file and return an error

The user has been frustrated by this for decades! It should be:

    again: ret=write(...);
    if(ret == -1) switch(errno) {
    case ENOSPC: wait(ENOSPC); goto again;
    ...
and yet very few languages or environments have useful implementations of prompt() and wait() despite how trivial it is (even in C)! Even fewer libraries make shoehorning correct error handling in. Error handling just isn't part of our (collective) programming culture and if we're going to change something, we should fix it right.
Post reply on HN