3 ms·
This certainly falls under Rich Hickey's definition of "simple", which is one virtue. But: > it is not immediately evident how the more elegant solution actual
by brundolf 6y ago
This certainly falls under Rich Hickey's definition of "simple", which is one virtue. But:
> it is not immediately evident how the more elegant solution actually works
another virtue is ease of comprehension, and the more elegant solution lacks that in my (and seemingly Linus') opinion. Maybe if you're used to working with pointers to pointers you might have an intuituon for them, but I at least had a difficult time gaining an intuitive grasp on the second solution, which could potentially nullify the bug-resistance of having fewer branching cases. In short, calling the second one objectively better is overstating it I think.
It's worth noting that in a language with union types, you can have the best of both worlds (using Rust here because it's the one I'm most familiar with):
enum LinkedList {
Null,
Node { value: i32, next: Box<LinkedList> }
}
In the same way that the pointer to a pointer homogenizes the head-case with the rest, a union type means that any given linked list "is just a node", and the head can therefore be treated the same way as any later node
- vips7L 6y agoWouldn't you end up with a Box of Null? Wouldn't it be better to: struct Node { value: i32 next: Option<Box<Node>> }
- brundolf 6y agoYeah that's true, but the problem with your version is it loses the homogeny because an empty list can't simply be a Node, it has to be represented in some other way (as an Option<Node> or something), so we're back to square one. Maybe I was wrong and this can't be done perfectly even with union types.
- vips7L 6y agoIn that case wouldn't you just: struct List { head: Option<Node> } struct Node { value: i32, next: Option<Box<Node>> }
- brundolf 6y agoYep, but this replicates the original inelegancy (from the article): Option<Node> and Option<Box<Node>> are not the same type, and so they can't be treated the same way.
- vips7L 6y agoI guess you could just allocate the head node on the heap too. I think rust probably has better tools for this. Probably some sort of let node = node.next; while let Some(n) = node { node = n.next }