Hacker News new | past | comments | ask | show | jobs | submit login

Not sure Go is such a great fit for scientific computing. On the one hand, with garbage collection and other things, it won't be as fast as C++. On the other hand, it's less flexible than Python.

That said, it's always useful to have a good scientific library in every language.




I didn't like the lack of templates when implementing some Linear Algebra stuff. You can definitely do it but I prefer using C++ or a dynamic language for that...


I don't think the speed is the problem here. Plenty of sci stuff is done in Python. Go's poor type system is a bigger issue.


Python with Numpy/Scipy. The Python there is just calling high performance fortran libraries.


It's not quite that simple. The core packages wrap fortran or C code but then additional packages are built on that. Going by the github breakdowns Pandas, SymPy or Jupyter are pretty much pure Python, matplotlib is 90% Python 10% C++ (though the Python ratio is probably skewed up by the in-repo examples).

And that high-performance Fortran or C code is at the root of so much scientific computing is an issue in Go considering the overhead of cgo calls.


Jupyter and matplotlib aren't designed to actually do any calculation (they are just for communicating results) so it doesn't make sense for them to be written in C. Pandas has a ton of pure Python code, but if you dig through the layers of abstraction, all of the core algorithms are implemented in cython or make calls to numpy (which is calling C code).

Bottom line, when you're using an established Python scientific computing library to do numerical calculations, you're calling C (or maybe Fortran) routines.


> Go's poor type system is a bigger issue.

This. I think Julia[1] had the right idea about multiple dispatch.

[1]: http://julialang.org


What makes Go's type system poor?


One of the worst places lack of generics hits is numeric code, because you really want to be able to write Vector<int> or Vector<byte> or Vector<complex> without having to write all that over and over, multiplied across a significant number of such structures you might want templated (matrices of several types, several types of math-vectors, several types of arrays, etc.), multiplied across a large number of operations on those types. Datastructures times types in them times operations on them comes out to a big number in numeric code.

I've often thought that the utility of templates in numeric code is part of the reason people tend to overestimate its utility in other places. Seeing something really nail a solution in one domain and assuming it must be equally useful everywhere is a common programming community failure I've seen over the years, and I've been putting together a sort of list in my head of such things. (It currently includes "inheritance based OO is awesome because it nails writing GUIs", even though it's not so great for most other tasks, "FP is great because it nails writing compilers" which is getting more popular but it took more than just that, "data binding is great because it nails simple CRUD forms" but inevitably explodes in complexity beyond that, that sort of thing. Beware the techonology that is always demoed on the same use case every time, in every video and essay written about it.)

(And I'm not saying templating is useless, any more than any of the other things I mentioned are useless. I'm just saying it's very easy to overestimate the importance and utility of the given technology if you only look at where it is at its absolute best. You really need to look at the whole picture.)


So this is a very interesting way of describing language niches, because I've often felt that Go nails one thing very well: routing streams of bytes.

Any time you have to deal with "plumbing" (for lack of a better term), Go makes the job absolutely trivial. In a sense, I think it's a shame that Go has made it's name as "a language for concurrency" because I think that the concurrency features are in fact supporting features of the aforementioned usage: streaming dumb bytes left and right. Otherwise stated, Go is concurrent because concurrency helps ship bytes; it's not concurrent for the sake of solving general concurrency problems.

With that in mind, I'm still not clear on what makes Go's type system sub-par. I keep hearing this meme repeated, and although I know next to nothing about type theory, I have always found Go's type system to provide just enough scaffolding for byte-delivery pipework. Beyond that it just gets out of the way.

Consider this: Go is formally a static language, but it behaves (in the sense of how it's used in a workflow) in a manner closer to a dynamic language (compile time is equivalent to ipython's warm-up time, go playground makes testing snippets interactively very simple, etc). I think it's an error to compare Go with C. Go feels more like Python with concurrency and type safety.

So again: I understand the use-case for generics, but viewed through the lens of "nailing" the problem of shipping bytes (which again, I contend is Go's purpose), I fail to understand why Go's type system is repeatedly labeled as lacking. Go isn't Rust. It's not solving the same problems as Rust. From there, what is it that makes Go's type system shitty? I would describe it as "just enough type system".

Other than generics, what is it that people are expecting this damn thing to do? I'm very much open to being wrong (especially since this would inevitably introduce me to some interesting languages), but I can't quite conceptualize what people have in mind when they complain about Go's type system.


My reply is intrinsically in the domain of scientific code. It is not intended to make sense in the general context.

In that global context... Go's type system is about as simple as they come. It's actually hard to come up with a statically-typed language that, in practice, is simpler. The type system in C itself is technically simpler, but with preprocessor macros I'm not sure if it's simpler in practice. I'd say that's why it's generally labeled as "lacking"; on the scale of type system complexity, it's near the bottom before you get into dynamic languages.

If you'd like to learn why that might be a problem for people, I recommend jumping in the deep end and learning Haskell for what strong type systems can guarantee.

There are certainly times I find myself unable to say things in the type system that I would like to be able to say in Go's type system, even given that I am in fact writing network servers with it. I take the tradeoff because in the context I'm working, the simplicity of code tends to win out even so.

Also: https://news.ycombinator.com/item?id=10208075#10208636

And I would fully agree that a non-trivial amount of Go hatred (but not all) occurs from people picking it up and trying to use it in a context they should never have even picked it up for. (That said, I tend to consider scientific programming one of those, and a burgeoning community seems intent on proving me wrong, so shrug.)


> It's actually hard to come up with a statically-typed language that, in practice, is simpler.

Oberon-07

https://www.inf.ethz.ch/personal/wirth/Oberon/Oberon07.Repor...


>My reply is intrinsically in the domain of scientific code. It is not intended to make sense in the general context.

If I'm being honest with myself, I too have serious reservations about the extent to which Go is suited for scientific computation.

> I recommend jumping in the deep end and learning Haskell for what strong type systems can guarantee.

I'm superficially familiar with Haskell's typeclass system, but respectfully, this misses my point. What use is such a system in the context of scientific computing, or in the context of Go's mission?

I understand that there are type systems with stronger guarantees, but again, Go is not Haskell. Go is not Rust. Go is not solving these problems. My question is, in practice, what features of a type system are "these people" (the ones complaining about Go's type system -- I don't presume to label you, jerf, as one of them) pining for?

My (respectful) exasperation stems from the fact that these arguments usually compile down to something roughly equivalent to "Rust exists so why is Go not Rust? (Or Haskell)".

>I take the tradeoff because in the context I'm working, the simplicity of code tends to win out even so.

But this is exactly my point. At some point, adding features to the type-system is going to reduce the simplicity you enjoy in the context of problems for which Go was engineered. I appreciate that (to quote your linked comment) "the further away from a 'network server' you get, the less appealing Go gets", and that every success story you encounter with Go involves network servers. Moreover, I agree. Go nails this particular problem space, and I contend that this is in part because of the fast-and-loose design of its type system. We are in agreement with respect to Go's problem domain, and we are in agreement with respect to the fact that Go should not be viewed as a general-purpose concurrency language. These points, however, do not address the question of its type system.

So again: what more do you want this type system to do in the context of writing network servers? Which specific features from Haskell do you find yourself wanting, and what guarantee do we have that this would not undermine the simplicity and dynamic-i-ness that has made Go successful as a plumbing language?

>That said, I tend to consider scientific programming one of those, and a burgeoning community seems intent on proving me wrong, so shrug.

I'm inclined to agree with the caveat that certain disciplines (molecular bio and genetics for instance) increasingly rely on high-throughput streams of data. Perhaps Go is well-suited to the pipework, and perhaps it's advantageous to perform simple data transforms natively prior to doing the heavy lifting in Python or Julia ... I nevertheless remain unconvinced.


"I'm superficially familiar with Haskell's typeclass system, but respectfully, this misses my point."

I suggest becoming more than superficially familiar, then. With all due respect, I believe your core problem is that you do not understand what advanced type systems can do, so it's a mystery to you why anybody would want them, and the only cure for that is to go learn. Again, let me emphasize, I do not mean this to be mean, but sometimes there's just no way around the problem in an HN-post sized reply.

I know one recurring thing I've encountered is that I'd love to be able to say that in

    type Something interface {
        DoWhatever() Something
    }
that the return result of DoWhatever is guaranteed to be the same type as the thing you called it on. I'd love to be able to guarantee that if I have a container and a contained type that I can associate the two things together (i.e., I have a "Game" and "Move" interfaces and I'd like to associate specific Game implementations to specific Move implementations). I'd like containers that don't wrap everything in interface{}, resulting in an inefficient representation that is also hard to use in the code. I'd like non-nillable pointers.

On the balance I still use it for my job because the benefits outweigh the costs, but there are tradeoffs I make for it.


>I suggest becoming more than superficially familiar, then.

It's a work in progress :)

>With all due respect

No offense taken

> I know one recurring thing I've encountered is that I'd love to be able to say that in [...] that the return result of DoWhatever is guaranteed to be the same type as the thing you called it on

Forgive me, but isn't this generics all over again, or am I missing something?

And once more, is it possible to bake these features into the type system without requiring more boilerplate code? I like the idea of strong guarantees of a type system, but I worry about having to wrestle with the compiler. One of the things I really like about Go is that the type system provides guidance but I don't spend much time making the compiler accept things that I patently know are compatible (I'm looking at you, Rust).


I'd be interested in hearing more about your Rust pain here; we're working a lot on ergonomics and productivity.


It's annoying to sometimes have to introduce artificial blocks just to make the borrow-checker happy. It sounds like there's going to be some work done on non-lexical lifetimes though, which would solve the more annoying of these problems.


Hear you loud and clear, thanks!


> keep hearing this meme repeated,

That's not a meme. People using statically typed languages want compile time safety, not heavy reflection and ad hoc type creation at run time like in Go. I'm not interested in having to use void pointers everywhere just to get a bit of code reuse. Go type system is shitty, its authors know it, but they are too arrogant to acknowledge that fact publicly.

> Other than generics

The absence of generics is the issue.


Again, could you provide concrete examples of what you'd want to see?

In practice I rarely use `interface{}`. I really am open to being wrong about this, but it would be nice if someone could show me what might be improved. So far everyone is just telling me that it can be improved and that "Go's type system is shitty".

I want to be convinced. I really do. I'm just not.


Lacking SSE2/4 is a big factor. The gonum packages use assembly in performance critical sections for this reason.


> it won't be as fast as C++.

People used to say the same of C++ against C and Pascal compilers.

Where would C++ compilers be now, if C++ compiler vendors had given up?


I don't think getting performance on par with C or C++ is even among the design goals of Go, but I could be wrong. Within one order of magnitude? Sure. But not on par.


Anyone is free to implement a compiler for Go.

Who knows what the goals of this person might be.


The issue was when those statements were made computers were super slow. This was where FORTRAN became king of scientific computing.


Those were the 50 and 60's, C was yet to be invented and only became competitive against Fortran compilers after restrict was added (C99) and the special scientific extensions from the ANSI working group for numerical computing.

Should C compiler vendors also given up against Fortran compilers?


>Not sure Go is such a great fit for scientific computing.

"Go Data Science Tooling, Packages, Libraries, etc."

https://github.com/gopherds/resources/tree/master/tooling


Now compare with the tooling, packages, libraries in C++ or Python.


Now imagine someone proposing C++ or Python libraries on Usenet for scientific computing, around 20 years ago.

I am not a big fan of how Go's type system turned out to be, but do see it positive that people take the effort of bringing alternatives into the eco-system.


also there's julia, which is being designed from the ground up for this domain. if i were working on a scientific computing library that would be my first choice of ecosystem to target.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: