Comment by friendly_chap
12 years ago
"Rule 5. Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming."
Quite ironic coming from the creator of Go. Algebraic data types, anyone?
I don't see the irony. Data structures and data types are two different axis.
You can argue that advanced language constructs will make it easier to write correct code to implement data structures, but it's not a magic bullet.
The Go authors argue that a simple programming language with loops, pointers and arrays is all you need to implement any data structure you need.
I find this a good example of a data structure for which I see little or no benefit in being modeled as an ADTs:
http://research.swtch.com/sparse
Even simple things like doubly linked lists are complicated with ADTs. On the other hand I don't know about good examples of ADTs used outside of the context of functional programming, do you have some pointers?
"You can argue that advanced language constructs will make it easier to write correct code to implement data structures, but it's not a magic bullet."
There is nothing advanced about ADTs.
"The Go authors argue that a simple programming language with loops, pointers and arrays is all you need to implement any data structure you need."
It's all about increasing the level of abstraction. There is a reason we don't code in assembly anymore. Of course machine code is all you need to implement any data structure, but how convenient is it?
"I find this a good example of a data structure for which I see little or no benefit in being modeled as an ADTs:"
So you found a single counterexample which (according to you) would not benefit from ADTs.
" On the other hand I don't know about good examples of ADTs used outside of the context of functional programming, do you have some pointers?"
I dislike pointers (a necessary evil if you have mutation I guess...), but here is one example:
data Gender = Male | Female vs type Gender int; const ( Male Gender = iota; Female )
Combine the first with pattern matching and you find yourself in awesomenessland (ie. code becomes readable, type safe).
>> On the other hand I don't know about good examples of ADTs used outside of the context of functional programming, do you have some pointers? > I dislike pointers (a necessary evil if you have mutation I guess...), but here is one example
Perhaps there was a misunderstanding. I asked you if you had some links to some interesting examples of ADT outside the context of functional programming. Because I was assuming that this wasn't a discussion about Go vs purely functional data structures.
Your example clearly shows the benefits of strong typing with fully described types. My point that this is orthogonal with Rob Pike's position about the importance of data structures.
Data structures exist independently on how we represent them. I don't see any irony or conflict in highlighting the importance of data structure vs. implementing language features that make it easier to write correct implementation of them.
> It's all about increasing the level of abstraction.
Rules of abstraction: https://pbs.twimg.com/media/BqkVxmrCUAEZSTZ.jpg
1 reply →
I was totally unfamiliar with any linking between functional programming and Abstract Data Types before reading your post. They are certainly present outside of that world.
Back in my university data structures class, an Abstract Data Type was just the collection of "a data structure and its operations". For example, a tree ADT could be a struct of two pointers and some value, along with operations like addNode, removeNode, findNode, copy, create, destroy, etc... We wrote lists, stacks, trees, hashes, and graphs in C as self-contained ADT libraries. This wikipedia page [1] explains the differences in approach.
The concept of data+operations was a lead in to objects for us, and seems very simple. Is the ADT idea in functional programming inherently more complex? I see from that page that it is intended to be immutable, which is certainly a difference.
1. http://en.wikipedia.org/wiki/Abstract_data_type#Imperative_v...
Unfortunately both abstract data types and algebraic data types share the acronym; I was replying to a comment mentioning the latter.
Oh, interesting. It's the middlebrow dismissal. I thought it had become an endangered species, but here it is, stepping right out into a crowded thread and trying to take out Rob Pike of all people. Good show!
https://news.ycombinator.com/item?id=4692598#up_4693920
Of course pg hates the "middle brow" dismissal. Part of his schtick is Malcolm Gladwell style 'intellectual porn' essays that ignore facts and complexity to paint an aesthetically pleasing (but false) narrative to people who are not subject experts. At this stage I'm not sure if PG does it deliberately like Gladwell admitted doing. I'm willing to give him the benefit of the doubt and say he does it inadvertently by writing about topics where he has no knowledge of previous study, coupled with a large ego born of being rich and constantly surrounded by sycophants trying to get funding.
The middle brow dismissal is apt/damaging in these situations because it saves everybody a lot of time by quickly demonstrating that the author ignored those pesky real world facts and complexities that spoilt the ideological narrative.
It's too bad The Master has departed, I'm going to miss his words being quoted to "settle any possible HN argument" in the words of this great comment: https://news.ycombinator.com/item?id=1716028. Also going to miss all the pearl clutching about "this comment/thread is horrible", okay maybe not. I assume work was never finished on the Lisp AI that would block comments he disagrees with, any of the mods still working on that?
I don't think you've fully understood Rob's point. Go is pretty good at creating machine-friendly data structures.
So is Rust, and it has algebraic data types, type parametrization, lifetimes and its representation is like C's.
Nobody said anything negative about Rust; in fact, it has nothing to do with this thread.
4 replies →
And some day you may even be able to use it. Let's save the Go vs Rust comparisons until they are both stable.
1 reply →
Machines are cheap. Developers are not. I would rather optimise for the latter.
Edit: since when having ADTs are so taxing for the machines? I did a quick search and I found no source saying they are expensive to implement.
I'm getting pretty sick of hearing this trope regurgitated all the time.
Developer time is often more expensive, but it's always a one-off cost. Machine costs are ongoing. Machines can also impose hard limits on scalability.
In the real world, software optimisation is often necessary. Ever play a computer game? Those have pretty hard limits on much time they can spend processing. You can't just throw hardware at the problem to make it go away when you don't control the client.
"Just add more hardware" is also an ecologically unsound and unsustainable approach. Ever wondered about the carbon footprint of the average data centre?
Maybe one day we'll have optimising compilers so good that thinking about machine-level data structures won't be necessary. They've come a long way in the last 20 years, but aren't quite there yet. In the meantime, if you ever find yourself actually needing to make something run within some hard limits on CPU time, RAM, etc., listen to people like Rob Pike: he know's what he's talking about, even if you don't like what he's saying.
In the meantime if you're working on an MVP, by all means optimise for developer time. In that context it's almost always the right decision.
4 replies →
Machines have a cost, developers have a cost. One must optimize for both costs, and assuming machines or developers were free compared to the other would be very stupid.
There are many problems that require some efficiency to solve effectively, especially in pike's field of systems.
3 replies →
Re: your edit regarding ADTs: it's not that they are expensive to implement, it's that they give you no control over the physical structure of the data, which is the really, really important thing when it comes to how expensive it is to perform operations on that data. That's the point Rob was making in #5.
BTW, if you want to gain an understanding of this stuff, the difference it can make and why, I'd recommend reading basically anything by Michael Abrash.
2 replies →
And if your problem requires only one of each, and needs them for the same amount of time, then your optimization would be the correct one.
Now scale this to a situation where solving the problem requires ten thousand machines for each developer working on code, and where each minute of time spent writing code translates into two days of machine time running that code, and the numbers start to look different.
1 reply →
Well, I'm no super fan of go, but given the ideas they were working with, I think they ended up with a fair compromise. I mean, if you want Haskell (or ML), use that?
I think it is a question of how far you're willing to take generalization over how easy it is to come up with a reasonable concrete solution to a concrete problem.
See eg: https://groups.google.com/d/msg/golang-nuts/DLxFvfdRKBY/NDkW...
The c mindset of unions/structs coupled with functions doesn't contradict the idea of "chose the right data structures".
[edit: It appears others have made this point better while I was typing. The gist seems to be (to paraphrase another comment): (abstract) data types and types are not the same thing. types can help with the implementation of ADTs, but that's not really relevent to the 5th rule.]
I don't get this:
"data types and types are not the same thing. types can help with the implementation of ADTs"
Can you please show me how can you implement a language (type system) feature without touching the compiler source?
I don't understand the question... an ADT is something like "a stack", where "a stack" is the collection of procedures that manipulate a stack, and have an interface that integrate with the type system. So a stack takes a type, and allows it to be pushed on, and popped off. Together these form an ADT. Now, if you have algebraic types, you might have an easier time implementing the stack ADT in a way that it can handle both text strings (push a string onto a stack) as well as numbers. Or you could just say that everything is a number: and "push by reference" -- so you can push a complex record to the stack -- but all the stack sees is an integer (a pointer to the record).
Type safety (checking that all integers pushed to the "record-of-type-library-card stack" are in fact valid pointers to valid library-card-records) can be helpful, but not needed to implement ADTs.
Am I close to clearing up what I was talking about above?
[edit: typo, also: you mis-quoted me, dropping the "abstract" in "abstract data type" -- which might be the source of the confusion?]
2 replies →
What about lisp, where the data structure is almost always a list?
What lisp? Common Lisp has plenty of data structures, including memory-efficient ones.