5 ms·
> Go began with Robert Griesemer, Rob Pike, and Ken Thompson. “What should a modern programming language look like” (the story goes as they were waiting for som
by AdieuToLogic 11y ago
> Go began with Robert Griesemer, Rob Pike, and Ken Thompson. “What should a modern programming language look like” (the story goes as they were waiting for some C++ to compile).
Cute. Nice to keep a dig[1] going. Since that horse has been kicked quite a few times over the years, how about those in the Go community address these language criticisms:
http://yager.io/programming/go.html http://yager.io/programming/go.html
For specific examples from the aforementioned link:
The "correct" way to build generic data structures
in Go is to cast things to the top type and then
put them in the data structure. This is how Java
used to work, circa 2004.
And:
Go has the null pointer (nil). I consider it a
shame whenever a new language, tabula rasa,
chooses to re-implement this unnecessary
bug-inducing feature.
Of which the latter has been regretted by its inventor[2] for years.
1 - "[C++] certainly has its good points. But by and large I think it's a bad language." (source: https://en.wikiquote.org/wiki/Ken_Thompson https://en.wikiquote.org/wiki/Ken_Thompson)
2 - http://www.wisdomandwonder.com/link/2015/tony-hoare-sorry-for-inventing-the-null-pointer http://www.wisdomandwonder.com/link/2015/tony-hoare-sorry-fo...
- pcwalton 11y agoHere, I'll address one of them: "It is an extremely common occurrence for a programmer to accidentally forget to account for the possibility that a pointer may be null, potentially leading to (at best) crashes and (at worst) exploitable vulnerabilities." Null pointers won't result in exploitable vulnerabilities in Go (not counting straightforward DoS-by-causing-the-program-to-panic). They might, in very rare cases, result in something exploitable in C or C++, because dereference of null is undefined behavior and the compiler is free to optimize accordingly. But in Golang the language semantics require the runtime to panic on nil dereference, so that won't result in something like RCE as it technically could in C or C++ (but isn't likely to).
- AdieuToLogic 11y ago> But in Golang the language semantics require the runtime to panic on nil dereference, so that won't result in something like RCE as it technically could in C or C++ (but isn't likely to). While you thoughtfully address the concerns Mr. Yager presents regarding the potential result of using a null pointer in Go, IMHO the more relevant fact is that Mr. Hoare identified in his own words a mistake he made _fifty years ago_ (1965) by introducing "null." The fact that Mr. Gerrand stated in the submitted article: “What should a modern programming language look like” Begs the questions: Why is this mistake oft addressed in _other_ languages repeated in Go? What are the benefits of _intentionally_ introducing this boundary condition into the language? Put bluntly, there is no benefit to dragging 0x0 forward in "a modern programming language." The lack of an answer to a function/method call is trivially encoded with some form of an option[1] type. 1 - https://en.wikipedia.org/wiki/Option_type https://en.wikipedia.org/wiki/Option_type
- zimbatm 11y agonil dereference is only really critical if it can result in security issues like in C and C++. After that there are a lot of class of errors that are possible even in stronger types systems like in Haskell, nil dereference is only one of them. The question ultimately is what is the shortest path to developing a functioning and correct program ? Compilers can be very smart and help you catch a lot of errors but they can also introduce friction if they become too slow. Everyone has different opinions about the "best" because we have different ways of getting to the end-result. Programming is a discovery process and some people prefer to think a lot upfront, some like to experiment and probably a different mix of both for every one of us. All this to say that nil in Go is not an absolute mistake. It's just a trade-off like everything else. Since I took Haskell as an example, it's also much much slower to compile.
- jerf 11y agoNULL's ability to create security errors in C/C++ is a relatively recent practical concern. (The theory that permits them goes back a long ways, but only recently have the optimizing compilers gone so crazy with unspecified behaviors.) Our concerns with NULL being a bad idea go back farther than that.
- catnaroek 11y agoIn my experience, unless you enable all the crazy type system extensions (which isn't a terribly good idea IMO), GHC doesn't really spend that much time typechecking programs. Most of the time is spent on optimizations, which are (0) possible thanks to purity [hooray!], (1) necessary to overcome the limitations of laziness [dangit!]. In any case, Haskell supports exploratory programming just fine. It's true that Haskell's definition of "exploring" (refine your design until you can convice GHCi and QuickCheck that it makes sense) is somewhat idiosyncratic from a Lisper or Smalltalker's point of view (refine your design until you can convince yourself that it makes sense), but that doesn't make it any less legitimate. It's still experimenting, except now you have a tool to validate the degree to which the experiment has been a success. It's experimental science, not experimental art. --- On the specific topic of nils, I think it's fair to say they're an absolute mistake in a statically typed language first released as late as in 2007. Standard ML and OCaml, both much older languages, have parametric polymorphism, algebraic data types, freedom from nils, and fast compilers: Poly/ML and OCaml's bytecode compiler, respectively. In addition, both Standad ML and OCaml have unrestricted imperative facilities, so freedom from nils is perfectly possible in an imperative language. --- Regarding the classes of errors that are still possible in type systems like Haskell's, I have found only one that really matters, and where the usual workarounds (e.g., phantom types) don't help. Haskell, being a mathematically-inspired language, favors programming in terms of "timeless" entities whose existence is unaffected by the number of times you use them. While appropriate for manipulating pure data (numbers, strings, lists, trees, etc.), it's awkward for manipulating ephemeral computational resources, such as file descriptors or open sessions. A language that fares better in this regard is Rust. Rust has parametric polymorphism, algebraic data types, freedom from nils (are we seeing a common theme?) and type classes, but gives up on interactive programming in exchange for precise control over data structure representation and resource management. Rust's type system design understands very well the ephemeral nature of objects: When a non-`Copy` object is passed around elsewhere, it's truly gone from the current lexical context. --- Now, I don't want to give the impression that I think verification is the be all and end all of computer programming. There's plenty of room for languages that let you develop "fast and loose" solutions, as opposed to follow some principled philosophy. (Ruby comes to mind.) However, Go's very own marketing suggests that this isn't what they're trying to achieve. They do want a language that enforces a programming discipline. They just happen to have designed a language whose discipline doesn't provide enough benefits to justify the freedom restriction.
- catnaroek 11y agoAttempting to dereference a null pointers may not violate memory safety, but it can do much worse things, like crash programs in the middle of unfinished transactions. If the atomicity guarantees are provided by someone else, then it's not much of a problem - it's their responsibility to clean up. However, if you're the one implementing the atomicity guarantees, you're pretty much screwed. And this is just an example.
- mseepgood 11y ago> This is how Java used to work, circa 2004. This part of Java actually wasn't so bad. I would argue that Java didn't get better with the addition of generics in 1.5.
- AdieuToLogic 11y agoI believe Mr. Yager's point was not so much about Java generics as it was that determining the type of a container's contents was impossible without manual type checking. I am not he so take that with a grain of salt. What makes opaque containers a particular form of debug hell is when working in a non-trivial code base. Lobotomizing the one assistant which never tires (the compiler) puts the onus on people to "just know" what is in there (for whatever definition of "there" is at the moment). Call me cynical, but people are horrible at keeping these kinds of concerns straight.
- mseepgood 11y agoThe built-in types slice and map are type-safe and cover 90% of container needs. If you want to use a non-builtin container such as container/heap and you find yourself casting too often, write one or two little wrapper functions for your use case, which encapsulate your casts. This is also an opportunity to make the wrapper represent the problem domain better.
- eloff 11y agoThis is some serious bike-shedding. Well there are some rare cases where you really need generic data structures, is not hugely annoying to use go generate and a template implementation. That being said, I'd still like to see generics in Go, providing the drawbacks are limited. The other criticism about null pointers is just ridiculous. If null pointers make in into a list of your top ten pain points while developing software in a team, I'm going to call you out for not being honest to yourself. Null pointers have their benefits and drawbacks, but it's so far down the list of practical concerns that it shouldn't even feature in your decision on what language to use.
- AdieuToLogic 11y ago> This is some serious bike-shedding. Does identfying fundamental deficiencies in a language now qualify as "bike shedding?" > Well there are some rare cases where you really need generic data structures, is not hugely annoying to use go generate and a template implementation. I don't understand how you draw this conclusion, as homogeneous collections are one of the most used forms of collections I've seen for many years. For an example of the precise issue losing the type within a container causes, see this example[1] of where a Go developer was struggling with an issue that is non-existent when types are retained. As for using an external tool to do "template generation", XDoclet[2] did that well over a decade ago. It was a PiTA then and now. > If null pointers make in into a list of your top ten pain points while developing software in a team, I'm going to call you out for not being honest to yourself. "Those who do not learn from history are doomed to repeat it" (source: http://thinkexist.com/quotation/those_who_do_not_learn_from_history_are_doomed_to/170710.html http://thinkexist.com/quotation/those_who_do_not_learn_from_...) They certainly do, as the number of people involved in working in a system increases, the assumptions regarding subsystem interaction vary. By having the ability to create a "software singularity" at any point by producing a null, everything will have to be _manually_ checked at the invocation site. Just like what had to be done in C for decades. Can you guarantee that everyone involved in the lifetime of a project will always use the same approach, have the same assumptions about how the behavioural contracts are fulfilled, and will _always_ check everything that needs to be ensured "non-null" at the call sites? With option types[3], or even better with disjoint union types[4] where the type contains either an error _or_ the desired result, this simply isn't a concern. The developer _must_ deal with the possibility of maybe not getting something back from a call (or of getting an error _instead of_ the desired result). 1- http://stackoverflow.com/questions/20087233/golang-get-the-value-from-list-element http://stackoverflow.com/questions/20087233/golang-get-the-v... 2 - http://xdoclet.sourceforge.net/xdoclet/index.html http://xdoclet.sourceforge.net/xdoclet/index.html 3 - https://en.wikipedia.org/wiki/Option_type https://en.wikipedia.org/wiki/Option_type 4 - https://en.wikipedia.org/wiki/Disjoint_union https://en.wikipedia.org/wiki/Disjoint_union
- rsc 11y agoI don't believe anyone from the Go team has said that using interface{} in containers is "the "correct" way to build generic data structures". It is merely one of the ways available today. (The other is to define algorithms in terms of operations, like sort.Sort does with sort.Interface.) We're not saying either of those are "correct" in the sense of optimal, but they're what we have now. Robert addressed generics in his talk (summary at https://sourcegraph.com/blog/live/gophercon2015/123645585015; https://sourcegraph.com/blog/live/gophercon2015/123645585015... I believe the video will be available in two weeks). Quoting the sourcegraph summary: > Generics is the single biggest language feature absent in Go. It’s often missed by newcomers to Go. But it’s more of a type-system mechanism. It’s unclear if it’s an essential language feature. > Generics are incredibly complex in both semantics and implementation. There are considerable trade-offs to consider, such as do you want a larger binary vs. slower binary vs. larger source code. > It’s also very non-orthogonal. It interacts with and complicates a lot of other language features. > They have tried and implemented prototypes of generics in Go, but they haven’t found a good solution, so they’ve decided to hold off and keep thinking about it for the time being. Robert also made the point that generics are very complex, much more so than most people realize. See also https://news.ycombinator.com/item?id=9622417 https://news.ycombinator.com/item?id=9622417.