<p>Hi guys! </p>
<p><em>EDIT</em>: Please don't make this a thread about fighting against/for generics. Thank you. And keep it civil. </p>
<p>I'm putting this here, so people who are looking for it, can find it and because I was asked enough times. And for beginners to have an easy, searchable answer. </p>
<p>So, there was already a post how Go is not a functional language, and people implemented reduce and filter one or the other way. But there is actually a Map function in the standard library package of Go. </p>
<p>It's hidden in their respective types, like strings and bytes. </p>
<p><a href="https://golang.org/pkg/strings/#Map" rel="nofollow">Strings Map</a>
<a href="https://golang.org/pkg/bytes/#Map" rel="nofollow">Bytes Map</a></p>
<p>How to use it is right there in the documentation. <a href="https://play.golang.org/p/H6wjLZj6lW" rel="nofollow">Example Of Using Strings Map</a>. </p>
<p>If this has been common knowledge, my apologies for re-posting. </p>
<p>Thanks!</p>
<hr/>**评论:**<br/><br/>mattyw83: <pre><p>Usually when people are looking for map they're looking for a general purpose implementation (like in haskell or clojure etc). This is a good example of a specific implementation, but not the generic version most people look for.</p></pre>skarlso: <pre><p>True! Do you think it's still worth it to keep this post? :)</p></pre>mattyw83: <pre><p>Yes I think so, it shoes the go approach: Write specific functions using types</p></pre>skarlso: <pre><p>Cheers man. :-)</p></pre>weberc2: <pre><p>It's sad to me that the Go solution is to write a new map function for every combination of types you're interested in mapping to/from. Other languages get by with a single map function, but to achieve equivalent versatility, Go requires N map functions for every type (where N is the number of types) or N<sup>2</sup> map functions. Of course, N is infinite, which is very bad news indeed (at least, if you care about type safety or code readability).</p>
<p>It's more troubling when we consider that map() only operates on two types. Consider algorithms that operate on M types! The Go solution is to write N<sup>M</sup> functions to achieve the same versatility as some other languages (at least without giving up static type safety)!</p>
<p>:(</p></pre>ggggopher: <pre><p>its not problem, just write the For loop instead of</p></pre>weberc2: <pre><p>For loops aren't very composable compared to <code>map()</code> and friends. The ceiling on abstraction is low.</p></pre>Fwippy: <pre><p>There are several tools that will help you generate the various <code>MapStringToInt</code> functions you want. You don't have to give up type safety or code readability. You write the function once, and let the computer deal with generating the N<sup>M</sup> combinations (or, better yet, just the ones you care about using).</p></pre>weberc2: <pre><p>The autogeneration bit is valid; however, readability will still suffer as you cram type names into the names of methods and other type names (what's the type name for <code>Tuple<A, Tuple<B, C>></code>, for example? What's the name of a mapping function that maps from string to that tuple type?).</p>
<p>The other problem is that someone either has to maintain these auto-generated copies or you have to diverge from the normal build process (which might be okay if your code is a program, but there is an expectation that libraries are <code>go get</code>-able).</p>
<p>I think this ends up being more painful than using lots of <code>interface{}</code> + <code>reflect</code> + testing the crap out of everything. It's certainly not a good substitute for generics (no matter how much I might want it to be). :/</p></pre>Fwippy: <pre><p>Shrug. I don't generally use anonymous struct types (which I assume is what you mean by your nested Tuple structure); and prefer to name all of the types that I use more than once. I think any function signature that returns something that convoluted is atrocious: <a href="https://play.golang.org/p/pqhBT7EhfW" rel="nofollow">https://play.golang.org/p/pqhBT7EhfW</a> vs <a href="https://play.golang.org/p/Uig5Phglo9" rel="nofollow">https://play.golang.org/p/Uig5Phglo9</a></p>
<p>If you have a reason to group these values in such a way, you should have a word or phrase that describes this structure, which should show you how to name it.</p>
<p>Regarding maintenance: Just put a pre-commit hook that runs <code>go generate</code> and commits the generated code. Now you don't have to think about it ever again and it's completely transparent to go-getters.</p></pre>weberc2: <pre><blockquote>
<p>Shrug. I don't generally use anonymous struct types (which I assume is what you mean by your nested Tuple structure); and prefer to name all of the types that I use more than once. I think any function signature that returns something that convoluted is atrocious: <a href="https://play.golang.org/p/pqhBT7EhfW" rel="nofollow">https://play.golang.org/p/pqhBT7EhfW</a> vs <a href="https://play.golang.org/p/Uig5Phglo9" rel="nofollow">https://play.golang.org/p/Uig5Phglo9</a>
If you have a reason to group these values in such a way, you should have a word or phrase that describes this structure, which should show you how to name it.</p>
</blockquote>
<p>You don't seem to understand the purpose of generic algorithms. Tuple was just an example data structure, it could as easily have been an OrderedMap<K, V> type. The point is that <em>you don't know the types in advance</em>, and you can't name what you don't know. Going back to the tuple example, consider that you want to write this function: <code>func Zip<A, B>(as []A, bs []B) []Tuple<A, B></code>. This function takes two slices with different types and returns a slice of Tuple<A, B> where the Nth element in the slice is a Tuple containing the Nth elements of the original slices. You can't create a named struct to replace the Tuple<A, B> because A and B are placeholders for types that the algorithm doesn't even know about yet!</p>
<blockquote>
<p>Regarding maintenance: Just put a pre-commit hook that runs go generate and commits the generated code. Now you don't have to think about it ever again and it's completely transparent to go-getters.</p>
</blockquote>
<p>This is all well and good, but this requires <em>every committer</em> to do this. Further, any time the "template" is changed, <code>go generate</code> needs to be invoked manually. Moreover, what happens when my binary has a StringLinkedList generated implementation, and my binary depends on your library which also happens to have a StringLinkedList generated implementation? All of that duplication would lead to bloated binaries (and libraries). Finally, even if you solve all of those problems, we're still back at the atrocious naming problem (remember the <code>Tuple<A, Tuple<B, C>></code> example a couple posts up?).</p>
<p>I really think giving up static type safety and using <code>interface{}</code> + <code>reflect</code> + lots of extra testing is the easiest solution we have today for most generic problems. You'll compromise performance and type safety, but it's the solution with the least developer effort.</p></pre>skarlso: <pre><p>Well, I think you are looking at it from the wrong point of view. </p>
<p>Go is a system language in all of its glory. C doesn't have generics and it gets by just fine. There are a couple of ways you can work around it with templates but that's it. </p>
<p>And to be honest, last time I used maps and reduce and filter was with java, ruby and python. :-) And I very much hate Java Generics. Don't get me wrong, I know that they are useful. But they make for a freakishly convoluted and complicated read all together. :-)</p>
<p>I mean, look at this:</p>
<pre><code>public static <T extends Comparable<T>> T maximum(T x, T y, T z)
</code></pre>
<p>Also, to be honest, I only used those syntactic sugar methods because they were available. But I actually could have written a much more readable for cycle. </p>
<p>Now, again. These methods are useful of course, they do have their place. Just not in Go. This language isn't built that way. And that's one of its features for which I fell in love with it. But it might not appeal like that to others. And that is okay. :-) I'm a jealous lover anyways. :-)) </p></pre>BBbk11: <pre><p>C'Mon cherry pick more 'bad' stuff from java.</p>
<p>look at c#:
T Max<T>(T x, T y) where T : IComparable</p>
<p>C doesn't has generics because It's kinda old and not that easy to implement. But C also has less overhead by design than Go. The way C targets low level is completly different. You should really look into this before you start talking about this. However C has a kinda strong way so called Macros. A macro could be easily used for simplify a Max 'function' into one line.</p>
<p>Also almost noone writes a web server itself in C nowadays. Lots of people just use C for performance reason and then use js or python or whatever in addition</p>
<p>Talking about generics is for me no discussion if It should be implemented the only discussion for me is how It should be implemented. Also the question is what are generics?</p></pre>weberc2: <pre><blockquote>
<p>C doesn't have generics and it gets by just fine.</p>
</blockquote>
<p>C just got the <code>_Generic</code> keyword. Besides that, if C "gets by just fine", then I really don't think we'd see the proliferation of post-C languages that we see today (Go included). I'm not saying you can't write interesting or useful programs in C or Go, only that these languages would be more versatile with some support for generic programming.</p>
<blockquote>
<p>And I very much hate Java Generics.</p>
</blockquote>
<p>I'm not advocating for Java Generics. There's no reason Go generics couldn't learn from Java's mistakes. Speaking of ugly generic solutions, have you seen Go's <code>sort</code> package?</p>
<blockquote>
<p>These methods are useful of course, they do have their place. Just not in Go. This language isn't built that way.</p>
</blockquote>
<p>I guess it's fortunate that programming languages aren't fixed, and the project maintainers can add features at their discretion.</p></pre>zarandysofia: <pre><blockquote>
<p>Well, I think you are looking at it from the wrong point of view.
Also, to be honest
Now, again. These methods are useful of course,</p>
</blockquote>
<p>I am just reading a bunch of standards degradation out the lack of generics and fanboyism on Go, I bet the day the feature finally arrive on the language (I doubt about it) your current mind set will do an 180, laugh about all this nonsensical delusions (forgive me the expression) and start using it them like underwear. Sad really.</p></pre>skarlso: <pre><p>I do not agree with you on that one, friend. :-) I genuinely think this langue does not require them and that they make for a convoluted read all together. But hey, whatever makes you sleep at night. :-)</p></pre>zarandysofia: <pre><blockquote>
<p>But hey, whatever makes you sleep at night. :-)</p>
</blockquote>
<p>Stop projecting.</p></pre>skarlso: <pre><p>Huh?
Edit: I think, I got what you mean. You mean to say I should stop using passive aggressive redirections? I wasn't trying to. I seriously wanted to say that whatever he likes. I dint want to tell anyone what to like. </p></pre>metamatic: <pre><p>It's almost like a lack of generics is a barrier to providing the functionality people want.</p></pre>caseynashvegas: <pre><p>Are you saying this sarcastically?</p></pre>metamatic: <pre><p>I know generics are a bit of a sore point in the Go community. I do think the language would be better if it had them, but on the other hand no generics is probably better than something ugly like Java-style generics.</p></pre>caseynashvegas: <pre><p>I couldn't tell your tone obviously, but I was hoping you weren't suggesting that not having generics prevents the ability to deliver any application functionality. I am not going to going to debate developer efficiency, but in no way are generics required for delivering any type of software.</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传