As for why Go isn't SML, just look at the original team. They had a background in languages like C (Ken Thompson , Oberon and Modula (Robert Griesemer) and Aleph, Newsqueak, and Limbo (Rob Pike). Nobody on the core Go team have ever been fans of functional languages or of complex type systems.
It's like that one year that I got myself addicted to Minecraft.
It could also use some newer things like better support for unicode strings.
[0]: http://sigbovik.org/2019/proceedings.pdf
[1]: Page 170, Also here: https://github.com/solb/sigbovik/blob/master/papers/SIGBOVIK...
Especially cruel is the "andalso" in the closing sentence.
https://github.com/aliceml/aliceml-alice
and make sure you have all the dependencies installed first, it does build on linux and its fun to play with.
I am currently working on a AliceML derived language and if there is any interest I'll post a note on HN - once its a bit futher down the line.
I've used Go channels plenty of times without any explicit mutexes, so I'm not sure what you're talking about here.
I'd add that these aren't just theoretical (EDIT: I forgot that his article linked to this paper).
https://songlh.github.io/paper/go-study.pdf
Go doesn't actually implement CSP correctly. That would require some changes. This provides a high-level overview.
https://stackoverflow.com/questions/32651557/golang-main-dif...
Threading is hard and gets a lot harder when you introduce pointers or mutable data. This is even harder when your type system is terrible. I suspect that Go trying to solve this would result in a language that looked a lot like Rust with a Garbage Collector.
You aren't doing your argument any favors when you're so hyperbolic. Go channels are manifestly not "broken."
> I suspect that Go trying to solve this would result in a language that looked a lot like Rust with a Garbage Collector.
And yet you honestly can't understand why the designers of Go didn't go down that path? Rust is significantly more complex than Go and much harder to learn.
Bottom line for me is that if you're going to be snotty about something, then at least be correct. Or better yet, don't be snotty in the first place.
Which of those features have they said the don't want?
https://tour.golang.org/concurrency/1
https://saityi.github.io/sml-tour/tour/03-01-spawn.html
There are differences, but once you get to that point in either tour, the differences shouldn't make it hard to read; if it is hard to read or understand, that would be welcome feedback, as I have failed in my attempt to present Standard ML well. :)
(I originally posted this as a 'Show HN', hoping for feedback, so it is totally welcome.)
I'm not sure I understand why this is true for Go rather than a statically typed FP language. If anything, I'd consider languages like Haskell or ML to be better at this.
- The obvious case is handling `nil`. In Haskell, you'd treat this as `Maybe a`, and it's obvious that you're not handling the nil case since the pattern match is incomplete. In Go, you get a nil pointer exception at runtime. You could check for the nil case for every pointer, but that's too onerous, so now you're left with relying on the programmer on checking
- Go doesn't have exceptions, which removes some of the hiding of bad code (see https://devblogs.microsoft.com/oldnewthing/20050114-00/?p=36...), but you can still accidentally use a result when an error is return (in fact, you have to return something!). In Haskell, you're forced to pattern match on an `Either`, which again exposes bad through an incomplete pattern match.
I don't think these are arguments for FP per se, but I do think that statically typed FP languages (and the languages they inspire) are much better about removing footguns and making bad code hard to write, simply because the typechecker is so restrictive. As a more general principle, instead of making bad code screamingly obvious, make it impossible to write!
Now, you mention later in the thread that you've already used Haskell before, so you're probably aware of all this and I may misinterpreted what you meant. Did you mean a different form of bad code?
I spent a long time learning Haskell and have written enough Clojure especially to safely call myself an expert in it. I obsess over languages (not proud of that btw). FP is hard. It's too hard for most programmers. A lot of people avoid saying this but it's true. It's hard in a way that you can't fix with experience.
That's why the tooling for it sucks. Suppose you want to make an IDE or even an API for your product. Do you want a lot of people to use it? Then you use ${BLUB}. Heavily abstract stuff dies. Look at Tensorflow vs. Pytorch. Tensorflow 1.0 had this wonderful functional, declarative, immutable way of writing neural networks, but people protested because they couldn't mutate variables in a for loop and have it automagically autodifferentiate. Abstraction kills network effects.
> every new language except Go has incorporated significant functional features
None of them come close to the semantics of FP (except Scala, but its negative adoption rate kind of proves my point). They all allow side effects which breaks the first rule.
You can say they stole some of the convenient syntactic sugar from FP, like pattern matching and lambdas (e.g., Kotlin and Rust). Great. So what advantage do FP langs have now? Making it hard to do I/O? Category theory? Having unmaintained compilers?
In any case, let's look at those haskell "hard parts" and contrast them.
Haskell treats everything as immutable. SML is NOT always immutable. It simply adds some (very sane) constraints on where mutation can occur which makes reasoning about mutation easier.
Haskell forbids side effects. This is an illusion of course (you'll find high-performance libraries often use the unsafe IO stuff). SML embraces side effects though general practice is to restrict them to specific modules to make the program easier to reason about (a good practice in pretty much all languages). You can definitely write imperative pieces of code if it improves performance.
Haskell is lazily evaluated. This can be a performance boon for some things, but is a bane to find and fixing performance bottlenecks. SML is eagerly evaluated like most other languages.
Haskell is crazy for typeclasses. They use them everywhere, but they often complicate actually using things. SML does not have type classes, but SucessorML (the next version) is looking at adding module typeclasses instead. These will have most of the same features, but because they are in the module instead, it should put a big limit on their abuse and make their use easier to track.
SML's big "ivory tower" ideas are: powerful type system, pattern matching, option types everywhere, first-class functions, and modules (essentially as a replacement for classes though that is not entirely true).
SML really is the whole package. The best parts of functional programming combined with the best parts of mainstream languages (restricted to the "good" subset) all tied up in a language definition that manages to reduce the amount of syntax compared to something like Java or Go while increasing the amount of power while at the same time not turning into an unreadable mess (it's pretty hard to write unreadable SML code).
The other thing is whole-program optimization vs method-at-a-time. A lot of SML devs use New Jersey for fast compiles when developing and MLton when deploying. You can get rid of a ton of stuff in functional languages once you do a whole program compile, but that will always take more time. MLton could really use a second, faster compiler, but I'm just appreciative of all their effort to make the current compiler output fast code.
To elaborate, CML is better than golang's channels and isn't broken (requiring mutexes over channels to avoid breaking qualifies as broken). SML syntax is simpler to learn, but still offers much more powerful abstractions with pattern matching. SML uses options instead of null pointer exceptions. Hindley-Milner types are clearly superior to Golang's type system (especially things like empty interface). SML has had generics for almost 25 years now while go languishes. SML has immutable data structures and they are the default for almost everything. Golang has implicit types, but SML's implicit types are much better -- especially structurally-typed records. SML's modules are amazing and simply have no comparison in go. Finally, SuccessorML is doing work toward adding a few new features to the language (for example, module type classes), but the language has an actual specification that anyone can implement (and many have) rather than the implementation effectively being the spec.