Live data from Hacker News

Channels Are Not Enough

gist.github.com

211–220 of 224 posts

Re: Channels Are Not Enough

#212
post #157

Earlier quoted context omitted.

> Are you arguing that an implementation of generics in a programming language is free? (Whether it be performance or implementation complexity.) I am. Performance: if you replace all generics with interface{}, you get performance that is at better or equal to current Go code. Implementation complexity: You could add some constraints to generics, for example only interface types can be used as generic parameters, and…

> Performance: if you replace all generics with interface{}, you get performance that is at better or equal to current Go code. That is incorrect. Using `interface{}` incurs a significant performance penalty at runtime because you end up boxing everything. For example, you cannot cast a `[]interface{}` to an arbitrary `[]A`. In other words, no, `interface{}` is not `void*`, sorry. If it was, Go would not be memory sa…

What I meant is, "better or equal to current Go code using the current version of polymorphism (which is `interface {}`)".

AFAIK it's not possible to write generic Go code without `interface {}` (or, alternatively, duplicating the code for each type).

Re: Channels Are Not Enough

#213
post #212

Earlier quoted context omitted.

> Performance: if you replace all generics with interface{}, you get performance that is at better or equal to current Go code. That is incorrect. Using `interface{}` incurs a significant performance penalty at runtime because you end up boxing everything. For example, you cannot cast a `[]interface{}` to an arbitrary `[]A`. In other words, no, `interface{}` is not `void*`, sorry. If it was, Go would not be memory sa…

What I meant is, "better or equal to current Go code using the current version of polymorphism (which is `interface {}`)". AFAIK it's not possible to write generic Go code without `interface {}` (or, alternatively, duplicating the code for each type).

Yes, but the tradeoff Go takes right now is "slow programmers," or "no generics." You are trading that in for "slow programs." This directly implies that generics have some sort of cost structure and are not free.

`interface{}` is very rarely used for writing "generic" code precisely because of its lack of type safety and performance implications. If you came up with a way to make it type safe without addressing performance, you've just implemented a generics scheme that will cause programs to be slower than they would be without generics (because people would start using them!).

Re: Channels Are Not Enough

#214
post #212

Earlier quoted context omitted.

What I meant is, "better or equal to current Go code using the current version of polymorphism (which is `interface {}`)". AFAIK it's not possible to write generic Go code without `interface {}` (or, alternatively, duplicating the code for each type).

Yes, but the tradeoff Go takes right now is "slow programmers," or "no generics." You are trading that in for "slow programs." This directly implies that generics have some sort of cost structure and are not free. `interface{}` is very rarely used for writing "generic" code precisely because of its lack of type safety and performance implications. If you came up with a way to make it type safe without addressing perf…

I think it should be clear to every programmer that there are different trade-offs to be made when designing systems, including the trade-off between generic-code&fast-development&slow-speed and specific-code&slow-development&fast-speed. People that don't get that shouldn't be programmers, and people that get it should have the freedom to make their own trade-offs.

In other words, the only "cost" of generics, thus, is the social cost (there is no purely technical cost). Here, it boils down to the philosophical/political freedom-vs-safety question, and I strongly incline towards freedom. Go does not. Go's position is, if not wrong, at least loosing, since programmers demonstrably are using work-arounds (`interface {}`) when they need generics.

Re: Channels Are Not Enough

#215
post #214

Earlier quoted context omitted.

Yes, but the tradeoff Go takes right now is "slow programmers," or "no generics." You are trading that in for "slow programs." This directly implies that generics have some sort of cost structure and are not free. `interface{}` is very rarely used for writing "generic" code precisely because of its lack of type safety and performance implications. If you came up with a way to make it type safe without addressing perf…

I think it should be clear to every programmer that there are different trade-offs to be made when designing systems, including the trade-off between generic-code&fast-development&slow-speed and specific-code&slow-development&fast-speed. People that don't get that shouldn't be programmers, and people that get it should have the freedom to make their own trade-offs. In other words, the only "cost" of generics, thus, i…

> Go's position is, if not wrong, at least loosing, since programmers demonstrably are using work-arounds (`interface {}`) when they need generics.

I just got through telling you that this type of use is actively discouraged, so no, people aren't using it as often as you might think.

If you want generics, you've got to pay for it. The implementation you've suggested requires a runtime performance penalty to use generics. Therefore, you have not demonstrated that generics are free.

Re: Channels Are Not Enough

#216
post #180

The interesting thing about Go, that can help make sense of all its oddities, is that it was not created to assist the developer. Go was created for businesses, not developers. The holy grail of a corporate programming language is that all individual developer personality is restricted, such that _you cannot tell from reading code who wrote it_. This is all about long-term, large-scale maintainability for massive cod…

I understand not having any fancy features in a "corporate programming language", but wouldn't language features aimed at reducing code duplication (like generics) help with maintainability?

I think the extra flexibility gained would be perceived as a negative. The ideal (from their perspective) is that there is only one way to do a particular thing, no matter how verbose it is. Google has recently been mostly Java (Guice, dependency injection everywhere), and has long preferred incredibly verbose code at the cost of occasional duplication.

Re: Channels Are Not Enough

#217

Earlier quoted context omitted.

As somebody using pre-generics Java libraries from time to time, I can say with confidence that generics are not the cause of complexity. Casting from Object is a source of bad type safety and doesn't help with documentation. The complexity you'll find in a mature codebase is a function of the way it is architectured and the complexity inherent to the domain, mostly.

I wish people wouldn't assume there's only two options - Generics or casting from Object/interface{}/void* It's a straw man argument. No experienced Go programmers are trying to say that's a good way to write code. The idea is to restructure your code so that basic data structures and interfaces pick up the majority of your reuse scenarios.

I'm no Go programmers, but I relatively often need to take a parametrized basic data structure as storage and write a parametrize class on top of it, while hiding the data structure because it's irrelevant.

Well, I guess I'll keep not being a Go programmer :)

Re: Channels Are Not Enough

#218
post #158

Earlier quoted context omitted.

There's no generalized solution to every generic problem. The "cast to interface{}" is the closest to a linear mapping of generics, but if you're reaching for that all the time, you're doing it wrong. So the only sane answer is, "it depends". The only use case that I have encountered that is essentially impossible in Go is the "generic data structure". Mind you, that's a bit of a big deal, even if it covered over by…

Talking about how to implement generics generically isn't really responding to my question. The original post had questions about how to implement specific concurrent constructs like pipelines, futures, and so on. So the question is how do you handle concurrency in Go? Are we missing important features that should be part of the language or standard libraries? Some of these may be one-off generic functions like appen…

I know this is going to sound like an evasion, but the answer is that idiomatic Go doesn't involve pulling in patterns from other languages, but using ones native to the language.

Futures I can be specific about, though. You simply don't use "futures" in Go. Futures (as the term is used by most languages) are a hack around missing concurrency constructs, and in Go, they aren't missing. Use channels instead. This covers rather a lot of patterns from Javascript and the weaker languages, actually... you don't port them, you simply don't use them. They aren't that appealing once you learn the native idioms, which are, generally, quite a bit better.

Putting a "future" library up on /r/golang is a pretty common occurrence... but they're so trivial they're worthless. It's harder to "use" a future than it is to just do thing the future library is doing.

For pipelines, you just "do" them... you don't set up some declarative pipeline, you just... program them. Sort of like how in the Python world they prefer the for loops to map statements? Same thing, really... if you want a pipeline, just hook things together manually. They may miss out on some abstraction, but, honestly, in most imperative languages I'm underwhelmed by the concept of really generic pipelines. Haskell's making some progress on that front and I've actually got an "in the wild" five-stager, but in the imperative world I'm not sure I've ever encountered in the wild some sort of 6-stage pipeline that was better written other ways.

If any major concurrency pattern is missing from Go, it's an explicitly asynchronous concurrency pattern. However, this can be fixed by library code: https://github.com/thejerf/reign

Re: Channels Are Not Enough

#219
In an essay titled "Why Pascal is Not My Favorite Programming Language" Brian W. Kernighan wrote:

The size of an array is part of its type

If one declares

     var     arr10 : array [1..10] of integer;
             arr20 : array [1..20] of integer;
then arr10 and arr20 are arrays of 10 and 20 integers respectively. Suppose we want to write a procedure 'sort' to sort an integer array. Because arr10 and arr20 have different types, it is not possible to write a single procedure that will sort them both.

The place where this affects Software Tools particularly, and I think programs in general, is that it makes it difficult indeed to create a library of routines for doing common, general-purpose operations like sorting.

Kernighan was one of the early C/Unix developers from Bell Labs. It is amusing to note that Go, whose authors come from the same background, getting criticized for something very similar.

[1]: http://www.lysator.liu.se/c/bwk-on-pascal.html

Re: Channels Are Not Enough

#220
post #180

Earlier quoted context omitted.

I understand not having any fancy features in a "corporate programming language", but wouldn't language features aimed at reducing code duplication (like generics) help with maintainability?

I think the extra flexibility gained would be perceived as a negative. The ideal (from their perspective) is that there is only one way to do a particular thing, no matter how verbose it is. Google has recently been mostly Java (Guice, dependency injection everywhere), and has long preferred incredibly verbose code at the cost of occasional duplication.

Agreed, it's likely what you say is the perception. But the thing is:

> The ideal (from their perspective) is that there is only one way to do a particular thing

The lack of useful tools like generics (and others) means there is no single way to do a particular thing: things must be duplicated everywhere (or ugly workarounds to avoid doing so must be employed, like casting from Object or using interface{} or whatever). Surely the benefits of better tools outweigh their inconveniences, even in a corporate environment? This is not a nerdy programmer's whim, but a major software engineering principle of direct consequences for any business.

Taken to an absurd extreme, you can simply copy & paste code everywhere -- that's the simplest programming model there is, and even the most junior of programmers can handle it without having their learning skills taxed in any way. It just leads to maintenance hell, which is why it's frowned upon even in corporate environments.

Post reply on HN