If you liked my "100-Year Programming Language" article or talk, this talk from Paul Cantrell (@inthehands) at Minnebar is *really* good.
Programming language history, including some wonderful really early stuff.
If you liked my "100-Year Programming Language" article or talk, this talk from Paul Cantrell (@inthehands) at Minnebar is *really* good.
Programming language history, including some wonderful really early stuff.
@codefolio
You guessed correctly that Maybe/Option is where I was going. I argue that it does solve the single worst problem with null; will type up when I have a little time later today.
@inthehands I *am* sorry it ends before he talks about alternatives to null. There are some good ones.
But the Maybe monad is mostly just three nulls in a trenchcoat. It doesn't fix the worst problems with it, it just adds a lot more verbosity to the problem.
Given how fast he was explaining stuff, it *would* have been fascinating to see how he explained monads in 45 seconds 🙂
@mattberan @codefolio Not all of it, but most of the sessions in larger rooms! And they really did a bang-up job with the video production quality this year.
@codefolio @inthehands this is how I learned MinneBar was recorded! I was so bummed to miss it this year. THANK YOU!
@codefolio
I realized I forgot to give you the promised reply! Here’s the way-to-short version of what I was going to say about null in that talk.
The distinguishing features of null are (1) it acts as if it’s a subtype of everything and (2) it has no methods. But if “subtype” means anything in an OO lang, it’s that methods of the supertype are still present on subtypes! Thus the core problem: null violates LSP. It’s a lie baked into the type system. 1/
@codefolio That’s the problem variant types solve: they don’t violate LSP. String? (using Swift notation here, that’s “optional String”) is not a subtype of String. “Box that might contain a cat” is not a cat. It is a box. And lang features make sure you deal with it as a box first before you can get at the cat inside. 2/
@codefolio This smells like a static-type-only thing, but applies to dyn langs too. In Ruby, for example, we use access patterns for NilClass as if it’s either a subtype or union type; the lang could choose to have a Optional class where the access patterns for a Foo don’t work for an Optional that might contain a Foo. (Not clear how you’d achieve all the sugar Swift does.) However… 3/
@codefolio …the approaches that the “nil is bad, actually” camp in Ruby actually does use also generally work by avoiding LSP violation: for example, make a “linked list node that is an endpoint” object instead of using nil, and make it respond to the same methods as other nodes.
@codefolio
>no type declarations => you're not violating a type declaration
I disagree! LSP isn’t about violating declarations; it’s about violating contracts. Ruby still has types aplenty, and contracts; it’s just that they’re implicit. In this fn:
def foo(num)
num.abs * 3
end
…the type of num is “thing that has an abs method that returns a thing with a * method that accepts 3.” That’s a type! And there may be some implicit type assumptions on the programmer’s part not explicit in code.
@inthehands Yeah, I definitely agree with these criticisms of nil. And yup, adding a special instance for your type-specific special value (linked list node, the symbol :end, etc) is generally much better than nil, for all the reasons you say.
Ruby's doesn't have the same LSP problems (no type declarations => you're not violating a type declaration) but of course nil is still bad.
@codefolio Taking Swift as an example, checking for none doesn’t look like checking for nil in the particular and very important way that this doesn’t work:
var s: String?
if s != nil {
print(s.count)
}
…because unwrapping is a separate lang feature that •ties the lexical scope of the unwrapped value• to the check.
@inthehands I'm a little leery of "it's fine, String? is another type, but not a subtype of String" since checking for None looks a lot like checking for nil. But I suppose in a typed language you can at least declare where it's not allowed to be nil, so there's that.
I wanted Rust to be like that, but having unsafe Rust all over limits the advantages pretty heavily (still runtime crashes, for instance.) So I'd need to work on a little-to-no-unsafe-Rust project to know.
@codefolio Right. My point is that code treats NilClass •as if it is a subtype•. That’s not explicitly modeled at compile time as in a static lang, but that doesn’t mean the contract assumptions aren’t there in the code all the same.
@inthehands It's a special value of a different type, so you avoid the whole "nil is a subtype of everything" problem.
In Ruby nil isn't a subtype of everything *and* it has some methods.
So if that's the distinguishing feature of null-as-an-abstraction-across-langs then Ruby's nil isn't one.
@inthehands Sure, but you're not allowed to pass nil to it in the same way you're not allowed to pass :end or "bob". Nil isn't a number, nor typed as if it is.
@codefolio Yes, that’s it: just assuming doesn’t work, even when the assumption is correct.
@inthehands So then presumably the benefit is that you can't access the internal value without doing a check, so you can't skip the check, even if you're "sure"?
I'm trying to make sure I understand.
@codefolio
Swift sugars it quite a lot, and it really helps. In particular, something that Swift does that I think Ross does not is to automatically promote String to String? when necessary:
func f() -> String? {
"hello" // works
}
My experience with Swift has been that yes, this really is a good thing, and the real problem with other langs hasn’t been the fundamental idea, but (1) ergonomics and (2) APIs making things optional “just in case” when it’s not information-bearing.
@inthehands That makes sense. It's the same kind of thing Rust is trying to do.
The Rust variation frustrates me, since it requires proving things to a compiler, often in very inconvenient ways. Maybe Swift's version is better that way.
It *does* seem like the way the world is headed. I really dislike it in Rust.
GNU social JP is a social network, courtesy of GNU social JP管理人. It runs on GNU social, version 2.0.2-dev, available under the GNU Affero General Public License.
All GNU social JP content and data are available under the Creative Commons Attribution 3.0 license.