5 ms·
This is probably one of the most discussed things on the Go mailing list (golang-nuts, if anyone is interested). Unlike some other features (like exceptions, ag
by objclxt 14y ago
This is probably one of the most discussed things on the Go mailing list (golang-nuts, if anyone is interested). Unlike some other features (like exceptions, again something oft discussed) there seems to be some openness towards it, but also a desire to not introduce anything that would cause increased complexity without a similar or greater increase in value.
- lbarrow 14y agoGo's approach to exception handling has a greater impact on the way Go programs are written than the lack of generics. That said, I'm fine with the exception handling because it's obviously a conscious decision by the language designers, and it fits in with the spirit of the language. The lack of generics doesn't feel like that. It strikes me more as an oversight than anything else. This is especially true because some builtins (i.e. make) are generic functions -- they're just special, and you aren't allowed to make your own.
- azth 14y agoThere are some other oversights too: lack of immutability/const qualifier; nil pointers in the language; `defer` working at the function, rather than the scope level, etc. Even for error handling, why not use a sum/option type as several other languages use?
- millerm 14y agoRegarding nil references, I now always think of this Sir Charles Antony Hoare quote when the topic arises: "I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. In recent years, a number of program analysers like PREfix and PREfast in Microsoft have been used to check references, and give warnings if there is a risk they may be non-null. More recent programming languages like Spec# have introduced declarations for non-null references. This is the solution, which I rejected in 1965."
- azth 14y agoSo he's saying he rejected declarations that allow you to declare either nullable or non-nullable types? Kotlin and Rust seem to have an interesting approach. In Kotlin, you have to explicitly declare nullable types, and Rust does not allow references/pointers to be null in the first place if I am not mistaken. I have just recently started learning more about Scala, and although it allows nulls to be passed, they are not idiomatic, and I am guessing it would not be too hard to have an automatic style checker that catches uses of null (at least those that do not interface to Java libraries).
- masklinn 14y agoNo, he's saying he now rejects references being nullable (as the default state of all reference types). A concept of "nothing here" is sometimes necessary so he probably doesn't reject explicit nullability annotations (option types as in Haskell, MLs or Rust for instance; this is not exactly an original approach either).
- bad_user 14y agoScala's approach is sane because you can't dissalow nulls when you're working with libraries that work with null values. On the other hand Scala gives you the tools to deal with nulls very efficiently. You can easily lift nullable values to Options, and because Option is a monadic type, it can be used in for-comprehensions and is very composable. Languages like Kotlin are missing the point.
- eta_carinae 14y ago> Languages like Kotlin are missing the point. That's a bit harsh. JetBrains and the developers of the compiler are certainly aware of the Maybe/Option approach, they chose not to use it. Their approach is not as composable as Haskell's but much more practical and more readable in my opinion. If anything, the fact that Option is still used so rarely in Scala is an indication that maybe, that experiment has failed.
- 14y ago
- snprbob86 14y agoClojure seems to be proof that C++'s const qualifier does not constitute a reasonable approach to immutability.
- azth 14y agoBut I didn't mention C++ :) (D and Rust have const too) To be honest, I haven't looked much at Clojure. Do their containers/data structures use the immutable versions by default (kind of similar to what Scala does?) The Rust programming language seems to have something going in that area. Immutability is the default, you have to explicitly declare mutable data members. Similar with methods, you have the option of declaring `self` to be mutable (which seems cleaner than C++'s approach).
- andrewflnr 14y agoRe Clojure, yes, you have to do extra work to get a mutable data structure, and then use ugly "!" functions to mutate it.
- snprbob86 14y agoClojure only provides immutable data structures. Java, however, provides many mutable data structures which are readily available to Clojure. Clojure also provides mutable reference types that are tuned for particular concurrency patterns. Atoms for synchronous compare-and-swap, agents for asynchronous queues, etc. There are no annotations to specify immutability, you have to trust whoever implemented the class you're using to provide the guarantees that are in their documentation. To some extent, that makes this a static vs dynamic typing discussion, but my point is that type annotations are realistically not necessary if you chose immutability as the default and provide a limited set of well known mutation operations. These operations are generally annotated with a "@", "!", or "." for "dereference current value", "side effectful", and "java interop" respectively.
- jesstaa 14y agoconst/immutability at the variable declaration introduces a whole lot of annoyances, see const in c/c++. If you want immutability do it at the type. For a language that uses multiple return values to indicate error nilable pointers are a requirement. With no constructors a non-nillable pointers would become a strange rarely used feature. 'defer' is currently very useful in loops, open a bunch of files in a loop and schedule them all to be closed at the end of the function. If defer was block scoped this would be impossible. The error handling with sum/option types is an idea that usually comes from people that haven't used Go or at least haven't thought about how it would work at all. It doesn't work. Languages that use sum/option types for errors are universally functional languages that don't mutate function parameters. The io.Reader interface is a good example of this problem. Read(p []byte) (n int, err error) You could make an option type of 'n' and 'err' but since the caller owns 'p' you can't prevent them from using it without checking for the error. It's non-trivial to transfer features between languages, they all interact with each other and have dependencies on each other.
- deleted 14y ago[deleted]
- Peaker 14y agoOutput parameters are indeed a safety problem not solved by sum types. However, sum types would still give extra safety in most cases. Also, it is possible to differentiate a type of allocation and a type of a usable buffer, such that "io.Reader" could take an allocation as an argument and return a sum type of an error and a usable buffer. The allocation should be an opaque type not usable as a buffer unless io.Reader converts it to such.
- jesstaa 14y agoThere are all kinds of additional complexity you could add to the type system to get additional safety. Unique pointers and linear typing are a few options, this is the route that Rust is going. But with complex type systems comes a lot of pain and work arounds to get around the types when you need to. Is the benefit of the additional safety worth the complexity?
- mseepgood 14y ago> There are some other oversights too: lack of immutability/const qualifier Not oversights but deliberate decisions. http://commandcenter.blogspot.de/2012/06/less-is-exponentially-more.html http://commandcenter.blogspot.de/2012/06/less-is-exponential... - constants are just numbers - no const or other type annotations Type System Tyranny - Clunky typing: - Makes programming harder (think of C's const: well-intentioned but awkward in practice) http://html5tv.rot13.org/goog-go.html http://html5tv.rot13.org/goog-go.html
- masklinn 14y agoAlso goroutines sharing memory.
- durin42 14y agoIt's not an oversight. They've said (r and rsc) that they want to wait and make sure they get generics Right in the context of the rest of the language, and make it an easy feature to use in the presence of everything else (should it ever be added.) I'll admit, I've wished for generics occasionally myself, but it's been remarkably rare in the end.
- masklinn 14y ago> They've said (r and rsc) that they want to wait and make sure they get generics Right in the context of the rest of the language Yet they still blessed a few builtin collections with generics without waiting to "get generics Right"
- burntsushi 14y agoWhat's your point? It's much simpler to bless a few builtins than implement an entire generics system (with respect to the rest of the language).
- eta_carinae 14y ago> They've said (r and rsc) that they want to wait and make sure they get generics Right in the context of the rest of the language In this case, wouldn't it have been better to ship 1.0 with generics? Retrofitting generics in a language already released with an existing code base sure doesn't seem like the best way to make sure the feature is "done right".
- damian2000 14y agoIn C# generics were introduced with version 2.0 (around 4 years after C# 1.0). It is now a language feature I couldn't live without.
- pjmlp 14y agoThey were already half-way done by .NET 1.0 release, Microsoft decided not to delay the release because of generics. http://blogs.msdn.com/b/dsyme/archive/2011/03/15/net-c-generics-history-some-photos-from-feb-1999.aspx http://blogs.msdn.com/b/dsyme/archive/2011/03/15/net-c-gener...