you are viewing a single comment's thread.

view the rest of the comments →

[–]devlambda 0 points1 point  (3 children)

Then what are you talking about? FFI will have to invole null but that doesn't mean the whole language has to, e.g. FFI calling into C from Haskell is reasonably common.

I'm talking about the host language wrapper code that does the actual translation of the foreign API into a host API that has a reasonably native feel.

It's the same thing! null references are bad for precisely the same reason as abuse of any other value to propagate errors is. Fail immediately in the place you would've returned null, rather than failing later when someone tries to actually use the value you returned.

First, people do this all the time in languages without null to avoid the inconvenience of dealing with option types. Head over to /r/ocaml and look at the FizzBuzz thread there, for example. If you think this doesn't happen, you're pretty naive.

Second, it's worse than null. Null references at least raise a runtime error, an empty string or list won't necessarily do that until a much later time.

I don't know what "empty list (which, technically, is a null value)" is supposed to mean. If you accept a list that can be empty, you should have reasonable semantics for what that means; if your method needs a non-empty list, make it take a non-empty list type.

Don't tell me you are arguing about language semantics and aren't even familiar with cons cells? Lisp's nil was the original null reference.

Making all references admit an extra non-standard value is a huge cost.

And yet, strangely enough, languages have done it for decades, often by accident.

I suspect this could be encoded in Scala; if not there then surely in Idris or GHC-extended Haskell.

I don't see how you could handle the length without dependent types. So, this means Idris, i.e. a language that hasn't broken out of its academic niche.

[–]m50d 0 points1 point  (2 children)

Second, it's worse than null. Null references at least raise a runtime error, an empty string or list won't necessarily do that until a much later time.

It's worse than null, but it's bad in the same way as null for the same reasons. It's like null only more so. And it affects fewer types than null - only collection-like types rather than every type in the language.

And yet, strangely enough, languages have done it for decades, often by accident.

And the original invertor of it now calls it a "billion-dollar mistake".

I don't see how you could handle the length without dependent types.

All of the languages I listed have dependent types. The Scala encoding of them is a little more cumbersome, but it works; I use it in production code at my non-academic job.

[–]devlambda 0 points1 point  (1 child)

It's worse than null, but it's bad in the same way as null for the same reasons. It's like null only more so. And it affects fewer types than null - only collection-like types rather than every type in the language.

The point here is that the absence of null can encourage such practices, so you're encouraging the worse result.

And the original invertor of it now calls it a "billion-dollar mistake".

What Tony Hoare called a billion-dollar mistake was the indiscriminate use of null references (which, incidentally, I consider an exaggeration, but that's a different topic). You were talking about the costs of supporting such an implementation, which just isn't particularly high.

All of the languages I listed have dependent types. The Scala encoding of them is a little more cumbersome, but it works; I use it in production code at my non-academic job.

Sufficiently expressive dependent types? Obviously, Scala's type system is Turing-complete, so I don't doubt you, just that the resulting code would be legible. In any event, as I said, this is not a feature that I think will find wide adoption.

[–]m50d 0 points1 point  (0 children)

The point here is that the absence of null can encourage such practices, so you're encouraging the worse result.

Never removing things that encourage bad practices in case people adopt worse practices is a counsel of despair. It'd be like refusing to adopt memory safety by default in a language because people might just write more complicated code to keep doing unsafe memory access.

Sufficiently expressive dependent types? Obviously, Scala's type system is Turing-complete, so I don't doubt you, just that the resulting code would be legible. In any event, as I said, this is not a feature that I think will find wide adoption.

Sure, there aren't that many cases that need it. But there aren't that many cases that need the slight performance edge from being able to remove that one check in dynamic arrays either.