re: You Either Have It Or You Don't VIEW POST

FULL DISCUSSION
 

Wow. Interesting!

I've never used clojure so correct me if I'm wrong, but clojure is a lisp and everything is a list in lisp? (hence the name) - so the "you either have it or you don't" just translates to either a list with one or more elements or an empty list?

Not sure if it helps, but this is how I use/think about types: when you're coding your program you are actually defining a computation graph. Using types (which like you say are only a compile time thing) are simply there to help you get the graph as correct as possible - it's a tool for the dev/compiler. And you can take that to the extreme in a language like Idris

It's unfortunate in some ways that Maybe is linked so closely with null/not null, because you can think of it another way - sometimes when we're building programs we need to do things which can fail or are outside of our control, like reading from a database or calling some http endpoint. How do you represent that in a computation graph? How do you represent it can fail as well as succeed? How do you say "don't do anything until you get this result"? Monads let us represent computations like this (interview tip: if someone asks you what a monad is, just say "it's a way of representing sequential computations") and Maybe has a monad.

For example, in our code we can say "go to the db and get this record. put the result into a Maybe". Now our compiler knows that there's a section of code which will either return Some blah or None and if it's Some blah everything went well, otherwise there was an error (and we threw away the error message)

Anyway, I can see what he's trying to say and if I'm right about the list thing it even makes some sense for clojure... but I don't think I agree overall :/

 

Thanks for the detailed response!

just translates to either a list with one or more elements or an empty list?

Clojure actually provides a rich set of persistent data structures in addition to lists like sets and maps. I think he's referring most commonly to map keys here, but the concept applies to lists as well.

fail as well as succeed

Great point. You're absolutely right, Maybe is being shoehorned here into something it isn't, but happens to be applicable towards.

it's a way of representing sequential computations

This is definitely more concise than my current word salad answer. I still have never managed to "English" the idea as succinctly as I think it should be able to be expressed but I remember specifically they day it "clicked" - truly not a complicated idea.

I think his point is that this idea of the potential for failure or gaps in your data will inevitably (in certain systems) apply to all data, so then why are we dealing with it in the domain level at all? Clojure kinds offloads that to how it manages data in general with it's STM engine. However, moving the complexity doesn't avoid that complexity.

 

correct me if I'm wrong, but clojure is a lisp and everything is a list in lisp?

Not quite. For example atoms aren't lists, neither are other primitive types. That's why there are predicate functions that check for null, i.e. null in Common Lisp or null? in Racket.

It's unfortunate in some ways that Maybe is linked so closely with null/not null, because you can think of it another way

That other way generally has another name though, Either (Haskell) or Result (e.g. Rust). The failure case (Left or Error) holds the error message so you don't have to throw it away. So in your examples a DB operation that may return no records (i.e. find by primary key) could be a Maybe, whereas something that actually produces an error would be an Either. That's why it's not uncommon to see Maybe values inside Either for things like API requests. The Either tells you if the operation itself succeeded (i.e. could we make a request), the Maybe if a value was returned from that request.

 

ah cool - thanks for clarifying. Then I guess I didn't really get his point!

about Either - yes, exactly - I was kind of deliberately over simplifying to make the point that there's other, sometimes nicer ways to think about Maybe

Maybe, IIRC, comes from Haskell, which doesn't have nullability so it has nothing to do with nullability checking.

It has everything to do with encoding the fact that having a value or not having one are two different, equally informative, and perfecly legal values. And your code must be able to distinguish those and act accordingly.

Lisp, and then Clojure probably have different idioms (i.e. the empty list) that do not require a union type, and can be treated as equally informative. That's probably what Hickey has in mind.

Yes, I understand the difference. The question is if there’s an inherent benefit to nulls or if there’s value to potentially modeling them as “not having something.” The answer is not super straightforward and I believe changes a lot with the domain, something that has been explored in a different comment (scripting vs core business logic for example).

code of conduct - report abuse