On Tue, Jun 21, 2016 at 9:38 PM, xingtao zhao <zhaoxing...@gmail.com> wrote:

> I totally agree that I always want generics mainly when I am writing a
> framework. But I do not agree with you on that "go is pretty much a
> language for writing applications". I don't think go is powerful enough
> that we do no need any framework. I don't think we can always develop
> applications from the scratch.
>

I agree. But I don't think that "reuse" implies "framework", lest "requires
generic". For example, you can write very easily reusable components based
on net/http. Much, much more so, than what we probably would have with
generics. For reuse you need to build abstractions, but the limited way in
which we can abstract in go requires you to think hard about *good* ones.


> And I do think it is a big help for go if we have a lot of
> frameworks/libraries right on your hand. I do think it is a waste of
> engineer time to develop all the tools from scratch. Currently there are
> many frameworks/libraries have to use a lot of reflections just because
> generic is missing.
>

No, they don't have to, they want to, because thinking about good
abstractions is hard and reflection is the only way go gives you to write
bad and ultimately useless abstractions.


> This both makes the framework/library hard to use, slower, and less safe
> (a lot of runtime type checking which should/could be done at compiling
> time).
>

I disagree that safety for it's own sake is a useful goal. I consider type
safety like I consider memory safety: You definitely want the vast majority
of your code to be memory safe, but sometimes you have to use unsafe in
limited cases and that's fine and it doesn't compromise the safety of the
program as a whole. If the unsafe amount of code is small enough, it's
easily verified by hand. The same goes for type-safety. It is fine to lose
some type-safety in limited amounts of code, as long as you are careful,
review it and make the limitations simple to understand.

A good example are the encoding packages - that's a decent place to use
reflection, even though it limits your static type safety. But there is
limited API surface that you need to understand, usually just two functions
or so. It's easy to still write safe programs that way.


> Think about how many people were asking: For the following types, how can
> I convert []Fool to []Barer, and via verse?
>
> type Barer interface { Bar() }
> type Foo struct{ ... }
> func (f *Foo) Bar() { ... }
> func Process([]Barer) { ... }
>
> We have to tell them write a helper function to convert it.
>

No, we don't. We have to write a loop. We might opt to write a helper if we
need to do that very often. But, honestly, we almost never do.


> While in fact, if we have generic, and declare Process as:
>
> func Process<T Barer>([]T) { ... }
>
> we do not need this kind of conversions at all. Interface is perfect for
> abstraction of the direct layer, while it is not good enough for
> abstractions inside of slice, map, chan, and structure, especially for
> slices which are used a lot in go code. I think this is a very big
> requirement by the users who is writing "applications" as well.
>

I disagree. You are, again, writing frameworks. A perfectly understandable
and readable loop that turns a []Foo into a []Barer is four lines of code.
A helper function is six. You probably need to do that on average at most
.1 times per application that you write. I don't consider .6 lines of code
per application saved a significant saving that could serve as an argument
here.

And you are also misrepresenting, what would happen. Because realistically
(look at existing languages with generics) the signature of that function
would more be something like

func Map<Iterable<T>, O>(in T, f func(T) O) Iterable<O>

Just to save .6 lines of code per application.

On Tuesday, June 21, 2016 at 11:56:01 AM UTC-7, Axel Wagner wrote:
>>
>> The issue is, that a "KeyValuePair<K, V>" (no matter if you implemented
>> it via generics or like you mention via interfaces) is a fundamentally
>> useless type and generics encourage people to add useless types. A
>> "KeyValuePair<K, V>" is a "struct { Key K, Value V }", plain and simple.
>> It's not an interface and it's not a generic type, it's simply a struct.
>>
>> I agree, that generics are useful, but they seem to be mainly useful for
>> people who write "frameworks", not so much for people who write
>> "applications" and so far, go is pretty much a language for the latter.
>> Whenever people try to justify generics, they do it from a "I want to write
>> a framework" POV - and whenever I miss generics, I do because I'm currently
>> writing a framework of some kind.
>>
>> Generics empower abstractions, but most programmers are very bad at
>> building abstractions, so if you make it easy to build abstractions, you
>> will end up with a lot of bad abstractions (have a look at java). So, to a
>> certain degree, the value of go is, to *not* make building abstractions
>> overly simple. That leads to abstractions being used only where they are
>> essential and being left out where they are superfluous. This is where
>> reduced cognitive overhead comes into play - limiting the levels of
>> abstractions that people need to deal with to the bare essentials. Java is
>> bloated and hard to use, not because the language is bad, but because it
>> has a history of programmers building bad abstractions into it which gets
>> stacked on top of each other. So, yes, if you compare a bad abstraction
>> using interfaces with a bad abstraction using generics, generics will, in
>> general, compare very well. But you just shouldn't build the bad
>> abstraction in the first place.
>>
>> The second concern with complexity is the spec. The exact behavior and
>> semantics of generics need to be spec'ed and useful generics need a lot
>> specification. For example, the current rules for type inference can be
>> understood completely just by looking at a single expression and it's type
>> and it's correspondingly simple to implement and spec. Generics usually
>> need more powerful type inference methods to not be cumbersome, which will
>> take up a lot of space in the spec. As humans, just like computers, have
>> very little memory, the time it takes to understand the spec will grow
>> superlinear with the length of it, due to frequent cache misses, so a long
>> spec will significantly increase the time needed to learn the language. In
>> the same vein, to understand a language, you need to know about
>> interactions between it's different concepts, not just the concepts itself,
>> so the needed space and time complexity to learn a language also grows
>> quadratic in the number of concepts in the language (in general). All of
>> that contributes to why people are wary of adding new concepts to go - the
>> costs in terms of understanding and learning the language are huge and they
>> grow very much superlinear in the number of concepts added, so each added
>> concept must be carefully examined (I know go for years and I still learn
>> new things about interactions between different concepts all the time).
>>
>>
>> I sometimes miss generics, yes, but I also believe adding them will make
>> the language significantly harder to learn and will significantly worsen
>> the quality of go code in the wild, so it would likely eliminate the
>> reasons I like go currently (which is that go code is usually of
>> exceptionally high quality, uniform and easy to understand).
>>
>> On Tue, Jun 21, 2016 at 5:06 PM, <andrew...@gmail.com> wrote:
>>
>>> >> What I mean is that most people who have followed the past generics
>>> discussions already know it's possible to implement them with efficient
>>> memory use and performance. So they don't need to worry much about that.
>>>
>>>
>>> Thank you for explanation.
>>>
>>> >> can they be implemented without making Go a much more complex
>>> language than it is now
>>>
>>> What is a measure of the syntax complexity in the Go language.
>>> What this means and how they should be measured such a relative criteria?
>>> - Much more complex
>>> - More complex
>>> - Slightly more complex
>>> - Little bit more complex
>>>
>>> Also how you personally measure these cognitive loads?
>>>
>>> 1.Sample (pattern)
>>>
>>> type KeyValuePair interafce {
>>>   key interface{}
>>>   val  interface{}
>>> }
>>>
>>> 2.Sample (pattern)
>>>
>>> type KeyValuePair<K, V> interafce {
>>>   key K
>>>   val  V
>>> }
>>>
>>> What about that a value of the #2 sample is more complex than #1 sample
>>> on the 146%?
>>> With permissible error of no more than 5%.
>>>
>>> I think that possible we should to start a discussion about that problem
>>> (complexity measurement of the Go language perception).
>>>
>>> I'm not kidding.
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "golang-nuts" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to golang-nuts...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to