I find Rule 5 interesting given how much Go disenfranchises data structure authors. If data structures are important to developing software then surely one would use a language that maximizes reusability of data structures.
Also, I think it’s interesting how biased the list is towards performance rather than developing software in general. There is nothing in here about decoupling components or how to think about abstraction. But I don’t know what context these rules were taken from.
I find Rule 5 interesting given how much Go disenfranchises data structure authors.
This is an opinion; not a fact. It disenfranchises data structure authors insomuch as you don’t approve with the abstraction power provided in Go. For example, I do not feel disenfranchised when I write Go programs.
On the other hand, idiomatic Go includes the ability to precisely specify how your data is laid out in memory. Depending on what you’re trying to do, this would be the exact opposite of disenfranchising data structure authors.
I do not claim these things are mutually exclusive.
There is nothing in here about decoupling components or how to think about abstraction.
The list of rules seem like pretty general maxims. Specific advice about decoupling or examples of good abstraction would feel out of place in a list like this. Often merely pointing someone toward the data rather than the algorithm is enough to motivate a better design.
The list of rules seem like pretty general maxims. Specific advice about decoupling or examples of good abstraction would feel out of place in a list like this.
I disagree. Programming Epigrams has 121 pithy sentences, some of which give nice general maxims that would have fit here just fine. I also think Rule 1 adequately expresses Rules 2 and 3.
This is an opinion; not a fact. It disenfranchises data structure authors insomuch as you don’t approve with the abstraction power provided in Go.
It is a fact that if you wish to author a data structure in Go, you are disenfranchised. Because you can’t author a data structure, you can only author a data structure that holds a particular type.
On the other hand, idiomatic Go includes the ability to precisely specify how your data is laid out in memory.
And why do you care about this? Performance? See Rule 1. I’d rather have a bunch of data structures at my finger tips that I can then rewrite with precise memory layouts than the alternative.
But my point is not that Go’s design philosophy is good or bad. But that if the author of Go feels data structures are important (which Rule 5 implies but it’s one sentence out of millions from the author, so who knows) then Go unequivocally make developing data structures a more burdensome task. That is a different statement than saying I don’t like Go because it makes writing data structures burdensome.
It is a fact that if you wish to author a data structure in Go, you are disenfranchised. Because you can’t author a data structure, you can only author a data structure that holds a particular type.
Data structures have nothing to do polymorphism. They are orthogonal concepts. A data structure is just a way to organize data in memory. That’s it. If the OP were talking about abstract data types, then your musings about the apparent contradictory notions of Rob Pike would be more poignant.
I’d rather have a bunch of data structures at my finger tips that I can then rewrite with precise memory layouts than the alternative.
Great! That’s a totally valid opinion. But that’s all it is, an opinion. It’s a trade off that works for you. It is not a universal maxim.
then Go unequivocally make developing data structures a more burdensome task
No. Go makes developing abstract data types (without sacrificing safety or performance) difficult. I would absolutely agree with this. It was an explicit design decision.
I think you’re drawing a false line between data structures and abstract data structures. My argument is that if one feels data structures are an important component in solving problems I would expect them to be given a stronger fist class status. This includes the ability to make reusable data structures. The fact that writing concrete data structure in Go is well support but reusable ones is not is a weakness IF one believes data structures are important. In this sense, Go has done nothing to advance the state of data structures in C.
And I’m not arguing anything is a maxim. My statement this entire time has been that it is my opinion that this decision is interesting given Rule 5.
And where we disagree is I think ADTs are a subset of DTs. You’re entitled to your own opinion on the hierarchy.
However my point is not limited to generics. As I stated in the Reddit thread, Go also lacks powerful tools for data structures such as Algebraic Data Types.
Do you think that Rob Pike was considering abstract data types when talking about data structures? I don’t. If you agree with that, then there should be nothing surprising about what he said.
Go also lacks powerful tools for data structures such as Algebraic Data Types.
Do you think that Rob Pike was considering abstract data types when talking about data structures?
Yes, I do. IMO the statement doesn’t make much sense otherwise. But to reiterate: as I’ve said that’s my opinion, so you’re free to side on any bias you prefer like I have.
Pike realized the importance of data structures to solving problems in 1989. Nearly 20 years later a language he designed does not make it easier to solve problems via data structures. That’s very surprising.
Why is that surprising? The Go team is perfectly aware of the existence and principles of generics and ADT (as stated in the language’s FAQ). I also think they care about these questions and are definitely smart people. So maybe they just made tradeoffs different from what you expect?
You write like the design choice of integrating generics and ADT in a language is superior by nature. What about the costs?
Have you read the full article? [1] Pike advises to use simple algorithms and simple data structures and goes on with a list of data structures that are sufficient for almost all practical programs: array, linked list, hash table and binary trees. Maybe this explains why he (and the rest of team) does not feel an urgent need for generics and ADT.
I’m not sure why this is so difficult to explain, but I will try again. What @owen and myself are saying is, if data structures are important to someone, I would expect them to favor abstractions and trade-offs that favor data structures. This is not what one sees in Go. This is all I am saying. I am well aware of the trade-offs that exist in Go and the stated reasons for them by the authors.
For example, for historical reasons the authors of C favor simplicity and minimizing the distance between the developer and the machine, as such I would expect that C lacks numerous abstraction capabilities that requires a more complicated compiler and remove you from the hardware. And this is what I see.
Java’s authors favored removing platform specifics from developers, as such I would expect to see a high level of abstraction from the underlying hardware and heavy set of optimizations. And this is what I see.
The author of Pascal favored simplicity and understandability of a language, as such I would expect to see a language that is straight forward to learn and make trade-offs in favor of readability rather than expressiveness. And this is whatI see.
If the author views data structures as the core component of a program, I would expect the author to make trade-offs to provide developers the ability a lot of expressive power when it comes to data structures. This is what I see in Ocaml and Haskell, this is not what I see in Go. The obvious counter point is “well that says more about you than it does about the authors of Go”. And yes, it does, and my statement really has no more depth or deeper meaning than that.
I’m not the one having downvoted this, but my guess is the downvoter thinks your comment is “incorrect” because you use 5 rules, completely out of context, written 15 years ago, to draw conclusions about what Rob Pike thinks and how he should have designed Go. This is very reductive. Or maybe the downvoter was just bored.
Your bias is pretty clear. This is the second conversation I’ve had with you in as many weeks where you’ve lambasted Go and its designers. (In this thread, you’ve politely called Pike an idiot and in the other you accused them of a campaign to mislead everyone.)
But you’re in good company. Lashing out at newer languages with type systems that don’t meet one’s personal standard of expressiveness is the trendy thing to do these days.
At no point in this thread did I call Pike an idiot. I expressed my surprise at what I would have expected given Rule 5. Please accuse me of things I’ve actually done.
It is exact that you did not called Pike an idiot explicitly. But your comments strongly suggests that he is one. In my opinion, you’re playing with words like a professional politician ;-)
In this sense, Go has done nothing to advance the state of data structures in C.
“Advancing the state of data structures in C” has never been a goal of Go. So what is your point?
Have you some kind of personal issue with Rob Pike and Go? It looks like you never miss an opportunity to criticize Rob Pike’s work and Go, even when the linked article is just about five random rules, presented out of context, and published in 1989!
To be very clear, I appreciate some your points about Go shortcomings, and understand why you seemingly prefer languages like Haskell or OCaml. But other professionals have different tradeoffs than yours that lead them to different choices in terms of programming tools.
I fail to understand why you spend time commenting every thread related to Go, even in very indirect or remote way, to just repeat that the language miss generics, algebraic data types, pattern matching, pure functions, etc., in short, all typical features of modern functional languages. This is just stating the obvious. It’s even clearly explained in Go’s own FAQ!
The fact that this post is about Rob Pike is only incidental to my comment. But I think many people are interpreting my statement incorrectly, which is my own fault. All I said was that the author of the quote states the data structures are important to solving problems, as such I’m surprised the language they created does not make expressing solutions in terms of data structures easier. For example, Ocaml and Haskell developers find data structures important to solving problems. As such, those languages provide a rich set of tools for expressing solutions to problems in terms of data structures.
And no, how could I have a personal issue with Rob Pike? I’ve never met him or had a conversation with him. I would imagine he’s a very pleasant and interesting and intelligent person to be around. I think you are suffering from selection bias: I’m critical of just about everything, you just happen to read more Go posts or Go posts are more popular right now.
I fail to understand why you spend time commenting every thread related to Go
I’ll spend my time how I want even if it confuses you.
I’m surprised the language they created does not make expressing solutions in terms of data structures easier.
I disagree. Go provides a lot of things that makes defining and using data structures easy and efficient by default:
built-in arrays/slices/structs/maps/channels;
composite literals;
arrays and structs are values and can be used without pointers/references which removes a lot of costly indirection and reduces pression on the garbage collector;
escape analysis to keep data as much as possible on the stack instead of allocation on the heap.
For example, Ocaml and Haskell developers find data structures important to solving problems.
I agree that having parametric polymorphism and sum types in OCaml and Haskell is great in some cases. But it can also makes the language specification complex (for example have a look at the infamous “monomorphism restriction” in the Haskell Report) and, as far as I know, you lose the benefits of the efficient memory representation Go provides by default.
I think you are suffering from selection bias: I’m critical of just about everything, you just happen to read more Go posts or Go posts are more popular right now.
No, I’m not. It happens that I also read the threads related to functional programming, Haskell, OCaml, ML et al, and I don’t see you putting the same energy and repetitiveness in your critic of these threads.
I’ll spend my time how I want even if it confuses you.
Ok, you’re right. How you spend your time is not my concern :) But my concern is you not making me spending my time reading the same unconstructive comment again and again in each thread related to Go. Again, official Go’s FAQ clearly states that the language does not have generics or sum types at this time, and explains why.
And to conclude, what would you think if I would comment every story about OCaml with “This language is just a mess! We are in 2014, concurrency is all the rage, and OCaml still has a global lock.” and every story about Haskell with “This language is an immature mess, full of unresolved issues. Look for example at the monomorphism restriction in the Haskell Report”?
But my concern is you not making me spending my time reading the same unconstructive comment again and again in each thread related to Go
I don’t make you do anything. Just ignore things with my name on them.
what would you think if I would comment every story about OCaml
I would not care at all. You’re free to post such comments if you want, how you spend your time is your own business.
However, I reiterate, there have been between 4 and 6 Go posts in the past two weeks. I have commented on two of them critiquing Go. That is between 50% and 33% of Go posts I comment on. So no, I do not post on every Go post like you claim I do.
I would not care at all. You’re free to post such comments if you want, how you spend your time is your own business.
I get your point, but are you aware the purpose of a site like Lobsters is to be a place where we exchange information and try to have interesting conversations? If you don’t care at all about what other people write and how they react to your comments, then what the heck are you doing here???
I took the time to write a detailed reply, and your answer is just about the “controversy” part. What about the part related to representation of data structures in memory, monomorphism restriction, Go FAQ, etc.?
I get your point, but are you aware the purpose of a site like Lobsters is to be a place where we exchange information and try to have interesting conversations?
I am, are you? You are telling me to contribute less because you don’t agree with my perspective.
If you don’t care at all about what other people write and how they react to your comments, then what the heck are you doing here
I never said I don’t care about your comments, I said I would not care about the fact that you post on every Ocaml and Haskell because that is your decision.
I took the time to write a detailed reply, and your answer is just about the “controversy” part. What about the part related to representation of data structures in memory, monomorphism restriction, Go FAQ, etc.?
Because there isn’t much to be said here that has not been repeated over and over.
apy, bitemyapp and puffnfresh are your prototypical PL (programming language) snobs.
Some of us, like me, argue in favor of type safety because it can be a wonderful trade off. It buys you a lot. But it invariably costs you something too.
PL snobs, on the other hand, argue some variation of “a more expressive type system is obviously correct.” They almost always refuse to admit to any trade offs. Most of their criticism boils down to a laundry list of pet features that aren’t available in Go. Some of them go so far as to claim that Go is harming the practice of programming. Some of them insult the designers.
I don’t know where they come from. All the Haskell programmers (for example) I know are pretty upfront and honest about the trade offs of type systems.
The “trade offs” of type systems I often see are usually false compromises. I do use Haskell professionally rather than Idris, so I obviously acknowledge that there are some current problems with more types.
I don’t think I’m better than anyone because I don’t use Go (I used to)
I do think Go is harmful to programming, I’ve described why many times. I don’t share this opinion because I want higher status, I share it because I want people to think about using more capable tools.
Many people share this opinion, is there some sort of collective phenomena where people have become snobs?
I know plenty of people who don’t like Go because it doesn’t suit their tastes. It doesn’t always suit my tastes either. This is why I use a variety of languages.
Snobs take this one step further. It isn’t enough to just not like it, but instead, claim that it actually harms the practice of programming. This is a snob’s attitude because it is a presumption that you know the right trade offs for everyone else to make. (This isn’t just limited to technical trade offs, mind you!)
A more extreme example: @bitemyapp compared uses of Go to rejecting vaccinations. As far as I could tell, he was being sincere.
Go makes many false trade offs - I am aware of this more than some others, which is why I point it out. I do have a self interest, in that I don’t want to work with more not-great tools in the future and I think telling people gives me a better chance than not.
I ask you to not interpret my self interest as about status or snobbery.
You’re completely ignoring every criticism I’ve made. Moreover, you’ve demonstrated my point with this:
Go makes many false trade offs
This is why you’re a snob. You think you know the right trade offs for everyone else. But trade offs come in a variety of shapes and sizes. Not all of them are technical.
A piece of unsolicited advice: if you don’t want to come off as a snob, then instead of saying “Go makes many false trade offs” you could say, “Go makes many trade offs that do not suit me.” This is reasonable.
I don’t know what your self interest has to do anything. I’m all for evangelism. I encourage others to learn FP all the time. But evangelism does not have to be snobbery.
Parametric types don’t have to create a runtime cost. Parametric types have also been well understood for many decades, the “cost in complexity” for a language like Go would be next to nothing, especially when put relative to the huge benefits.
Caring at all about a negligible cost on compilation or implementation is a very silly thing to do.
So you acknowledge that there are trade offs. You just dismiss them as “silly” or “negligible.” Those are OPINIONS that you believe apply universally, not facts. Thus, you have demonstrated my point that you are a snob.
(That you think the compilation time of gc is “negligible” compared to that of ghc or ocamlopt is very interesting. The compilation time may be a worthwhile cost that you will happily pay, but once again, only a snob presumes that it is a worthwhile cost for everyone to pay.)
Is the current compilation speed of the Go compiler a well define target of N lines/time unit? As far as I can tell the Go compiler happens to have some performance and it’s now being held as sacred. The same with runtime. Generics would be too expensive, allegedly, but the current performance of interfaces and the GC is not.
Do you know the origin story of Go? They supposedly thought of it while waiting for other compilers to compile. It’s right there in the purpose of the project: compile large programs quickly.
Why is it “sacred” to want programs to compile fast?
Generics would be too expensive, allegedly, but the current performance of interfaces and the GC is not.
Yes. They are called trade offs. Did you know that some people can value certain sides of the trade off differently? It is possible that having a GC is more important than having generics.
To presume that you know the right set of trade offs for everyone else to make is the height of snobbery.
Ah sorry you’re misinterpreting my question. I’m not saying the trade offs are stupid here, I’m asking how the trade-offs are evaluated. As far as I can tell, the current compilation speed is just what they happen to be, not a specific target. So what makes extra compilation time of generics too expensive? Would compiling 2x slower be acceptable? 3x? If no, why not? Where do these numbers come from and how does one have a productive discussion about features otherwise? If there was no target, then why is GC and interface{} overhead acceptable but generics is not?
To presume that you know the right set of trade offs for everyone else to make is the height of snobbery.
I’m not presuming anything actually. Your attitude is just making assumptions about a genuine question.
As far as I can tell, the current compilation speed is just what they happen to be, not a specific target. So what makes extra compilation time of generics too expensive? Would compiling 2x slower be acceptable? 3x? If no, why not? Where do these numbers come from and how does one have a productive discussion about features otherwise?
I’m not in charge of Go, so I don’t really have any good answers for you other than “search the mailing list.” Numerous people have made proposals for generics of varying quality.
If there was no target, then why is GC and interface{} overhead acceptable but generics is not?
Using interface{} is not idiomatic Go, so I don’t know why you’re talking about it. If all you want to do is write abstract data types in Go, then you’re going to have a bad time. You can’t do it without sacrificing at least one of the following: generality (probably can’t call it an ADT in this case, I suppose), safety or performance.
It seems easy to forget that Go comes with built in abstract data types that are very common, and this greatly eases the burden of not having generics. This also relatively diminishes the value of full generics. This also makes Go fundamentally different from pre-generics Java/C++, which folks often cite as proof that Go will wind up needing generics some day. The trade offs are different when the language gives you polymorphic vectors, stacks, queues and hash tables.
This is known as the “Worse is Better” philosophy. Personally, I am a fan of both “Worse is Better” and “The Right Thing.” It seems like a lot of other folks like to pick one or the other.
The GC is highly valued because manual memory management becomes a very large chore when writing concurrent/CSP programs.
If you are looking for me to quantify “very large chore” relative to the chores of writing code without full generics in Go, then I’m afraid you’ll be disappointed. I don’t know how to quantify such things. All I know is that even though I love working in an expressive type system, I also don’t mind working in Go. Do I ever have to fight its type system? Yes. All the time? No way. Are there other parts of Go that I very much like—that have nothing to do with its type system—that make me want to use it? Yes. Trade offs my friend, trade offs.
I’m not in charge of Go, so I don’t really have any good answers for you other than “search the mailing list.” Numerous people have made proposals for generics of varying quality.
My question is completely independent of generics, I’m just trying to understand what the target is.
Using interface{} is not idiomatic Go
I’m sorry, I worded my statement wrong. It should have read “If there is no target, the why is the GC and interfaces overhead acceptable but generics are not?” My question doesn’t have anything to do with interface{}.
The core of my question is: you can’t talk about making trade-offs unless you’ve defined what the target is. It’s not trade-offs then, it’s just preferences.
The core of my question is: you can’t talk about making trade-offs unless you’ve defined what the target is. It’s not trade-offs then, it’s just preferences.
If you want targets, then read the Go FAQ. If you want a more nuanced view, then read the mailing list. As far as I’m aware, there are no precisely defined targets. I don’t see why this is requisite for trade offs to exist.
It’s not trade-offs then, it’s just preferences.
Preferences are absolutely trade offs! Many trade offs aren’t precisely technical. Some of them are about complexity, which can be an inherently subjective thing. (e.g., On most days of the week, I find Haskell to be beautifully simple. But so many others that I respect have said that they found it too complex. Who am I to discount their perception?)
This troll against me is patently false, I cannot speak to @bitemyapp or @puffnfresh, however at no point in this thread did I claim a more expressive type system is obviously correct. I stated my opinion of what I would expect to see in a language created by someone who stated Rule 5. If your opinion is that you would expect to see a language like Go given Rule 5 then that’s fine, that’s your opinion. I have mine. But there is no need to fall so low as to call me a PL Snob and make false claims as to my opinion of what is important in a programming language. Disagreeing with me is fine, but being an asshole is not. I have been respectful to you and would expect similar treatment.
PL snobs are annoying, so it is frustrating dealing with your ilk. Here are some selected quotes from you that support that moniker:
Unfortunately, the authors of Go have been done an excellent job convincing people that there is a contradiction between a more powerful type system and being simple and practical.
This implies that you’re either calling the authors of Go stupid or deceptive. This isn’t just a one off thing, you explicitly state as such here:
I think the claims that yourself, and Rob Pike, make in the link you posted are either ignorant or disingenuous.
…
Go is really cheating a whole generation of developers out of progress.
Why? This is what a PL snob says. Progress doesn’t have to be a more expressive type system. Go can make progress in other areas.
proponents of Go, and specifically its lack of generics, often sight that implementing them well in the type system and/or runtime is somehow an unsolved mystery
Actually, ‘ignorant’ and ‘stupid’ mean different things. Being ‘ignorant’ is not an insult. For example, you were ignorant of the distinction, that does not make you stupid.
Why? This is what a PL snob says.
Because a language like Ocaml has an expressive type system and is very close to equal in performance to Go and has pretty decent compile times. In this sense I believe the Go authors have made poor decisions. See what happens when you ask why rather than just make accusations? You get an answer.
This is a blatant misrepresentation.
Not from where I stand. The authors claim solving this problem and fitting inside their requirements is an unsolved mystery. If it were a solved mystery, Go would have generics. Can you explain why you think this is a misrepresentation?
You’re telling me that calling Griesemer, Pike and Thompson ignorant is not an insult?
I can understand how calling a budding computer scientist ignorant is not an insult. It’s no biggie, they are expected not to know something.
Calling top computer scientists—all with vast experience in language design—ignorant in precisely the thing they have experience in is most definitely an insult.
You may have niggled a little point about the distinction between ignorance and stupidity, but it is inconsequential to my argument: you make a point of being a PL snob by insulting those who design languages with type systems that aren’t as expressive as you’d like.
has pretty decent compile times
You’ve just conveniently pushed away one of the most important features of Go: its wicked fast compiler. Ocaml doesn’t even come close.
In this sense I believe the Go authors have made poor decisions.
They have only made poor decisions with respect to pleasing your sensibilities. That would be a completely reasonable and non-snobby thing to say.
Not from where I stand. The authors claim solving this problem and fitting inside their requirements is an unsolved mystery. If it were a solved mystery, Go would have generics. Can you explain why you think this is a misrepresentation?
The context of your quote implies that it really isn’t an unsolved mystery. Therefore, you are once again subtly implying that they are stupid (or ignorant, pick-your-favorite-insult).
Even experts in a field are ignorant of things in it. The Go team are not type theorists, as far as I can tell, and none of their previous languages have powerful type systems. So to claim they are possibly ignorant is hardly a stretch.
There have been long threads on the Go mailing list about such topics. They are not ignorant of them. They just don’t agree with your personal preferences. And for that, you claim they must be ignorant or disingenuous.
This is an excellent selection of quotes! I remember having read them too. I fully agree these quotes are snobbish and insulting. It’s difficult to interpret them in any other way.
@apy, according to you, what would be an example of a programming language including “the ability to make reusable data structures” and which does not suffer too much from the associated costs (language specification becoming too much complex, increased compilation time, code bloat when the compiler implements generics using monomorphization, or slow execution when the compiler implements generics using some kind of type erasure and/or boxing/unboxing)? A lot of people would be really interested by a constructive answer, because this is the crux of the issue. If you have no idea about this, then please stop.
So the easiest one of your criteria to game is ‘compilation time’ because acceptable compilation time is subjective. The language that fits for me is Ocaml. I find Ocaml compilation times quite acceptable. They are longer than Go’s but still better than C++ (IME). Ocaml has a powerful type system and, IMO, the language specification is not too complicated. I learned most of my Ocaml from reading the specification rather than a tutorial.
In terms of executable performance, Ocaml is on par with Go based on the Language Shootout, despite supporting a richer set of data structure abstractions. Of course this benchmark comes with all of the well known disclaimers of benchmarking. And one should note: the Ocaml compiler has not been given serious attention when it comes to optimization, so its performance can be improved.
There are other ways to game the system as well. mlton is often cited as producing extremely performant code at the cost of compilation time. But what SML developers do is develop using a faster compiler, such as SML/NJ, which has quick compilation times, and then build final releases in mlton. Since releases are built on the order of a few times, generally, the cost of mlton is minimal to the overall process. Of course that comes at the cost of a more complicated ecosystem (two compilers) but it’s possible to do something like clang or gcc and adjust the level of optimizations at compile time depending on if one wants faster compilation times or executables.
Thanks, we’re moving toward a constructive discussion :)
About compilation time: Is OCaml using some kind of incremental compilation (recompiling only the parts/modules that have been changed) or does it recompile everything always? And what is the usual build time for the programs you work on?
About language specification: I agree that OCaml authors have found a good balance between language expressiveness and language simplicity. The spec seems quite readable and not too long.
About execution performance: I read the source code of each benchmark in Go and OCaml. The Go version is generally shorter, which is unexpected considering OCaml emphasis on expressiveness. Do you know why?
I also noticed some code duplications that I don’t understand in spectralnorm (eval_A_times_u and eval_At_times_u) and knucleotide (write_frequencies15 and write_frequencies16, write_count15 and write_count16). These are typically the kind of duplications that I don’t expect in a language which supports parametric polymorphism and algebraic data types. Is it for optimization purposes?
And one should note: the Ocaml compiler has not been given serious attention when it comes to optimization, so its performance can be improved.
This is a weird argument. It’s like saying “Interpreted languages are slow but it’s because we’ve not given serious attention to optimization”. The truth is this is harder to optimize most interpreted languages. The cost of development of a runtime like V8 is very very high. It’s like saying “C++ templates compilation is slow but it’s because we’ve not given serious attention to it”. The truth is this is harder to compile quickly for structural reason. OCaml gives more expressiveness and safety to the programmer, and this is good, but it also complicates things on the compiler-side and there is a cost there that must be taken into account.
mlton is often cited as producing extremely performant code at the cost of compilation time.
I agree that having different compilers for development and building the production binary is an interesting strategy.
What about the strategy used by the compiler(s) to implement generics? Do you know about this? Does the compiler generates one polymorphic version of the code or many specialized versions for each type (monomorphization)? I think that MLton uses the latter strategy.
Is OCaml using some kind of incremental compilation
Ocaml itself is not concerned with how you compile it. I use makefiles which means I only recompile the subtree that depends on the changes. Most other ocaml build tools do this as well, but this is a separate concern of the actual language.
About execution performance: I read the source code of each benchmark in Go and OCaml. The Go version is generally shorter, which is unexpected considering OCaml emphasis on expressiveness. Do you know why?
Sorry, no, I haven’t read the code on the language shootout. I use the link more of an indication that one can acheive roughly equivalent performance even with a more expressive type system like Ocaml. I don’t actually think the language shootout is very good for much else, in a large system a lot of these micro benchmarks are drowned out by real-world issues.
So in reality, Go is probably slightly faster than Ocaml in a lot of cases, however when it matters Ocaml let’s you write fast code.
This is a weird argument. It’s like saying “Interpreted languages are slow but it’s because we’ve not given serious attention to optimization”.
I’m saying something differently though. Compilers like mlton demonstrate you can compile an ML to be highly optimized and efficient. Nothing in the semantics of the language prohibit this. This simply has not been a priority for Ocaml since, for the most part, it’s fast enough. So the work has been done for Ocaml’s twin, it’s just not worth it yet. Which is different than saying that one thinks a problem is solvable if they work hard enough.
What about the strategy used by the compiler(s) to implement generics?
The way this works in Ocaml is, in the worst case, you use some extra space to represent your data with a header and the actual value. So, boxing. Again, as a low-bar, one can see that the memory consumption between Go and Ocaml are roughly equivalent in the language shootout. In my experience the memory consumption of an Ocaml program is much smaller than equivalent Java, Python, or Ruby apps. C is of course smaller and I cannot speak to C++. Where possible the compiler can optimize the boxes away, for example if all of the computation happens inside the function, values will be put into registers sometimes. The Ocaml compiler does not do any monomorphic optimizations, AFAIK. Yes, mlton monomorphises everything, which is one reason it’s so expensive.
BTW, do you know how Go implements interfaces btw? I would imagine it requires boxing as a place to put the data + vtable. Is this correct?
you use some extra space to represent your data with a header and the actual value.
Do you know if the value is stored alongside the header or is stored as a pointer to the actual data?
I’m asking because this is a game changer in some cases. Let’s say we want to create an array of 100 (x, y) integer pairs. In Go, with no interface, on a 64 bits machine, this will be stored in 100 x 2 x 4 = 800 contiguous bytes. In Java, for example, what you will get is an array of 100 pointers, pointing to 100 pairs allocated separately on the heap. It creates a lot of indirection and put a lot of pressure on the garbage collector.
How does it work in idiomatic OCaml?
The Ocaml compiler does not do any monomorphic optimizations, AFAIK.
It makes sense because, as far as I know, this is the only way to get incremental compilation.
BTW, do you know how Go implements interfaces btw? I would imagine it requires boxing as a place to put the data + vtable. Is this correct?
Yes, this is quite close to what you imagine. A value of type interface is represented in memory as a pair of two words, one pointing to a kind of vtable (an itable), the other pointing to the data. Here is a good explanation by one of Go’s authors: http://research.swtch.com/interfaces.
Please note that you pay the price of this indirection only when you need an interface.
From what I understand, and the details can be found in RWO[1], the representation of a value in Ocaml is just about what you described for an interface in Go. At least two words (although I think integers have some space optimization here), adjacent to each other. And records have some tricks to pack values together.
I’m unsure of the specifics of the array situation. I believe they are boxed, however Ocaml BigArrays are not boxed for some times if possible.
Thanks for the link.
Given what you described, what is the actual runtime cost incurred by generics if the implementation is equivalent to how interfaces are already implemented?
Thanks for the link! It is an excellent explanation of OCaml memory representation.
You are right about the representation of a value in OCaml being similar to the representation of an interface value in Go (even with some significant semantic and operational differences). It follows they should have similar performance characteristics.
I think that using this approach for everything is ok in OCaml considering the goals and the use cases of the language. It simplifies a lot the implementation because the compiler does not need to generate a specialized version of each function for each possible type. It just needs to generate an efficient polymorphic version of the code and it is done.
But this approach would be difficult to reconcile with the goals of Go. Go is positioned as a systems programming language (to program application servers, not operating systems). Using boxing almost everywhere is not an option here. This is the reason why interfaces are not the default mechanism for everything. This is also the reason why generics are a little bit more difficult to implement than in OCaml.
Java is well-known for having a problem with this. For illustration, here is an excerpt of what the Disruptor project says about it [1]:
There is a proposal by John Rose to introduce “value types” to the Java language which would allow arrays of tuples, like other languages such as C, and so ensure that memory would be allocated contiguously and avoid the pointer indirection.
To conclude, I think that Go will have some form of generics one day. I think it will not be based on some kind of monomorphization because it would increase compilation time a lot, which is one of Go’s major goals. So we’re left with the compiler generating polymorphic code like OCaml. For generic containers, which generally don’t need to know anything about the element type behavior, except its size and sometimes an equality operator, we don’t need interfaces and the performance can stay high (it looks like built-in arrays/slices/maps/chanels work like this according to a quick read of the runtime code). But for other purposes, generics will probably depend on interfaces and have the same performance characteristics than in OCaml. There is no silver bullet :)
But this approach would be difficult to reconcile with the goals of Go. Go is positioned as a systems programming language (to program application servers, not operating systems). Using boxing almost everywhere is not an option here.
Why? Ocaml is used as a systems programming language as well, boxing has not been an issue. Java is one of the most used server side languages and it boxes everything. I think this statement has zero evidence to back it up.
This is the reason why interfaces are not the default mechanism for everything. This is also the reason why generics are a little bit more difficult to implement than in OCaml.
If I need to do anything generic-like in Go, I have to use some kind of interface, the worst case being interface{}. Therefore: I already have to drop to interfaces to do generic things, so I why can’t I implement generics as a compile-time construct that produces interface{} code? I’m not saying you should, I’m saying as a thought experiment these things are semantically equivalent. You only need to drop to a boxed value when you’re doing something generic, and the compiler knows when you’re doing something generic, so it can produce code equivalent to what a human would write, but proven correct.
Note: this does not restrict you from writing a container that is specific to your type (which is the current state of Go) but it provides the ability to provide generic data structures at a cost of some pointer indirection. So you’re in no worse a state than today. And for many problems the extra indirection does not matter. See Rule 1.
The runtime cost is related to pointer indirections and having to allocate/free memory on the heap for each value.
Yes, as I said Ocaml provides tools to remove the indirection in performance critical places. BigArray was explicitly made for this. And record types have some optimizations on this that one can make use of.
Why? Ocaml is used as a systems programming language as well, boxing has not been an issue. Java is one of the most used server side languages and it boxes everything.
It obviously depends on how we define systems programming. So I’ll try to be more explicit. Go wants to be able to replace C and C++ in most circumstances. One of the distinctive features of C/C++ is the strong control it gives over memory layout and the use of pointers and references. Go aims for a similar flexibility. This is the reason why boxing cannot be the default.
I think this statement has zero evidence to back it up.
Zero evidence? I shared a link about the Disruptor library, where this problem is discussed very explicitly. This is even one of the important reason for developing this library in the first place.
You only need to drop to a boxed value when you’re doing something generic, and the compiler knows when you’re doing something generic, so it can produce code equivalent to what a human would write, but proven correct.
I agree. This is exactly what I wrote at the end of my comment. And I think that Go will have generics one day based on something similar, at least in the general case.
At this point in time, C++ and Java generally compete for the same turf. And Java usually wins. Even in the Disruptor quote you made, it’s an off-handed comment and hardly represents a serious roadblock. And let’s be clear, LMAX is doing a ridiculous number of transactions per second, significantly larger than a vast majority of Go developers will experience. So your claim that boxing is a showstopper has no evidence behind it (Java is still massively popular and performant).
At this point in time, C++ and Java generally compete for the same turf. And Java usually wins.
Interesting. Any evidence of this?
And let’s be clear, LMAX is doing a ridiculous number of transactions per second, significantly larger than a vast majority of Go developers will experience.
What is your source for such a claim? You like to ask for evidence, which is legitimate, so I think it’s fair that you hold yourself to the same standard.
So your claim that boxing is a showstopper has no evidence behind it
I did not write that boxing is a “showstopper”. I wrote that boxing cannot be the default behavior in Go because it has a runtime cost that Go designers are probably not willing to pay when generics/interfaces are not used. Languages like C, C++ and Rust don’t box everything for the same reason. Even Haskell has its SPECIALIZE pragma. I’m just saying that it’s significantly easier to implement generics in a language where everything is boxed.
It depends on which thing you are asking for evidence for. Java and C++ competing for the same turf should be self evident. The turf that Java does not compete for that C++ owns is games, but Go isn’t competing for there anyways so we can disregard it. But in terms of service backends, Java has been shown to be doing well here. Netflix, Amazon, Facebook, Google, basically any financial firm, has some core component written in Java. I take back my claim that “java usually wins”. And I’ll rephrase it: In my experience, Java usually wins. I have never worked in a company that decided to rewrite some component in C++. I have worked at many that have decided to rewrite a component in Java. On top of that, basically all vendor solution in the financial industry is in Java. HealthCare.gov’s core components were in Java. The list goes on. That is not to say C++ is being marginalized, but Java is clearly a powerful contender in the space Go is trying to win.
What is your source for such a claim? You like to ask for evidence, which is legitimate, so I think it’s fair that you hold yourself to the same standard.
Did you read the paper you linked to? It states:
On processors at moderate clock rates we have seen over 25 million messages per second and latencies lower than 50 nanoseconds.
LMAX is a betting exchange that, according to Martin Thompson, handles more transactions per day than every financial exchange on the internet.
Given that: it’s clear, even by Rob Pike’s admission, that a significant number of people flocking to Go are coming from the Python and Ruby community, for which their goal is to be able to handle messages counted in the thousands per second for the most part.
And in general: not many companies reach the scale of doing millions of messages per second.
I wrote that boxing cannot be the default behavior in Go because it has a runtime cost that Go designers are probably not willing to pay when generics/interfaces are not used.
To recap:
I have shown you that Java and Ocaml, languages that box everything by default, can have performance as good as Go’s. We’ve also discussed that the compiler could do exactly what a human does right now when they want generics (convert to/from interface{}), meaning that things would not be boxed by default. This would likely increase compiler time, but by how much is unclear. It’s also unclear to me what is specifically important about the current compiler times other than that is what the happen to be. Would compilation taking 2x longer be acceptable? If not, why not?
So far I have not heard you provide a concrete reason why either boxing or implicit interface{} conversion is unsuitable for Go.
Java and C++ competing for the same turf should be self evident. […] That is not to say C++ is being marginalized, but Java is clearly a powerful contender in the space Go is trying to win.
Yes, so what? How is it relevant to the question of why Go does not have generics today and how it can have them tomorrow?
Did you read the paper you linked to?
Yes, my friend. This is usually what I do before sharing a link.
On this topic, in a former comment, you wrote:
Ocaml is used as a systems programming language as well, boxing has not been an issue. Java is one of the most used server side languages and it boxes everything. I think this statement has zero evidence to back it up.
At some point, if you’re genuinely interested in language design and implementation, you also have to do your own research. The Disruptor paper talks about a proposal to introduce value types to Java (in the paragraph I quoted earlier). Here is the proposal:
Is it enough “evidence” for you that boxing can be a problem? Again, nobody is saying that boxing is a “showstopper” (your word); it’s just a tradeoff with advantages, and drawbacks.
And in general: not many companies reach the scale of doing millions of messages per second.
No, for sure. And Google, where Go was designed, is obviously not one of them… Don’t you see how ridiculous this argument is?
I have shown you that Java and Ocaml, languages that box everything by default, can have performance as good as Go’s.
No, you have not.
So far I have not heard you provide a concrete reason why either boxing or implicit interface{} conversion is unsuitable for Go.
I have provided some reasons that you happily ignored or rejected, because they don’t fit your view of the world or you language design preferences.
I think I will probably follow the advice you gave me in a past comment and stop reading what you write. You are so exaggeratedly argumentative. I reread the thread and it’s quite clear that you have absolutely no interest in understanding why Go does not have generics already, and how they can be added in the future. I think you’re mostly interested in arguing that your tools of choice are superior, and that Go designers and users are wrong.
Discussing with you sounds more like lawyers on opposing sides arguing in court, than engineers on the same team sharing knowledge and looking for solutions.
Language design and implementation are complex issues. They cannot be discussed by dropping anecdotical evidences and jumping from one argument to the other, depending on what best suits your end goal.
There is something irritating and disrespectful in the way you write about adding generics to Go being something obvious, “a solved problem”. If it was so obvious, don’t you think someone would already have submitted a working solution with code and documentation, and convinced the core team to merge it?
I’m curious to know who you are, what you do for a living and what are your achievements in language design? What makes you so sure that you’re right and the whole Go team is wrong?
For the record, my name is Nicolas Grilly. If you ever had the opportunity, one day, to recruit me in your team, please don’t. I would probably hate engineering something with you.
But this approach would be difficult to reconcile with the goals of Go. Go is positioned as a systems programming language (to program application servers, not operating systems). Using boxing almost everywhere is not an option here.
To which I demonstrated that Java, a language which boxes (almost) everything by default, competes very successfully in the same space as Go. And Disruptor also handles a significant number of transactions per second.
Is it enough “evidence” for you that boxing can be a problem?
That will help get more performance out of it, sure. But that is a different argument than the one I am making. I am claiming that Java, with boxed values, already has ridiculously good performance given its near ubiquitous position in the world, as such my statement is that your claim that being boxed everywhere is at direct opposition to being a systems language lacks evidence. It would be nice to know what the actual run-time targets are, as well. How can one state that the run-time costs would be too expensive if the actual target doesn’t exist? Perhaps I’m missing it but snooping around the Go forums did not turn up anything for me.
No, for sure. And Google, where Go was designed, is obviously not one of them… Don’t you see how ridiculous this argument is?
Yes, that is a fair point. But I think my point was communicated poorly. Again, you are saying that because of the domain Go is aiming at, boxing is unacceptable. However, Disruptor does an insane number of tps, so your statement doesn’t hold up to the evidence. My claim that most Go developers won’t experience a comparable tps was really a red herring and I should have left it out.
I have shown you that Java and Ocaml, languages that box everything by default, can have performance as good as Go’s.
No, you have not.
I provided a link to the language shootout showing Ocaml about equal to Go. So yes, I have. If your statement is actually that I have shown you evidence but you question the quality of it, well that is a matter of perspective and I can’t really argue with that.
several paragraphs of attacks against me and my character
From my perspective the following claims have been made:
The compilation-time cost would be too expensive
The run-time cost would be too expensive
In response I have:
Shown that Java, a language with generics and boxes everything, has solid performance. Disruptor being able to hit tps of around 25million.
Ocaml, a language with generics and boxes everything can have performance on par with Go.
Asked what the actual targets for compilation-time and run-time are, with no answer. This point in particular makes any discussion almost impossible. Without an actual target it’s impossible to know if a proposal is too expensive or not.
Suggested an implementation that would have the compiler create code that is the exact same as what Go developers would write now (casting to interface{} and back), providing no extra run-time cost, but clearly at some (unknown) compile-time cost.
Given the above, I feel that I have made an effort to understand why Go does not have generics and provided counter evidence to existing claims as to why it doesn’t. IMO, the responses I’ve received have only been authoritarian: “the authors of Go don’t see a solution they like” but without providing any specifics beyond that.
If you have provided a linked which goes into details what the requirements are for the authors to add generics to the language then I’m sorry that I have missed it, please link me again.
For the record, my name is Nicolas Grilly. If you ever had the opportunity, one day, to recruit me in your team, please don’t. I would probably hate engineering something with you.
I’m sorry you feel that way, but that is a disrespectful and unneeded comment to make. At no point have I insulted you, speculated as to what it would be like to work with you, or made hypothesis about your character. In my opinion this thread has been full of great discussion and healthy disagreement and I’m happy to have been a part of it.
9) It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.
However the mathematician in me always looks for the exceptions… and finds it.
The idea behind that is if you have the 10 functions for each of 10 data structures, you only have a vocabulary of 10 to operate on any one data structure, and you cannot use the other 90……..
Moral of the story…. store everything as a string….
Just kidding. Sort of.
Personally I don’t like that epigram. I’d replace it with “Understand relational algebra. Use it.”
These rules are presented out of context. They are part of a longer article, “Notes on Programming in C”, published in 1989, in a section of the article about most programs being unnecessarily complex.
Which contains a line I’ve read before and always been completely baffled by:
…thousands of needless lines of code passing through the lexical analyzer, which is (in good compilers) the most expensive phase.
I completely fail to see how expensive lexical analysis could ever be (or have been) considered a mark of a good compiler. Lexical analysis is a “simple” problem: given an input, there is exactly one correct output; taking a long time to arrive at that result seems like a bad thing to me. Code generation, on the other hand, is a less simple problem (and a much more interesting one if you ask me): for a given input, there are many possible correct outputs; choosing a good one from that (large) space is a tricky problem, and spending some time on doing a good job of it could be seen as the sign of a good compiler.
I’ve always wondered just what the heck Pike was thinking when he wrote that…
I find Rule 5 interesting given how much Go disenfranchises data structure authors. If data structures are important to developing software then surely one would use a language that maximizes reusability of data structures.
Also, I think it’s interesting how biased the list is towards performance rather than developing software in general. There is nothing in here about decoupling components or how to think about abstraction. But I don’t know what context these rules were taken from.
This is an opinion; not a fact. It disenfranchises data structure authors insomuch as you don’t approve with the abstraction power provided in Go. For example, I do not feel disenfranchised when I write Go programs.
On the other hand, idiomatic Go includes the ability to precisely specify how your data is laid out in memory. Depending on what you’re trying to do, this would be the exact opposite of disenfranchising data structure authors.
I do not claim these things are mutually exclusive.
The list of rules seem like pretty general maxims. Specific advice about decoupling or examples of good abstraction would feel out of place in a list like this. Often merely pointing someone toward the data rather than the algorithm is enough to motivate a better design.
I disagree. Programming Epigrams has 121 pithy sentences, some of which give nice general maxims that would have fit here just fine. I also think Rule 1 adequately expresses Rules 2 and 3.
It is a fact that if you wish to author a data structure in Go, you are disenfranchised. Because you can’t author a data structure, you can only author a data structure that holds a particular type.
And why do you care about this? Performance? See Rule 1. I’d rather have a bunch of data structures at my finger tips that I can then rewrite with precise memory layouts than the alternative.
But my point is not that Go’s design philosophy is good or bad. But that if the author of Go feels data structures are important (which Rule 5 implies but it’s one sentence out of millions from the author, so who knows) then Go unequivocally make developing data structures a more burdensome task. That is a different statement than saying I don’t like Go because it makes writing data structures burdensome.
Data structures have nothing to do polymorphism. They are orthogonal concepts. A data structure is just a way to organize data in memory. That’s it. If the OP were talking about abstract data types, then your musings about the apparent contradictory notions of Rob Pike would be more poignant.
Great! That’s a totally valid opinion. But that’s all it is, an opinion. It’s a trade off that works for you. It is not a universal maxim.
No. Go makes developing abstract data types (without sacrificing safety or performance) difficult. I would absolutely agree with this. It was an explicit design decision.
I think you’re drawing a false line between data structures and abstract data structures. My argument is that if one feels data structures are an important component in solving problems I would expect them to be given a stronger fist class status. This includes the ability to make reusable data structures. The fact that writing concrete data structure in Go is well support but reusable ones is not is a weakness IF one believes data structures are important. In this sense, Go has done nothing to advance the state of data structures in C.
And I’m not arguing anything is a maxim. My statement this entire time has been that it is my opinion that this decision is interesting given Rule 5.
Except Pike did not say “abstract data types.” He said “data structures.” So there’s no inconsistency here.
And where we disagree is I think ADTs are a subset of DTs. You’re entitled to your own opinion on the hierarchy.
However my point is not limited to generics. As I stated in the Reddit thread, Go also lacks powerful tools for data structures such as Algebraic Data Types.
Do you think that Rob Pike was considering abstract data types when talking about data structures? I don’t. If you agree with that, then there should be nothing surprising about what he said.
Yes. Indeed. Trade offs abound.
Yes, I do. IMO the statement doesn’t make much sense otherwise. But to reiterate: as I’ve said that’s my opinion, so you’re free to side on any bias you prefer like I have.
Are you aware that the complete article, from which these 5 rules were extracted, was published in 1989?
All the more reason apy’s comments are on point.
Pike realized the importance of data structures to solving problems in 1989. Nearly 20 years later a language he designed does not make it easier to solve problems via data structures. That’s very surprising.
Why is that surprising? The Go team is perfectly aware of the existence and principles of generics and ADT (as stated in the language’s FAQ). I also think they care about these questions and are definitely smart people. So maybe they just made tradeoffs different from what you expect?
You write like the design choice of integrating generics and ADT in a language is superior by nature. What about the costs?
Have you read the full article? [1] Pike advises to use simple algorithms and simple data structures and goes on with a list of data structures that are sufficient for almost all practical programs: array, linked list, hash table and binary trees. Maybe this explains why he (and the rest of team) does not feel an urgent need for generics and ADT.
[1] http://www.lysator.liu.se/c/pikestyle.html
I’m not sure why this is so difficult to explain, but I will try again. What @owen and myself are saying is, if data structures are important to someone, I would expect them to favor abstractions and trade-offs that favor data structures. This is not what one sees in Go. This is all I am saying. I am well aware of the trade-offs that exist in Go and the stated reasons for them by the authors.
For example, for historical reasons the authors of C favor simplicity and minimizing the distance between the developer and the machine, as such I would expect that C lacks numerous abstraction capabilities that requires a more complicated compiler and remove you from the hardware. And this is what I see.
Java’s authors favored removing platform specifics from developers, as such I would expect to see a high level of abstraction from the underlying hardware and heavy set of optimizations. And this is what I see.
The author of Pascal favored simplicity and understandability of a language, as such I would expect to see a language that is straight forward to learn and make trade-offs in favor of readability rather than expressiveness. And this is whatI see.
If the author views data structures as the core component of a program, I would expect the author to make trade-offs to provide developers the ability a lot of expressive power when it comes to data structures. This is what I see in Ocaml and Haskell, this is not what I see in Go. The obvious counter point is “well that says more about you than it does about the authors of Go”. And yes, it does, and my statement really has no more depth or deeper meaning than that.
I’m not sure how this was down voted for being ‘incorrect’ considering it’s clearly an opinion post.
I’m not the one having downvoted this, but my guess is the downvoter thinks your comment is “incorrect” because you use 5 rules, completely out of context, written 15 years ago, to draw conclusions about what Rob Pike thinks and how he should have designed Go. This is very reductive. Or maybe the downvoter was just bored.
Your bias is pretty clear. This is the second conversation I’ve had with you in as many weeks where you’ve lambasted Go and its designers. (In this thread, you’ve politely called Pike an idiot and in the other you accused them of a campaign to mislead everyone.)
But you’re in good company. Lashing out at newer languages with type systems that don’t meet one’s personal standard of expressiveness is the trendy thing to do these days.
At no point in this thread did I call Pike an idiot. I expressed my surprise at what I would have expected given Rule 5. Please accuse me of things I’ve actually done.
It is exact that you did not called Pike an idiot explicitly. But your comments strongly suggests that he is one. In my opinion, you’re playing with words like a professional politician ;-)
If I thought Rob Pike was an idiot I’d call Rob Pike an idiot. Rob Pike and I heavily disagree on programming languages, that is all.
“Advancing the state of data structures in C” has never been a goal of Go. So what is your point?
Have you some kind of personal issue with Rob Pike and Go? It looks like you never miss an opportunity to criticize Rob Pike’s work and Go, even when the linked article is just about five random rules, presented out of context, and published in 1989!
To be very clear, I appreciate some your points about Go shortcomings, and understand why you seemingly prefer languages like Haskell or OCaml. But other professionals have different tradeoffs than yours that lead them to different choices in terms of programming tools.
I fail to understand why you spend time commenting every thread related to Go, even in very indirect or remote way, to just repeat that the language miss generics, algebraic data types, pattern matching, pure functions, etc., in short, all typical features of modern functional languages. This is just stating the obvious. It’s even clearly explained in Go’s own FAQ!
The fact that this post is about Rob Pike is only incidental to my comment. But I think many people are interpreting my statement incorrectly, which is my own fault. All I said was that the author of the quote states the data structures are important to solving problems, as such I’m surprised the language they created does not make expressing solutions in terms of data structures easier. For example, Ocaml and Haskell developers find data structures important to solving problems. As such, those languages provide a rich set of tools for expressing solutions to problems in terms of data structures.
And no, how could I have a personal issue with Rob Pike? I’ve never met him or had a conversation with him. I would imagine he’s a very pleasant and interesting and intelligent person to be around. I think you are suffering from selection bias: I’m critical of just about everything, you just happen to read more Go posts or Go posts are more popular right now.
I’ll spend my time how I want even if it confuses you.
Hello @apy,
Thanks for answering.
I disagree. Go provides a lot of things that makes defining and using data structures easy and efficient by default:
I agree that having parametric polymorphism and sum types in OCaml and Haskell is great in some cases. But it can also makes the language specification complex (for example have a look at the infamous “monomorphism restriction” in the Haskell Report) and, as far as I know, you lose the benefits of the efficient memory representation Go provides by default.
No, I’m not. It happens that I also read the threads related to functional programming, Haskell, OCaml, ML et al, and I don’t see you putting the same energy and repetitiveness in your critic of these threads.
Ok, you’re right. How you spend your time is not my concern :) But my concern is you not making me spending my time reading the same unconstructive comment again and again in each thread related to Go. Again, official Go’s FAQ clearly states that the language does not have generics or sum types at this time, and explains why.
And to conclude, what would you think if I would comment every story about OCaml with “This language is just a mess! We are in 2014, concurrency is all the rage, and OCaml still has a global lock.” and every story about Haskell with “This language is an immature mess, full of unresolved issues. Look for example at the monomorphism restriction in the Haskell Report”?
I don’t make you do anything. Just ignore things with my name on them.
I would not care at all. You’re free to post such comments if you want, how you spend your time is your own business.
However, I reiterate, there have been between 4 and 6 Go posts in the past two weeks. I have commented on two of them critiquing Go. That is between 50% and 33% of Go posts I comment on. So no, I do not post on every Go post like you claim I do.
You wrote:
And:
I get your point, but are you aware the purpose of a site like Lobsters is to be a place where we exchange information and try to have interesting conversations? If you don’t care at all about what other people write and how they react to your comments, then what the heck are you doing here???
I took the time to write a detailed reply, and your answer is just about the “controversy” part. What about the part related to representation of data structures in memory, monomorphism restriction, Go FAQ, etc.?
I am, are you? You are telling me to contribute less because you don’t agree with my perspective.
I never said I don’t care about your comments, I said I would not care about the fact that you post on every Ocaml and Haskell because that is your decision.
Because there isn’t much to be said here that has not been repeated over and over.
It looks like we definitely live on different planets.
apy, bitemyapp and puffnfresh are your prototypical PL (programming language) snobs.
Some of us, like me, argue in favor of type safety because it can be a wonderful trade off. It buys you a lot. But it invariably costs you something too.
PL snobs, on the other hand, argue some variation of “a more expressive type system is obviously correct.” They almost always refuse to admit to any trade offs. Most of their criticism boils down to a laundry list of pet features that aren’t available in Go. Some of them go so far as to claim that Go is harming the practice of programming. Some of them insult the designers.
I don’t know where they come from. All the Haskell programmers (for example) I know are pretty upfront and honest about the trade offs of type systems.
I do believe that some tools (i.e. programming languages) are better than others. Please rethink about whether that makes me a dishonest snob.
The “trade offs” of type systems I often see are usually false compromises. I do use Haskell professionally rather than Idris, so I obviously acknowledge that there are some current problems with more types.
That is not what makes you a snob. We all have our preferences. You’re twisting what I said.
I’ve seen you make comments to the effect of “Go is harmful to programming.” That’s a snobbish comment.
I don’t know what you mean by snobbish.
I know plenty of people who don’t like Go because it doesn’t suit their tastes. It doesn’t always suit my tastes either. This is why I use a variety of languages.
Snobs take this one step further. It isn’t enough to just not like it, but instead, claim that it actually harms the practice of programming. This is a snob’s attitude because it is a presumption that you know the right trade offs for everyone else to make. (This isn’t just limited to technical trade offs, mind you!)
A more extreme example: @bitemyapp compared uses of Go to rejecting vaccinations. As far as I could tell, he was being sincere.
Go makes many false trade offs - I am aware of this more than some others, which is why I point it out. I do have a self interest, in that I don’t want to work with more not-great tools in the future and I think telling people gives me a better chance than not.
I ask you to not interpret my self interest as about status or snobbery.
@puffnfresh, two questions for you:
You’re completely ignoring every criticism I’ve made. Moreover, you’ve demonstrated my point with this:
This is why you’re a snob. You think you know the right trade offs for everyone else. But trade offs come in a variety of shapes and sizes. Not all of them are technical.
A piece of unsolicited advice: if you don’t want to come off as a snob, then instead of saying “Go makes many false trade offs” you could say, “Go makes many trade offs that do not suit me.” This is reasonable.
I don’t know what your self interest has to do anything. I’m all for evangelism. I encourage others to learn FP all the time. But evangelism does not have to be snobbery.
I’m not even acknowledging Go actually makes trade offs. You’re working under the assumption that Go’s claimed trade offs do exist.
If they don’t exist, then you’re implying that generics are free. That is:
If you agree with the above statements, then I’d say we’re at a pretty solid impasse.
If you disagree with the above statements, then you acknowledge that there exists trade offs.
Parametric types don’t have to create a runtime cost. Parametric types have also been well understood for many decades, the “cost in complexity” for a language like Go would be next to nothing, especially when put relative to the huge benefits.
Caring at all about a negligible cost on compilation or implementation is a very silly thing to do.
Parametric types have a runtime cost:
That’s not the end of the world, but there is a cost.
So you acknowledge that there are trade offs. You just dismiss them as “silly” or “negligible.” Those are OPINIONS that you believe apply universally, not facts. Thus, you have demonstrated my point that you are a snob.
(That you think the compilation time of
gcis “negligible” compared to that ofghcorocamloptis very interesting. The compilation time may be a worthwhile cost that you will happily pay, but once again, only a snob presumes that it is a worthwhile cost for everyone to pay.)Is the current compilation speed of the Go compiler a well define target of N lines/time unit? As far as I can tell the Go compiler happens to have some performance and it’s now being held as sacred. The same with runtime. Generics would be too expensive, allegedly, but the current performance of interfaces and the GC is not.
No, it’s not sacred. It’s still subject to improvements and a major goal of Go. Look for example:
http://dave.cheney.net/2014/05/22/go-1-3-linker-improvements
I don’t know of any well defined target.
Do you know the origin story of Go? They supposedly thought of it while waiting for other compilers to compile. It’s right there in the purpose of the project: compile large programs quickly.
Why is it “sacred” to want programs to compile fast?
Yes. They are called trade offs. Did you know that some people can value certain sides of the trade off differently? It is possible that having a GC is more important than having generics.
To presume that you know the right set of trade offs for everyone else to make is the height of snobbery.
Ah sorry you’re misinterpreting my question. I’m not saying the trade offs are stupid here, I’m asking how the trade-offs are evaluated. As far as I can tell, the current compilation speed is just what they happen to be, not a specific target. So what makes extra compilation time of generics too expensive? Would compiling 2x slower be acceptable? 3x? If no, why not? Where do these numbers come from and how does one have a productive discussion about features otherwise? If there was no target, then why is GC and
interface{}overhead acceptable but generics is not?I’m not presuming anything actually. Your attitude is just making assumptions about a genuine question.
I’m not in charge of Go, so I don’t really have any good answers for you other than “search the mailing list.” Numerous people have made proposals for generics of varying quality.
Using
interface{}is not idiomatic Go, so I don’t know why you’re talking about it. If all you want to do is write abstract data types in Go, then you’re going to have a bad time. You can’t do it without sacrificing at least one of the following: generality (probably can’t call it an ADT in this case, I suppose), safety or performance.It seems easy to forget that Go comes with built in abstract data types that are very common, and this greatly eases the burden of not having generics. This also relatively diminishes the value of full generics. This also makes Go fundamentally different from pre-generics Java/C++, which folks often cite as proof that Go will wind up needing generics some day. The trade offs are different when the language gives you polymorphic vectors, stacks, queues and hash tables.
This is known as the “Worse is Better” philosophy. Personally, I am a fan of both “Worse is Better” and “The Right Thing.” It seems like a lot of other folks like to pick one or the other.
The GC is highly valued because manual memory management becomes a very large chore when writing concurrent/CSP programs.
If you are looking for me to quantify “very large chore” relative to the chores of writing code without full generics in Go, then I’m afraid you’ll be disappointed. I don’t know how to quantify such things. All I know is that even though I love working in an expressive type system, I also don’t mind working in Go. Do I ever have to fight its type system? Yes. All the time? No way. Are there other parts of Go that I very much like—that have nothing to do with its type system—that make me want to use it? Yes. Trade offs my friend, trade offs.
My question is completely independent of generics, I’m just trying to understand what the target is.
I’m sorry, I worded my statement wrong. It should have read “If there is no target, the why is the GC and interfaces overhead acceptable but generics are not?” My question doesn’t have anything to do with
interface{}.The core of my question is: you can’t talk about making trade-offs unless you’ve defined what the target is. It’s not trade-offs then, it’s just preferences.
If you want targets, then read the Go FAQ. If you want a more nuanced view, then read the mailing list. As far as I’m aware, there are no precisely defined targets. I don’t see why this is requisite for trade offs to exist.
Preferences are absolutely trade offs! Many trade offs aren’t precisely technical. Some of them are about complexity, which can be an inherently subjective thing. (e.g., On most days of the week, I find Haskell to be beautifully simple. But so many others that I respect have said that they found it too complex. Who am I to discount their perception?)
This troll against me is patently false, I cannot speak to @bitemyapp or @puffnfresh, however at no point in this thread did I claim a more expressive type system is obviously correct. I stated my opinion of what I would expect to see in a language created by someone who stated Rule 5. If your opinion is that you would expect to see a language like Go given Rule 5 then that’s fine, that’s your opinion. I have mine. But there is no need to fall so low as to call me a PL Snob and make false claims as to my opinion of what is important in a programming language. Disagreeing with me is fine, but being an asshole is not. I have been respectful to you and would expect similar treatment.
PL snobs are annoying, so it is frustrating dealing with your ilk. Here are some selected quotes from you that support that moniker:
This implies that you’re either calling the authors of Go stupid or deceptive. This isn’t just a one off thing, you explicitly state as such here:
…
Why? This is what a PL snob says. Progress doesn’t have to be a more expressive type system. Go can make progress in other areas.
This is a blatant misrepresentation.
etc…
Actually, ‘ignorant’ and ‘stupid’ mean different things. Being ‘ignorant’ is not an insult. For example, you were ignorant of the distinction, that does not make you stupid.
Because a language like Ocaml has an expressive type system and is very close to equal in performance to Go and has pretty decent compile times. In this sense I believe the Go authors have made poor decisions. See what happens when you ask why rather than just make accusations? You get an answer.
Not from where I stand. The authors claim solving this problem and fitting inside their requirements is an unsolved mystery. If it were a solved mystery, Go would have generics. Can you explain why you think this is a misrepresentation?
You’re telling me that calling Griesemer, Pike and Thompson ignorant is not an insult?
I can understand how calling a budding computer scientist ignorant is not an insult. It’s no biggie, they are expected not to know something.
Calling top computer scientists—all with vast experience in language design—ignorant in precisely the thing they have experience in is most definitely an insult.
You may have niggled a little point about the distinction between ignorance and stupidity, but it is inconsequential to my argument: you make a point of being a PL snob by insulting those who design languages with type systems that aren’t as expressive as you’d like.
You’ve just conveniently pushed away one of the most important features of Go: its wicked fast compiler. Ocaml doesn’t even come close.
They have only made poor decisions with respect to pleasing your sensibilities. That would be a completely reasonable and non-snobby thing to say.
The context of your quote implies that it really isn’t an unsolved mystery. Therefore, you are once again subtly implying that they are stupid (or ignorant, pick-your-favorite-insult).
Even experts in a field are ignorant of things in it. The Go team are not type theorists, as far as I can tell, and none of their previous languages have powerful type systems. So to claim they are possibly ignorant is hardly a stretch.
There have been long threads on the Go mailing list about such topics. They are not ignorant of them. They just don’t agree with your personal preferences. And for that, you claim they must be ignorant or disingenuous.
This is an excellent selection of quotes! I remember having read them too. I fully agree these quotes are snobbish and insulting. It’s difficult to interpret them in any other way.
@burntsushi, your comment relates well to what I feel about this discussion!
@apy, according to you, what would be an example of a programming language including “the ability to make reusable data structures” and which does not suffer too much from the associated costs (language specification becoming too much complex, increased compilation time, code bloat when the compiler implements generics using monomorphization, or slow execution when the compiler implements generics using some kind of type erasure and/or boxing/unboxing)? A lot of people would be really interested by a constructive answer, because this is the crux of the issue. If you have no idea about this, then please stop.
So the easiest one of your criteria to game is ‘compilation time’ because acceptable compilation time is subjective. The language that fits for me is Ocaml. I find Ocaml compilation times quite acceptable. They are longer than Go’s but still better than C++ (IME). Ocaml has a powerful type system and, IMO, the language specification is not too complicated. I learned most of my Ocaml from reading the specification rather than a tutorial.
In terms of executable performance, Ocaml is on par with Go based on the Language Shootout, despite supporting a richer set of data structure abstractions. Of course this benchmark comes with all of the well known disclaimers of benchmarking. And one should note: the Ocaml compiler has not been given serious attention when it comes to optimization, so its performance can be improved.
http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?test=all&lang=go&lang2=ocaml&data=u64q
There are other ways to game the system as well. mlton is often cited as producing extremely performant code at the cost of compilation time. But what SML developers do is develop using a faster compiler, such as SML/NJ, which has quick compilation times, and then build final releases in mlton. Since releases are built on the order of a few times, generally, the cost of mlton is minimal to the overall process. Of course that comes at the cost of a more complicated ecosystem (two compilers) but it’s possible to do something like clang or gcc and adjust the level of optimizations at compile time depending on if one wants faster compilation times or executables.
Thanks, we’re moving toward a constructive discussion :)
About compilation time: Is OCaml using some kind of incremental compilation (recompiling only the parts/modules that have been changed) or does it recompile everything always? And what is the usual build time for the programs you work on?
About language specification: I agree that OCaml authors have found a good balance between language expressiveness and language simplicity. The spec seems quite readable and not too long.
About execution performance: I read the source code of each benchmark in Go and OCaml. The Go version is generally shorter, which is unexpected considering OCaml emphasis on expressiveness. Do you know why?
I also noticed some code duplications that I don’t understand in spectralnorm (eval_A_times_u and eval_At_times_u) and knucleotide (write_frequencies15 and write_frequencies16, write_count15 and write_count16). These are typically the kind of duplications that I don’t expect in a language which supports parametric polymorphism and algebraic data types. Is it for optimization purposes?
This is a weird argument. It’s like saying “Interpreted languages are slow but it’s because we’ve not given serious attention to optimization”. The truth is this is harder to optimize most interpreted languages. The cost of development of a runtime like V8 is very very high. It’s like saying “C++ templates compilation is slow but it’s because we’ve not given serious attention to it”. The truth is this is harder to compile quickly for structural reason. OCaml gives more expressiveness and safety to the programmer, and this is good, but it also complicates things on the compiler-side and there is a cost there that must be taken into account.
I agree that having different compilers for development and building the production binary is an interesting strategy.
What about the strategy used by the compiler(s) to implement generics? Do you know about this? Does the compiler generates one polymorphic version of the code or many specialized versions for each type (monomorphization)? I think that MLton uses the latter strategy.
Ocaml itself is not concerned with how you compile it. I use makefiles which means I only recompile the subtree that depends on the changes. Most other ocaml build tools do this as well, but this is a separate concern of the actual language.
Sorry, no, I haven’t read the code on the language shootout. I use the link more of an indication that one can acheive roughly equivalent performance even with a more expressive type system like Ocaml. I don’t actually think the language shootout is very good for much else, in a large system a lot of these micro benchmarks are drowned out by real-world issues.
So in reality, Go is probably slightly faster than Ocaml in a lot of cases, however when it matters Ocaml let’s you write fast code.
I’m saying something differently though. Compilers like mlton demonstrate you can compile an ML to be highly optimized and efficient. Nothing in the semantics of the language prohibit this. This simply has not been a priority for Ocaml since, for the most part, it’s fast enough. So the work has been done for Ocaml’s twin, it’s just not worth it yet. Which is different than saying that one thinks a problem is solvable if they work hard enough.
The way this works in Ocaml is, in the worst case, you use some extra space to represent your data with a header and the actual value. So, boxing. Again, as a low-bar, one can see that the memory consumption between Go and Ocaml are roughly equivalent in the language shootout. In my experience the memory consumption of an Ocaml program is much smaller than equivalent Java, Python, or Ruby apps. C is of course smaller and I cannot speak to C++. Where possible the compiler can optimize the boxes away, for example if all of the computation happens inside the function, values will be put into registers sometimes. The Ocaml compiler does not do any monomorphic optimizations, AFAIK. Yes, mlton monomorphises everything, which is one reason it’s so expensive.
BTW, do you know how Go implements interfaces btw? I would imagine it requires boxing as a place to put the data + vtable. Is this correct?
At least we have a meaningful conversation :)
Do you know if the value is stored alongside the header or is stored as a pointer to the actual data?
I’m asking because this is a game changer in some cases. Let’s say we want to create an array of 100 (x, y) integer pairs. In Go, with no interface, on a 64 bits machine, this will be stored in 100 x 2 x 4 = 800 contiguous bytes. In Java, for example, what you will get is an array of 100 pointers, pointing to 100 pairs allocated separately on the heap. It creates a lot of indirection and put a lot of pressure on the garbage collector.
How does it work in idiomatic OCaml?
It makes sense because, as far as I know, this is the only way to get incremental compilation.
Yes, this is quite close to what you imagine. A value of type interface is represented in memory as a pair of two words, one pointing to a kind of vtable (an itable), the other pointing to the data. Here is a good explanation by one of Go’s authors: http://research.swtch.com/interfaces.
Please note that you pay the price of this indirection only when you need an interface.
From what I understand, and the details can be found in RWO[1], the representation of a value in Ocaml is just about what you described for an interface in Go. At least two words (although I think integers have some space optimization here), adjacent to each other. And records have some tricks to pack values together.
I’m unsure of the specifics of the array situation. I believe they are boxed, however Ocaml BigArrays are not boxed for some times if possible.
Thanks for the link.
Given what you described, what is the actual runtime cost incurred by generics if the implementation is equivalent to how interfaces are already implemented?
[1] https://realworldocaml.org/v1/en/html/memory-representation-of-values.html
Thanks for the link! It is an excellent explanation of OCaml memory representation.
You are right about the representation of a value in OCaml being similar to the representation of an interface value in Go (even with some significant semantic and operational differences). It follows they should have similar performance characteristics.
I think that using this approach for everything is ok in OCaml considering the goals and the use cases of the language. It simplifies a lot the implementation because the compiler does not need to generate a specialized version of each function for each possible type. It just needs to generate an efficient polymorphic version of the code and it is done.
But this approach would be difficult to reconcile with the goals of Go. Go is positioned as a systems programming language (to program application servers, not operating systems). Using boxing almost everywhere is not an option here. This is the reason why interfaces are not the default mechanism for everything. This is also the reason why generics are a little bit more difficult to implement than in OCaml.
The runtime cost is related to pointer indirections and having to allocate/free memory on the heap for each value. Here is an interesting presentation of Microsoft about this subject in C++: http://view.officeapps.live.com/op/view.aspx?src=http%3a%2f%2fvideo.ch9.ms%2fsessions%2fbuild%2f2014%2f2-661.pptx
Java is well-known for having a problem with this. For illustration, here is an excerpt of what the Disruptor project says about it [1]:
[1] See section 4.1 at http://lmax-exchange.github.io/disruptor/files/Disruptor-1.0.pdf
To conclude, I think that Go will have some form of generics one day. I think it will not be based on some kind of monomorphization because it would increase compilation time a lot, which is one of Go’s major goals. So we’re left with the compiler generating polymorphic code like OCaml. For generic containers, which generally don’t need to know anything about the element type behavior, except its size and sometimes an equality operator, we don’t need interfaces and the performance can stay high (it looks like built-in arrays/slices/maps/chanels work like this according to a quick read of the runtime code). But for other purposes, generics will probably depend on interfaces and have the same performance characteristics than in OCaml. There is no silver bullet :)
Edited: removed a useless note about MLton.
Why? Ocaml is used as a systems programming language as well, boxing has not been an issue. Java is one of the most used server side languages and it boxes everything. I think this statement has zero evidence to back it up.
If I need to do anything generic-like in Go, I have to use some kind of interface, the worst case being
interface{}. Therefore: I already have to drop to interfaces to do generic things, so I why can’t I implement generics as a compile-time construct that producesinterface{}code? I’m not saying you should, I’m saying as a thought experiment these things are semantically equivalent. You only need to drop to a boxed value when you’re doing something generic, and the compiler knows when you’re doing something generic, so it can produce code equivalent to what a human would write, but proven correct.Note: this does not restrict you from writing a container that is specific to your type (which is the current state of Go) but it provides the ability to provide generic data structures at a cost of some pointer indirection. So you’re in no worse a state than today. And for many problems the extra indirection does not matter. See Rule 1.
Yes, as I said Ocaml provides tools to remove the indirection in performance critical places.
BigArraywas explicitly made for this. And record types have some optimizations on this that one can make use of.It obviously depends on how we define systems programming. So I’ll try to be more explicit. Go wants to be able to replace C and C++ in most circumstances. One of the distinctive features of C/C++ is the strong control it gives over memory layout and the use of pointers and references. Go aims for a similar flexibility. This is the reason why boxing cannot be the default.
Zero evidence? I shared a link about the Disruptor library, where this problem is discussed very explicitly. This is even one of the important reason for developing this library in the first place.
I agree. This is exactly what I wrote at the end of my comment. And I think that Go will have generics one day based on something similar, at least in the general case.
At this point in time, C++ and Java generally compete for the same turf. And Java usually wins. Even in the Disruptor quote you made, it’s an off-handed comment and hardly represents a serious roadblock. And let’s be clear, LMAX is doing a ridiculous number of transactions per second, significantly larger than a vast majority of Go developers will experience. So your claim that boxing is a showstopper has no evidence behind it (Java is still massively popular and performant).
Interesting. Any evidence of this?
What is your source for such a claim? You like to ask for evidence, which is legitimate, so I think it’s fair that you hold yourself to the same standard.
I did not write that boxing is a “showstopper”. I wrote that boxing cannot be the default behavior in Go because it has a runtime cost that Go designers are probably not willing to pay when generics/interfaces are not used. Languages like C, C++ and Rust don’t box everything for the same reason. Even Haskell has its SPECIALIZE pragma. I’m just saying that it’s significantly easier to implement generics in a language where everything is boxed.
It depends on which thing you are asking for evidence for. Java and C++ competing for the same turf should be self evident. The turf that Java does not compete for that C++ owns is games, but Go isn’t competing for there anyways so we can disregard it. But in terms of service backends, Java has been shown to be doing well here. Netflix, Amazon, Facebook, Google, basically any financial firm, has some core component written in Java. I take back my claim that “java usually wins”. And I’ll rephrase it: In my experience, Java usually wins. I have never worked in a company that decided to rewrite some component in C++. I have worked at many that have decided to rewrite a component in Java. On top of that, basically all vendor solution in the financial industry is in Java. HealthCare.gov’s core components were in Java. The list goes on. That is not to say C++ is being marginalized, but Java is clearly a powerful contender in the space Go is trying to win.
Did you read the paper you linked to? It states:
LMAX is a betting exchange that, according to Martin Thompson, handles more transactions per day than every financial exchange on the internet.
Given that: it’s clear, even by Rob Pike’s admission, that a significant number of people flocking to Go are coming from the Python and Ruby community, for which their goal is to be able to handle messages counted in the thousands per second for the most part.
And in general: not many companies reach the scale of doing millions of messages per second.
To recap:
I have shown you that Java and Ocaml, languages that box everything by default, can have performance as good as Go’s. We’ve also discussed that the compiler could do exactly what a human does right now when they want generics (convert to/from
interface{}), meaning that things would not be boxed by default. This would likely increase compiler time, but by how much is unclear. It’s also unclear to me what is specifically important about the current compiler times other than that is what the happen to be. Would compilation taking 2x longer be acceptable? If not, why not?So far I have not heard you provide a concrete reason why either boxing or implicit
interface{}conversion is unsuitable for Go.Yes, so what? How is it relevant to the question of why Go does not have generics today and how it can have them tomorrow?
Yes, my friend. This is usually what I do before sharing a link.
On this topic, in a former comment, you wrote:
At some point, if you’re genuinely interested in language design and implementation, you also have to do your own research. The Disruptor paper talks about a proposal to introduce value types to Java (in the paragraph I quoted earlier). Here is the proposal:
http://cr.openjdk.java.net/~jrose/values/values-0.html
Is it enough “evidence” for you that boxing can be a problem? Again, nobody is saying that boxing is a “showstopper” (your word); it’s just a tradeoff with advantages, and drawbacks.
No, for sure. And Google, where Go was designed, is obviously not one of them… Don’t you see how ridiculous this argument is?
No, you have not.
I have provided some reasons that you happily ignored or rejected, because they don’t fit your view of the world or you language design preferences.
I think I will probably follow the advice you gave me in a past comment and stop reading what you write. You are so exaggeratedly argumentative. I reread the thread and it’s quite clear that you have absolutely no interest in understanding why Go does not have generics already, and how they can be added in the future. I think you’re mostly interested in arguing that your tools of choice are superior, and that Go designers and users are wrong.
Discussing with you sounds more like lawyers on opposing sides arguing in court, than engineers on the same team sharing knowledge and looking for solutions.
Language design and implementation are complex issues. They cannot be discussed by dropping anecdotical evidences and jumping from one argument to the other, depending on what best suits your end goal.
There is something irritating and disrespectful in the way you write about adding generics to Go being something obvious, “a solved problem”. If it was so obvious, don’t you think someone would already have submitted a working solution with code and documentation, and convinced the core team to merge it?
I’m curious to know who you are, what you do for a living and what are your achievements in language design? What makes you so sure that you’re right and the whole Go team is wrong?
For the record, my name is Nicolas Grilly. If you ever had the opportunity, one day, to recruit me in your team, please don’t. I would probably hate engineering something with you.
Your statement was:
To which I demonstrated that Java, a language which boxes (almost) everything by default, competes very successfully in the same space as Go. And Disruptor also handles a significant number of transactions per second.
That will help get more performance out of it, sure. But that is a different argument than the one I am making. I am claiming that Java, with boxed values, already has ridiculously good performance given its near ubiquitous position in the world, as such my statement is that your claim that being boxed everywhere is at direct opposition to being a systems language lacks evidence. It would be nice to know what the actual run-time targets are, as well. How can one state that the run-time costs would be too expensive if the actual target doesn’t exist? Perhaps I’m missing it but snooping around the Go forums did not turn up anything for me.
Yes, that is a fair point. But I think my point was communicated poorly. Again, you are saying that because of the domain Go is aiming at, boxing is unacceptable. However, Disruptor does an insane number of tps, so your statement doesn’t hold up to the evidence. My claim that most Go developers won’t experience a comparable tps was really a red herring and I should have left it out.
I provided a link to the language shootout showing Ocaml about equal to Go. So yes, I have. If your statement is actually that I have shown you evidence but you question the quality of it, well that is a matter of perspective and I can’t really argue with that.
From my perspective the following claims have been made:
In response I have:
interface{}and back), providing no extra run-time cost, but clearly at some (unknown) compile-time cost.Given the above, I feel that I have made an effort to understand why Go does not have generics and provided counter evidence to existing claims as to why it doesn’t. IMO, the responses I’ve received have only been authoritarian: “the authors of Go don’t see a solution they like” but without providing any specifics beyond that.
If you have provided a linked which goes into details what the requirements are for the authors to add generics to the language then I’m sorry that I have missed it, please link me again.
I’m sorry you feel that way, but that is a disrespectful and unneeded comment to make. At no point have I insulted you, speculated as to what it would be like to work with you, or made hypothesis about your character. In my opinion this thread has been full of great discussion and healthy disagreement and I’m happy to have been a part of it.
You inspired me to go have another look at Programming Epigrams http://www.cs.yale.edu/homes/perlis-alan/quotes.html
A very related one is…
However the mathematician in me always looks for the exceptions… and finds it.
The idea behind that is if you have the 10 functions for each of 10 data structures, you only have a vocabulary of 10 to operate on any one data structure, and you cannot use the other 90……..
Moral of the story…. store everything as a string….
Just kidding. Sort of.
Personally I don’t like that epigram. I’d replace it with “Understand relational algebra. Use it.”
I think this (modified) version of epigram 1 applies more :)
I guess you are getting at the fact that Go doesn’t have generics or polymorphic functions.
It does have interfaces though and you can create reusable data structures with them.
It also lacks algebraic data types, phantom types, etc.
And interfaces are insufficient to implement many data structures (without losing type safety).
As a beginner in Go that is kind of surprising to me, could you go into a bit of detail how they’re insufficient for type safe implementations?
Consider how you would write a linked list that can hold any type in Go.
I wasn’t sure if you meant a hetrogeneous list or a homogenous one, now I see that it’s impossible to write a homogenous one in Go!
I’ve looked up examples of this non-typesafe programming in Go:
}
ordered_list_test.go
What a disappointment!
Just a guess, you spend most of your time in the web app world?
Nope. Even if I did spend all my time in web apps: What is your point?
These rules are presented out of context. They are part of a longer article, “Notes on Programming in C”, published in 1989, in a section of the article about most programs being unnecessarily complex.
http://www.lysator.liu.se/c/pikestyle.html
Which contains a line I’ve read before and always been completely baffled by:
I completely fail to see how expensive lexical analysis could ever be (or have been) considered a mark of a good compiler. Lexical analysis is a “simple” problem: given an input, there is exactly one correct output; taking a long time to arrive at that result seems like a bad thing to me. Code generation, on the other hand, is a less simple problem (and a much more interesting one if you ask me): for a given input, there are many possible correct outputs; choosing a good one from that (large) space is a tricky problem, and spending some time on doing a good job of it could be seen as the sign of a good compiler.
I’ve always wondered just what the heck Pike was thinking when he wrote that…
Good question. No idea why he wrote that!