5 ms·
Erlang is well-researched, pragmatical language (read the Armstrong Thesis at last) this is why it is "great". User-level runtime, which is trying to do kernel'
by dschiptsov 11y ago
Erlang is well-researched, pragmatical language (read the Armstrong Thesis at last) this is why it is "great". User-level runtime, which is trying to do kernel's job is a problem, but relying on message-passing and being mostly-functional it, at least, have no threading/locking problems - so it scales. Nothing much to talk about.
Go is also well-researched language with emphasis on keeping it simple and being good-enough and doing it right way (utf8 vs. other encodings) - a philosophy from Plan 9. Go has in it a lot of fine ideas, attention to details and good-enough minimalism - the basis for success. It is also pragmatic - that is why it is imperative and "simply" static-typed.
Criticism about lack of generics or is not essential, especially considering that generics in a static typed language is an awkward mess. Complexity of its user-space runtime is a problem, of course, but runtime is hard, especially when it is not mostly-functional.
Go is in some sense "back to the basics/essentials" approach, not just in programming but also in running the code, and even this is enough to be successful.
BTW, its syntactic clumsiness and shortcomings (hipsters are blogging about) came from being statically typed, just admit it. On the other side, being C-like and already having C-to-Go translators opens up the road to static-analyzing and other tools.
Go is the product of old-school (Bell labs) minds (like Smalltalk or Lisps) not of bunch of punks.)
- arthurcolle 11y agoJoe Armstrong's thesis, for the interested: http://www.erlang.org/download/armstrong_thesis_2003.pdf http://www.erlang.org/download/armstrong_thesis_2003.pdf
- biokoda 11y ago> User-level runtime, which is trying to do kernel's job is a problem, but being mostly-functional it, at least, have no threading/locking problems - so it scales. Nothing much to talk about. Spoken as someone who has never really used it. Dismissing it as nothing much to talk about is ridiculous.
- dschiptsov 11y agoErlang is "great". There is nothing much to talk about.
- adwn 11y ago> Criticism about lack of generics or is not essential, especially considering that generics in a static typed language is an awkward mess. This is very wrong. Sure, C++ templates are a mess, but generics in a language with a well-designed type system, like Haskell or Rust, are incredibly useful and very elegant, especially in combination with type classes/traits.
- dschiptsov 11y agoHaskell is rather an exception. Looking at generics in Java is more telling.)
- rbehrends 11y agoA common theme is that only languages that had generics retrofitted into them have awkward implementations (because your design space is now constrained), while those that were designed to have them ab initio typically work fine. I don't really want to belabor the point of Go and generics; it's one of the many simplicity vs. expressiveness design choices that language designers have to make. But the claim that parametric polymorphism in a statically typed language is (presumably inherently) an awkward mess is a peculiar one, given that there are so many successful examples.
- masklinn 11y agoJava is a much bigger exception than Haskell, a heavily runtime-checked language with significant established codebases in which generics were retrofit with the foremost goal to minimise their backwards-compatibility impact. Witness C#, a very similar language whose team decided they had a low enough userbase yet that they could afford to break BC and introduce separate reified generic collections[0]. And just about every other language (Haskell very much included) was designed with generics from the start. Haskell is not an exception, Java is. [0] the C# team knew all along the language would have generics, but generics were not ready for 1.0 so they were pushed back to 2.0
- useerup 11y agoA few corrections: The foremost goal when retrofitting generics into Java may have been backwards compatibility, but the requirement that drove the designers to type erasure and the clunky implementation was migration compatibility. C# had generics retrofitted and kept perfect backwards compatibility. You can still run C# 1.0 programs on a modern 4.0 runtime. That is backwards compatibility, and it would have been quite possible to fit Java generics the same way. Migration compatibility is a (in hindsight) rather absurd requirement where old (non generic-aware) code should be able to call new (generic-aware) code where you as the integrator have control over the source code of neither the "old" nor the "new" code. In practice this would only happen when you use an old library that has taken direct dependencies on external (to the library) non-generic classes (i.e. not interfaces), and where you will not accept that the old code keeps calling the old classes. C# retained the old collection classes, implemented new generics-aware collection classes that still supported the old interfaces (with proper type checking and -casting). This meant that old code could still be passed references to new generic collections and work as expected. The only constraint in C# is that is "old" code has taken a strong dependency on an old non-generic class you cannot pass a new generic class to that code.
- Gonzih 11y agoI'm sorry, but if go would be product of lisp minded people it would be simple language with ability to extend the language on the fly. Reality is in go there is no way to even introduce some nice contract on top of error return and if statements without external preprocessor.
- dschiptsov 11y agoYeah, Bell Labs never been a Lisp shop, but they developed their own philosophy and make it walk with the Plan 9 project.
- XorNot 11y agoGo's error handling leaves something to be desired. I find myself reinventing exceptions a lot by just passing errors up through generic "error" return types. It feels like it would be a lot cleaner to add syntax support for exceptions and call it a day.
- alienasa 11y agoThere is support for fully "exceptional" behavior. It's called "panic". The Go language designers explicitly didn't include exceptions because "coupling exceptions to a control structure, as in the try-catch-finally idiom, results in convoluted code. It also tends to encourage programmers to label too many ordinary errors, such as failing to open a file, as exceptional" [1]. I agree with them. While handling errors everywhere is a little painful to write, it enforces better practices by making you acknowledge that things could fail and ignore, handle, or pass the buck. [1] https://golang.org/doc/faq https://golang.org/doc/faq
- codygman 11y ago> I agree with them. While handling errors everywhere is a little painful to write, it enforces better practices by making you acknowledge that things could fail and ignore, handle, or pass the buck. There are better ways of accomplishing the same thing though, one way is the Either monad in Haskell. Here's an example I post sometimes comparing error handling in Go to Haskell's either monad: func failureExample()(*http.Response) { // 1st get, do nothing if success else print exception and exit response, err := http.Get("http://httpbin.org/status/200") if err != nil { fmt.Printf("%s", err) os.Exit(1) } else { defer response.Body.Close() } // 2nd get, do nothing if success else print exception and exit response2, err := http.Get("http://httpbin.org/status/200") if err != nil { fmt.Printf("%s", err) os.Exit(1) } else { defer response2.Body.Close() } // 3rd get, do nothing if success else print exception and exit response3, err := http.Get("http://httpbin.org/status/200") if err != nil { fmt.Printf("%s", err) os.Exit(1) } else { defer response3.Body.Close() } // 4th get, return response if success else print exception and exit response4, err := http.Get("http://httpbin.org/status/404") if err != nil { fmt.Printf("%s", err) os.Exit(1) } else { defer response4.Body.Close() } return response4 } func main() { fmt.Println("A failure.") failure := failureExample(); fmt.Println(failure); } The equivalent Haskell code: failureExample :: IO (Either SomeException (Response LBS.ByteString)) failureExample = try $ do get "http://www.httpbin.org/status/200" get "http://www.httpbin.org/status/200" get "http://www.httpbin.org/status/200" get "http://www.httpbin.org/status/404" main = failureExample >>= \case Right r -> putStrLn $ "The successful pages status was (spoiler: it's 200!): " ++ show (r ^. responseStatus) Left e -> putStrLn ("error: " ++ show e)
- aikah 11y ago> Go is also well-researched language Concurrency in Go certainly is, the rest is not, definitely. > its syntactic clumsiness and shortcomings (hipsters are blogging about) came from being statically typed, just admit it That's the kind of dismissive and arrogant attitude I often hear from gophers. Doesn't make me want to be part of that community. Have a look at the Cyclone language. It has generics,tagged unions and pattern matching AND it is statically typed. https://cyclone.thelanguage.org/wiki/User%20Manual/ https://cyclone.thelanguage.org/wiki/User%20Manual/ Saying that statically typed languages cannot be expressive is pure FUD. Go designers just didn't strike the right balance between features and minimalism, because they didn't care. Without its concurrency model, Go is not much.
- dschiptsov 11y ago> Saying that statically typed languages cannot be expressive is pure FUD. Could you, please, show us an example from the rosettacode.org website? Generic Quicksort, perhaps?
- rubiquity 11y agoTake a look at OCaml, or any ML variant language (aside from Rust, which is more C++ than ML in my opinion anyway) for that matter, for a static typed language with a good implementation of generic types.