This is very true. Go is a pleasure to write. In fact, it's such a pleasure then when you hit something that wasn't really well designed it's horrid.
This is very true. Go is a pleasure to write. In fact, it's such a pleasure then when you hit something that wasn't really well designed it's horrid.
I wish Go stays on that path for a long time. And it never gets TOO big, which makes for awful communities.
In particular, OCaml has an awesome module system and a great take on structural sub-typing combined with proper type inference and sane parametric polymorphism.
Having actual algebraic data types is night and day to Go's more limited structs. OCaml also has a good object system which people don't use too often but can come on very handy.
While I agree that the former is a nice language, it doesn't compare favorably to Go as a development suite: the standard library is terribly designed, and the package management is rather poor compared to Go's (which is about as great as it gets).
Now there is "OCaml Batteries Included" which is supposed to mitigate that, but it appeared after I stopped actively using OCaml so I can't comment on that (incidentally, I dislike many of their choices).
Also Go has many of the features that make programming in ML a pleasure, many languages these days have them, which is a good thing.
Personally my tool of choice for many tasks would be OCaml with Go's package management system, and perhaps a syntax closer to M-expressions (like Mathematica).
Would you mind expanding on what is good about m expressions and how that could apply to go, I'm not familiar with them?
Please note I'm suggesting using that syntax for OCaml, not Go.
In short, I want to write "f[x;y]" for "f x y". On the first sight it appears this adds a bunch of noise, but there are many advantages:
1. You now have much less parens resulting from nested function calls;
2. You get partial application by any argument, not just the last. map[;list] is a "functor" that applies its argument to "list";
3. Corollary to this, chaining functions together is now much easier even if you need to supply a parameter other than the last: f[;x]$g[y] (assuming $ stands for apply; it might be wortwhile to take empty space for application)
4. Further you are able to unify many aspects of the syntax (if[cond;true;false]), which makes parsing easier for both humans and computers.
For package management, I haven't had the chance to really try it yet, but I'm hearing good things about OPAM.
Finally, Rust just looks awesome, I'm hoping that the language stabilizes before the end of the year, as I'd love to do my master thesis with it.
Package management is one of those things that are better off when there is just one.
I've been porting the reconciliation algorithm in SKS to Golang so Hockeypuck can peer with SKS servers. I think it will be very useful in other applications beyond keyservers. The mathematical definitions of finite fields and polynomials are elegant in OCaml, and I definitely understand the choice of language from that point-of-view.
If you want to see a comparison of finite-field arithmetic and polynomial factoring in Go vs OCaml, my recon port is in a separate project called conflux (https://github.com/cmars/conflux). It's an incomplete work in progress, needs tightening up, tail-call elimination, etc. but early feedback is welcome.
As a developer unfamiliar with OCaml & without much formal mathematics background, I had a hard time understanding some of the intent of the SKS sources -- in those cases, conflux is a straight-up port from OCaml with unit-tests also ported from SKS to back it up. Some of it, I understood the math concept, but not the OCaml, so I ported from SymPy instead.
Wolfram Alpha was also helpful to validate my work and create test cases -- it does polynomial factoring over finite fields!
I was mentioning it in my previous comment to provide perspective on my opinion of Go.
I am a big supporter of the idea that all languages have their advantages anyway :)
Go code will look a little less DRY to you as a result, which is a fair criticism, but it makes up for that by being incredibly opinionated (that's a good thing), being incredibly easy to prototype in, and being incredibly easy to refactor painlessly.
Nah, list comprehensions are just syntactic sugar and not used much in haskell. Python seems to encourage their use a lot, but you hardly even see them in haskell code.
>a very intricate type system allowing for things like generics (which Go doesn't have either).
That is definitely one of the big problems, but I take issue with the characterization of that as needing "a very intricate type system". Parametric polymorphism is very simple, and has been a completely solved issue for a very long time. There is simply no excuse for a brand new language to be decades behind on something so easy to do right.
>being incredibly easy to prototype in, and being incredibly easy to refactor painlessly.
Those are actually two of the other big issues going from go to haskell. Go is harder to prototype in, and it is easy to add bugs when refactoring because the type system is so poor.
Go has addressed this; their approach is Go's interfaces, which combines the best of all worlds: duck typing with static type checks and type inference.
> Go is harder to prototype in, and it is easy to add bugs when refactoring because the type system is so poor.
This is where we'll have to agree to disagree. It's definitely not harder to prototype in - and I say this as a functional programmer - and if you find the type system to be inadequate when refactoring, it sounds to me like you're trying to write idiomatic Haskell in Go. Go's type system, by design, stays out of the way - if you're writing Go idiomatically, you really shouldn't be thinking very much about the types as you write them.
As for generics, this gets beaten to death on every single Go post on HackerNews. Yes, Go would ideally have generics. Yes, there are tradeoffs involved. Yes, those tradeoffs have been explained by the Go developers at length. Yes, they would be open to including them in the future, if somebody addressed the existing concerns. No, nobody seems to mind that they're missing from the language as-is, given those tradeoffs.
>It's definitely not harder to prototype in - and I say this as a functional programmer
Have you used haskell to make the comparison?
>if you're writing Go idiomatically, you really shouldn't be thinking very much about the types as you write them.
I don't understand where you are coming from here. I am not thinking about types, that is why I need the compiler to point out when I mess them up. The problem is go has such a limited type system, that you have to change much more code when you refactor, and the type system is inadequate for catching many errors, in particular dealing with error handling. The combination makes go worse for refactoring than haskell. It is certainly much better than python for example, but you seem to be convinced that go is the top of the spectrum and nothing can exist above it.
Xmonad is a pretty common recommendation for looking at "good haskell code", in particular the overall design and how they keep the IO part minimized and isolated so the bulk of the application is easier to unit test. I think the standard libraries the come with GHC are good examples too.
http://isthishaskell.blogspot.com/2013/02/tips-on-learning.h...
I'd wager that if you aren't thinking about what your inputs and outputs are going to be at every step, you're introducing bugs or working harder than you have to. A strong static type system like you find in Haskell formalizes that so that it's required, but even in the languages I write most often (Python and C, which get bashed constantly for their type systems), this is just what writing solid code is about.
In Python, I may not be thinking exactly "what is the type of this thing, foo", but I am asking myself "okay, I'm trying to iterate this thing, is it actually iterable? How do I handle when it isn't? or guarantee it to always be an iterable ?".
i'm excited about rust, which did go the algebraic datatype route.
Also playing with Racket, Clojure, and good ol' Common Lisp.
{-# LANGUAGE OverloadedStrings #-}
import Snap
import qualified Data.ByteString as BS
main :: IO ()
main = httpServe (setPort 8000 emptyConfig) $ writeBS $ BS.replicate (1024*1024) 100
I'm benchmarking it currently, but my laptop's network stack seems to break ab. It's also probably faster to build the response incrementally using an Enumerator, but I've never used Snap's Enumerator library and this is slightly closer to the design being tested in the other servers since it'll allocate the whole bytestring instead of writing it lazily.I don't have the full numbers (didn't log them) -- but running "ab -n 100000 -c 1000 http://localhost:8000/ -- nodejs completed in 160 seconds, go in 170 seconds. Nodejs had a few requests around 8 seconds, and go had a worst time of almost 5 seconds. (This is on an old desktop, with a core 2 duo - roughly 6000 "bogomips" pr core, two cores).
I'm guessing the haskell solutions ran out of resources, but I'm not sure.
With a single-threaded Warp instance, I could get around 1350 reqs/seconds, though it failed dramatically when I used more threads.
Tried it now -- both haskell versions crash with -O2 as well (and ab -n 100000 -c 1000 -- so not the same benchmark as the original -- and a rather silly test).
Go was such a huge relief after that horrible catastrophe language that seems to still continue to wreck new generations. Please, please, don't poison your career on focusing on a single language, especially one as disturbing as Haskell.
Also, the negative effect one gets after going back to one's own code after several months seemed much much worse in Haskell. Haskell code is too thick, too concise, not unlike mathematics. I find it ironic that the community, apparently, values that.
I bet others have had better experiences, but I definitely did not. Hanging around with Haskell clearly taught me many good things about program design, but I don't foresee myself wanting to ever write anything on the platform ever again.
My career is likely older than you, I think it'll survive the horrors of using a good language. I've been running production web sites on haskell for a year so far, and it has been great.
Your career spans over 30 years? If so, I applaud you and of course withhold my rights to criticize your choices without knowing more details.