| > Please keep in mind that there are differences at scale. What is "easy to work with" for 1 programmer over a month might not be so for 20 programmers over years. > The argument is that simpler is better at scale. Airplanes can move freely in 3 dimensions, but airliners are constrained to fly in particular ways around busy airports and cross country. For one, I just debate the premise the simplicity has anything to do with cardinality of features/concepts. But let's take that argument at face value: then why _not_ assembly if this is the case? Why not a language with the absolute minimum number of concepts? I think if you interrogate this premise you'll find it doesn't hold a lot of water and that Go doesn't really aspire to this goal anyways. I think we have some amount of working memory for being able to intuit programming with a certain number of concepts. There's a valid argument that some languages suffer by breaking that barrier (though I personally think Go underestimates where that barrier is), but it seems incorrect that language designers should be optimizing for a minimal number of features. I think complexity at scale has more to do with features that interact poorly (or cause poor interactions more frequently with a larger number of people). Specifically its about composition. For instance, there's a valid argument to be made that asynchronous exceptions (i.e. the ability to interrupt another thread with an exception) and locks poorly compose. Mutable state is a common example of a feature that's a detriment to composition. But parametric polymorphism, if anything, gives us a much greater ability to compose. It allows us to define functions that work on data arbitrarily parameterized by other types, which makes them conducive to composition. And likewise, we don't suffer ability to reason about composition at scale with parametric types. A parametric function does not gain complexity as more team members are added, more code is written, more deadcode accumulates, etc. Parametricity changes nothing at scale. > In your experience, what kind of "cost" has there been in unsafe casting to use collections? Even in environments like Smalltalk, where all use of collections amounts to "unsafe casting," I've rarely seen situations where a mistake of this type wasn't found trivially. That's an argument for Go to not have types. But Go does have types, and type safety is often espoused as a benefit of Go. If you're going to have types, it makes zero sense to me why you should not have parametric polymorphism, since this is the only way to have things like typed collections without opening yourself up to the possibility of casting errors. Frankly I find it bizarre that people claim that they have found type errors to be trivially fixable, because the scope of where a type error can be introduced is enormous in an untyped language... its literally every location that potentially calls into the code where the error occurs. > Does your frustration come from having to abandon the "assured safety" the type system would give you, or does it come from an experience of the costs? Yes, type safety is an enormous advantage to writing correct code in my opinion. It's one of the best mechanisms a programming language can give you for enforcing invariants about data. The curry-howard correspondence is a huge advantage to writing correct code. Every place a type checker isn't being used to delimit acceptable data is a potential source of a huge number of bugs. It's also a frustration because casting introduces conversation and type checking boilerplate that a type checker could ultimately take care of for you. |
Okay, then you can throw away the rest of your post and stop right here. The overwhelming historical evidence is that assembly doesn't scale.
> That's an argument for Go to not have types.
Sorry, that doesn't follow. Is the logic here just because I mention Smalltalk, that I'm advocating late binding and the only type being Object for Go? Sorry, but that doesn't follow. The argument is that Go doesn't need a more complicated type system to avoid problems with heterogeneous collections -- because practice shows that even a simpler one can suffice.
> Frankly I find it bizarre that people claim that they have found type errors to be trivially fixable, because the scope of where a type error can be introduced is enormous in an untyped language...
Sounds like you're invoking freshman level false "common knowledge." Have you ever worked in an "untyped" language in a real project? What if a project simply used runtime asserts? Then a type error in a heterogeneous collection would be caught in unit testing. If it got out to production, it could be easily caught and logged. In 15 years of Smalltalk industry work I never encountered the kind of heterogeneous collection type error you're referring to in production. The closest thing I can recall involved the heterogeneous typed reuse of a local variable. (Which is simply bad coding style in Smalltalk.) In Go, you have a type system that provides much more feedback at compile time, and workable mechanisms for detecting the problem at runtime. So at least in this one instance (heterogeneous collections) there is arguably almost no practical benefit to parametric polymorphism.
(P.S. Technically speaking, Smalltalk is strongly typed with message passing semantics for methods implemented through late binding. It's not "untyped.")