Go(lang) VS Generics: What are the USE CASES?

6,453 views
Skip to first unread message

josvazg

unread,
Apr 20, 2012, 6:05:15 AM4/20/12
to golang-nuts
This is NOT yet another "I want generics in Go" or "why Go doesn't
have generics?" post.

In fact, on the contrary, the idea is to enumerate the Use Cases for
Generics and how Go solves them without Generics.

In this way we could:
1- Point any newcomer to this thread when he/she asks the same old
question again and no wasting more time in that.
2- Isolate the USE CASES that call for (or force) a Generics based
solution, one by one and identify:
* Whether or not there are good enough solutions in Go right NOW,
with some sample of them.
* If there is NOT a PROPER solution right now, or it is too complex,
ugly or gives bad performance or maintenance:
* Would it be easily solvable (and worth) by adding an orthogonal
NON-generics feature to Go or not?

Who knows, we might find that generics always have good alternative
solutions! (or we may not)

Dave Cheney

unread,
Apr 20, 2012, 6:13:46 AM4/20/12
to josvazg, golang-nuts
I suggest that email is the wrong tool for this of job. I recommend
you collect and curate this data on the wiki.

Cheers

Dave

josvazg

unread,
Apr 20, 2012, 6:15:23 AM4/20/12
to golan...@googlegroups.com
FIRST USE CASE: 
If you just need to have an Generic Algorithm on some data whose Type you Don't Yet Know but that needs to follow some Properties or Behaviours...

You just use interfaces to define the properties or behaviours and make the Generic Algorithm work on that interface. As exemplified by the sort package:

...
More uses cases?

josvazg

unread,
Apr 20, 2012, 6:26:54 AM4/20/12
to golan...@googlegroups.com, josvazg
Done:

The problem is I do not KNOW all the use cases to enumerate neither their solutions, so a previous discussion may help completing the wiki page.

Jose

Davies Liu

unread,
Apr 20, 2012, 6:52:35 AM4/20/12
to josvazg, golan...@googlegroups.com
Another one: map() in Python:

map(lambda x:x*2, range(100))

How can i archive this in Go?

nv := Map(func (x int) int { return x * 2 },  []int{1,2,3})

I had tried reflect solution, the performance is really bad.

func Map(f interface{}, v interface{}) interface{} {
--
 - Davies

Ryan Betts

unread,
Apr 20, 2012, 8:02:33 AM4/20/12
to golan...@googlegroups.com, josvazg
On Friday, April 20, 2012 6:52:35 AM UTC-4, Davies wrote:
Another one: map() in Python
map(lambda x:x*2, range(100))

- Polymorphic functions that operate on built-in generic types. 
  func KeyIntersection(a map[T1]T2, b map[T1]T2) map[T1]T2 {}

- Containers that must store non-interface values. There are various motivations: control memory layout, require an immutable copy..

Ryan.

Robert Johnstone

unread,
Apr 20, 2012, 9:25:51 AM4/20/12
to golang-nuts
Another use case: type safe containers.

Michael Jones

unread,
Apr 20, 2012, 10:09:32 AM4/20/12
to Robert Johnstone, golang-nuts
mathematical operations on classes of numbers, for example, everything
about being complex or quaternion, independent of base type, so as to
allow Gaussian integers or complex reals via the same specializable
code, and by extension, allow various forms of interval arithmetic
upon int, real, or perhaps complex built from other parameterized
types.

--
Michael T. Jones | Chief Technology Advocate  | m...@google.com |  +1
650-335-5765

John Asmuth

unread,
Apr 20, 2012, 10:18:15 AM4/20/12
to golan...@googlegroups.com
Code that wants to use a channel in a generic way will fundamentally change the semantics.

That is, if you have a "chan X" and want to pass it to a function that needs a "chan Y", assuming you can convert an X to a Y, you have to introduce a buffer - that chan can no longer be used as a synchronization point.

josvazg

unread,
Apr 20, 2012, 10:36:27 AM4/20/12
to golan...@googlegroups.com
Does anyone have (proper) solutions for those in Go. (cause I haven't right now)

We could write them down on the wiki under "unsolved use cases" for the time being.

Jose

Robert Johnstone

unread,
Apr 20, 2012, 10:48:38 AM4/20/12
to golang-nuts
I don't see how generics fix this problem, unless the original
function is generic.

Also, are you sure that the chan can no longer be used as a
synchronization point? The value will pass through an intermediate
stage on its way to the final destination, but I'm not certain that
you'll break the sending code.

Robert Johnstone

unread,
Apr 20, 2012, 10:50:00 AM4/20/12
to golang-nuts
Agreed, although we should keep in mind that allowing operator
overloading is a separate issue.

si guy

unread,
Apr 20, 2012, 10:57:05 AM4/20/12
to golan...@googlegroups.com
To paraphrase someone (I don't remember who):
Go programs should be written in a go mindset.

Some of these use cases smell like algorithms written for the features of some other language that are being ported to go.

An example I _do_ understand would be containers, which should be tailored to each application anyway removing the use for generics.
It's not as though they are difficult to write.

Vanja Pejovic

unread,
Apr 20, 2012, 10:59:49 AM4/20/12
to Robert Johnstone, golang-nuts
If you have two unbuffered channels, var cx chan X, and var cy chan Y, and something like:
cy <- foo(<-cx)  and foo is a func (X) Y
and you have two other pieces of code, one that sends on cx, and one that receives on cy, you will never move forward.

The sender will block until the goroutine running foo receives from cx, and the receiver will block until the same goroutine sends on cy. 

Michael Jones

unread,
Apr 20, 2012, 11:01:41 AM4/20/12
to Robert Johnstone, golang-nuts
Certainly.

I'm not eager, but also not unwilling to write
a.AddIntervalComplexRational64(b)
if I have to, but I sure think that a compiler, preprocessor, macro
system, metaprogramming language, or some such should allow me the
luxury of building the cross product of a dozen orthogonal behaviors
by specifying code for the dozen behaviors and rules for composition
rather than me coding 4096 discrete solutions in vi. Saying no to this
is like saying, you don't need integer multiply, just add. a lot.

--

andrey mirtchovski

unread,
Apr 20, 2012, 11:06:32 AM4/20/12
to golang-nuts
polymorphic functions for useful things like "make", "new", "len", "append" ;)

Corey Thomasson

unread,
Apr 20, 2012, 11:45:29 AM4/20/12
to Michael Jones, Robert Johnstone, golang-nuts
On 20 April 2012 11:01, Michael Jones <m...@google.com> wrote:
but I sure think that a compiler, preprocessor, macro
system, metaprogramming language, or some such should allow me the
luxury of building the cross product of a dozen orthogonal behaviors
by specifying code for the dozen behaviors and rules for composition
rather than me coding 4096 discrete solutions in vi.

 m4, awk, sh, etc. call all solve this problem (rather easily in fact) if you just want _something_ to do it.

Michael Jones

unread,
Apr 20, 2012, 11:52:42 AM4/20/12
to Corey Thomasson, Robert Johnstone, golang-nuts
That's how I solve it. I just think that Go could solve it better, perhaps with type-aware expansion or other sophistication, and so I shared it as an example of what could be done in this area.

John Asmuth

unread,
Apr 20, 2012, 12:00:05 PM4/20/12
to golan...@googlegroups.com, Robert Johnstone


On Friday, April 20, 2012 10:59:49 AM UTC-4, vvaffle wrote:
If you have two unbuffered channels, var cx chan X, and var cy chan Y, and something like:
cy <- foo(<-cx)  and foo is a func (X) Y
and you have two other pieces of code, one that sends on cx, and one that receives on cy, you will never move forward.

The sender will block until the goroutine running foo receives from cx, and the receiver will block until the same goroutine sends on cy. 

I do not believe this is correct. "<-cx" will be evaluated as soon as someone sends to it, and the value will sit in the goroutine running "cy <- foo(<-cx)" until someone reads from cy. That is, it will be a buffer of size 1.

Vanja Pejovic

unread,
Apr 20, 2012, 12:04:09 PM4/20/12
to John Asmuth, golan...@googlegroups.com, Robert Johnstone
Yeah, you're right.

josvazg

unread,
Apr 25, 2012, 4:39:55 AM4/25/12
to golan...@googlegroups.com, josvazg
I updated the wiki to reflect this unresolved use case at:

You say that the Go solution based on reflection has bad performance, but...
is it worse than the Python implementation or not?

On Friday, April 20, 2012 12:52:35 PM UTC+2, Davies wrote:
Another one: map() in Python:

map(lambda x:x*2, range(100))

How can i archive this in Go?

nv := Map(func (x int) int { return x * 2 },  []int{1,2,3})

I had tried reflect solution, the performance is really bad.

func Map(f interface{}, v interface{}) interface{} {
}
 - Davies

Jesse McNelis

unread,
Apr 25, 2012, 5:47:50 AM4/25/12
to Davies Liu, josvazg, golan...@googlegroups.com
On Fri, Apr 20, 2012 at 8:52 PM, Davies Liu <davie...@gmail.com> wrote:
> Another one: map() in Python:
>
> map(lambda x:x*2, range(100))
>
> How can i archive this in Go?
>
> nv := Map(func (x int) int { return x * 2 },  []int{1,2,3})
>
> I had tried reflect solution, the performance is really bad.
>
> func Map(f interface{}, v interface{}) interface{} {
> }

The generic Go solution to map() is:

s := []int{1,2,3}
f := func(x int){return x*2}
for i,_:= range s {
s[i] = f(s[i])
}

Which has even better readability than a call to map().


--
=====================
http://jessta.id.au

roger peppe

unread,
Apr 25, 2012, 5:58:35 AM4/25/12
to Jesse McNelis, Davies Liu, josvazg, golan...@googlegroups.com
On 25 April 2012 10:47, Jesse McNelis <jes...@jessta.id.au> wrote:
> On Fri, Apr 20, 2012 at 8:52 PM, Davies Liu <davie...@gmail.com> wrote:
>> Another one: map() in Python:
>>
>> map(lambda x:x*2, range(100))
>>
>> How can i archive this in Go?
>>
>> nv := Map(func (x int) int { return x * 2 },  []int{1,2,3})
>>
>> I had tried reflect solution, the performance is really bad.
>>
>> func Map(f interface{}, v interface{}) interface{} {
>> }
>
> The generic Go solution to map() is:
>
> s := []int{1,2,3}
> f := func(x int){return x*2}
> for i,_:= range s {
>    s[i] = f(s[i])
> }

or even:

s := []int{1,2,3}
for i := range s {
s[i] *= 2
}

:-)

Chandra Sekar S

unread,
Apr 25, 2012, 6:32:10 AM4/25/12
to golan...@googlegroups.com
It's more like,

s := []int{1,2,3}
s2 := make([]int, len(s))
for i, v := range s {
   s2[i] = v*2
}

Repeat for every type of slice you'd be doing a map on.

I also see the style used in sort package being recommended instead of
full generic support. Slices are a lot more commonly sorted than
anything else and re-implementing Swap and Len for every type of slice
is redundant. With proper generics, the Sort function can just take a
slice and a function which compares 2 items of the slice.

Kyle Lemons

unread,
Apr 25, 2012, 12:20:14 PM4/25/12
to Chandra Sekar S, golan...@googlegroups.com
On Wed, Apr 25, 2012 at 3:32 AM, Chandra Sekar S <chand...@gmail.com> wrote:
It's more like,

s := []int{1,2,3}
s2 := make([]int, len(s))
for i, v := range s {
   s2[i] = v*2
}

Repeat for every type of slice you'd be doing a map on.

I don't do maps that often, but when I do, I always find it most clear to simply inline the 3-line loop.
 
I also see the style used in sort package being recommended instead of
full generic support. Slices are a lot more commonly sorted than
anything else and re-implementing Swap and Len for every type of slice
is redundant. With proper generics, the Sort function can just take a
slice and a function which compares 2 items of the slice.

I've seen code for generic sorts.  The problem is that you have to not only have a generic way to know how to sort (lexicographically? numerically? in reverse?) but how to get the key (is it a bare number? is it a struct member? is it an index of a sub-slice/array?).  It is FAR clearer to simply write the 4 lines of code it takes to precisely describe what you want to sort, and the performance is better.

Chandru

unread,
Apr 25, 2012, 12:41:51 PM4/25/12
to golan...@googlegroups.com
That'll be done by the comparison function!

bugpowder

unread,
Apr 26, 2012, 3:38:13 PM4/26/12
to golan...@googlegroups.com
On Friday, April 20, 2012 10:57:05 PM UTC+8, si guy wrote:

To paraphrase someone (I don't remember who):
Go programs should be written in a go mindset.

Assuming Go's mindset is perfect and set in stone.

Because it's not about writing "Go programs" it's about using Go to write programs --so needs may vary.

For example: C can be perfect for some programs, but that doesn't mean that you have to use C strings to "write in a C mindset". 
In fact you would do much better, and your program will more likely be more correct, if you use a third-party string library that keeps the strings length, abstracts away the char arrays, etc.

Rodrigo Kochenburger

unread,
Jun 27, 2012, 8:35:42 PM6/27/12
to golan...@googlegroups.com
In my case, every time I thought that having Generics would have helped me was mostly to allow sharing algorithms or data structures. Usually it was doable with the current language implementation but always involved more code and noise to make it work.

Take the math package for example. It uses float64 for all function arguments and returns, forcing you to always typecast your value to it and back. You endup with a lot of float64() and, for example, int() in your code and many unnecessary memory allocation and copy of data.

Another example is for containers, where you want to enforce a given type, like a map[string]int would do. I might have a tree or a queue or whatever and be able to trust and check at compile time if the type is what expected.

I've never found a problem that couldn't be solved without generics but it would definitely make easier to write less code for more reusable code, sometimes.

On Friday, April 20, 2012 7:05:15 AM UTC-3, josvazg wrote:
This is NOT yet another "I want generics in Go" or "why Go doesn't
have generics?" post.

In fact, on the contrary, the idea is to enumerate the Use Cases for
Generics and how Go solves them without Generics.

In this way we could:
1- Point any newcomer to this thread when he/she asks the same old
question again and no wasting more time in that.
2- Isolate the USE CASES that call for (or force) a Generics based
solution, one by one and identify:
 * Whether or not there are good enough solutions in Go right NOW,
with some sample of them.
 * If there is NOT a PROPER solution right now, or it is too complex,
ugly or gives bad performance or maintenance:
   * Would it be easily solvable (and worth) by adding an orthogonal
NON-generics feature to Go or not?

Who knows, we might find that generics always have good alternative
solutions! (or we may not)

andrey mirtchovski

unread,
Jun 30, 2012, 4:35:02 PM6/30/12
to slavomi...@gmail.com, golan...@googlegroups.com
> func memo(f func(int) int) func(int) int {

it's a bit contrived and probably a more elegant solution can be
found, but off the top of my head i came up with this:

http://play.golang.org/p/m-gH-U_Zws

add10 and addten can be combined into one, but are separate here for
illustrative purposes.

David Klaffenbach

unread,
Jun 30, 2012, 10:14:43 PM6/30/12
to golan...@googlegroups.com, slavomi...@gmail.com

David Klaffenbach

unread,
Jun 30, 2012, 10:17:52 PM6/30/12
to golan...@googlegroups.com, slavomi...@gmail.com
This is more telling: http://play.golang.org/p/YZlpwMze-2

I don't understand why this doesn't panic at runtime.

andrey mirtchovski

unread,
Jun 30, 2012, 10:21:05 PM6/30/12
to David Klaffenbach, golan...@googlegroups.com, slavomi...@gmail.com
> I don't understand why this doesn't panic at runtime.

because every time implements the empty interface. presumably in the
two functions I put there one would want to emit errors if they
encountered the incorrect type (that follows from he fact that they
can be combined).

this isn't type-checked generics. the code side-steps the type system
to gain a bit of generality at the expense of safety.

andrey mirtchovski

unread,
Jun 30, 2012, 10:22:23 PM6/30/12
to David Klaffenbach, golan...@googlegroups.com, slavomi...@gmail.com
> because every time implements the empty interface.

s/time/type/, sorry

David Klaffenbach

unread,
Jun 30, 2012, 11:53:35 PM6/30/12
to golan...@googlegroups.com, David Klaffenbach, slavomi...@gmail.com
I still don't understand.  It seems to me that f("eleven") (in line 36 of http://play.golang.org/p/YZlpwMze-2) should cause a call to add10("eleven") which should then call i.(int) with i being "eleven" and I expected the type assertion would fail.

What am I missing?


On Saturday, June 30, 2012 9:22:23 PM UTC-5, aam wrote:
> because every time implements the empty interface.

s/time/type/, sorry

andrey mirtchovski

unread,
Jul 1, 2012, 12:04:44 AM7/1/12
to David Klaffenbach, golan...@googlegroups.com, slavomi...@gmail.com
> I still don't understand. It seems to me that f("eleven") (in line 36 of
> http://play.golang.org/p/YZlpwMze-2) should cause a call to add10("eleven")
> which should then call i.(int) with i being "eleven" and I expected the type
> assertion would fail.
>
> What am I missing?

you're probably missing the type-check on line 18: if the argument is
_not_ an int the function returns it unchanged. you'll get an error if
you don't do the check on line 18. (nb: the same will happen in the
python memo function, where you have the duck typing I was trying to
emulate):


>>> z=memo(lambda x: x+10)
>>> z(10)
20
>>> z("test")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in wrapper
File "<stdin>", line 1, in <lambda>
TypeError: cannot concatenate 'str' and 'int' objects

David Klaffenbach

unread,
Jul 1, 2012, 12:18:33 AM7/1/12
to golan...@googlegroups.com, David Klaffenbach, slavomi...@gmail.com
Thanks, I was missing that, and if I comment out the if block I do get the panic.

Russel Winder

unread,
Jul 1, 2012, 1:05:54 AM7/1/12
to slavomi...@gmail.com, golan...@googlegroups.com
On Sat, 2012-06-30 at 12:43 -0700, slavomi...@gmail.com wrote:
> I would also add memoization to that list.
>
> Here's how it's done in Python:
>
> def memo(f):
> cache = {}

I suggest there should be an @wraps decorator on the nested function
wrapper.

> def wrapper(*args):
> try:
> res = cache[args]
> except KeyError:
> res = cache[args] = f(*args)
> return res
>
> return wrapper

Also, I suspect there should be a **kwargs in the parameter list of
wrapper, and as argument to the f call. As presented at the moment,
memo only deals with positional arguments and not with keyword
arguments.

--
Russel.
=============================================================================
Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel...@ekiga.net
41 Buckmaster Road m: +44 7770 465 077 xmpp: rus...@winder.org.uk
London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
signature.asc

Slavomir Kaslev

unread,
Jul 1, 2012, 1:56:36 AM7/1/12
to David Klaffenbach, golan...@googlegroups.com
I get it that Go embraces C's approach to generic programming. And I
mean that in a good way; I love C. As far as I understand it,
interface{} is void* with runtime reflection.

While that's simple and good enough, generics would be welcome at some point.
--
Slavomir Kaslev

Slavomir Kaslev

unread,
Jul 1, 2012, 1:48:20 AM7/1/12
to Russel Winder, golan...@googlegroups.com
Totally. I was keeping it simple as this a Go list and not everyone
would be comfortable with Python.
--
Slavomir Kaslev

Clifford Hammerschmidt

unread,
Jul 1, 2012, 1:39:43 PM7/1/12
to Russel Winder, slavomi...@gmail.com, golan...@googlegroups.com
The memo implementation that returns interface{} doesn't really solve the problem, since *every* caller will have to cast back to the original type to use it as the original type again.

-- 
Clifford Hammerschmidt, P.Eng.



On Sat, Jun 30, 2012 at 10:05 PM, Russel Winder <rus...@winder.org.uk> wrote:

steve wang

unread,
Jul 2, 2012, 1:40:30 AM7/2/12
to golan...@googlegroups.com
In my opinion, it's acceptable to cope with this problem outside the compiler with the technique which is already used in package "html/template".
In other words, the Go team can provide us with a set of offical templates in which standard algorithms are implemented and a tool with which we can compile the template into real go code. In this case, the automated code is easy to read and debug and maintain, and is also reliable. And we should be able to write our own template to implement our own business logic.
This technique is a bit old but practical. 

josvazg

unread,
Jul 2, 2012, 3:39:23 AM7/2/12
to golan...@googlegroups.com
Maybe I am wrong, but it seems to me that the Go core team is not to much fan of autogenerated code.

All Golang design decisions are quite well thought and render simple & orthogonal but powerful solutions to most problems. I would like to know why they seem to always prefer reflection (which sometimes has performance problems or makes code less typesafe or even less clear) or why is it they don't like automatic code generation. 

They sure have good reasons for that so I would like to hear them.

Paul Borman

unread,
Jul 2, 2012, 11:41:51 AM7/2/12
to josvazg, golan...@googlegroups.com
Go is focused on the programmer.  Fast compilations help programmers.  When you say "automatic code generation" I think you mean something like C++ templates (which are just sophisticated Macros).  These slow down compiles and bloat your code.  (And from my perspective, make your code much more difficult to read.)  See Russ' blog post at http://research.swtch.com/generic

    -Paul

Chandru

unread,
Jul 2, 2012, 1:36:57 PM7/2/12
to golang-nuts
The interesting thing about comments on Russ' post is that he does not address why Go cannot implement generics like C# does. Several posts mention it though. What are the technical difficulties in using the C# way?

--
Chandra Sekar.S

josvazg

unread,
Jul 3, 2012, 3:25:04 AM7/3/12
to golan...@googlegroups.com, josvazg
Yes, I new that one and know about Russ blog, that, as someone posted, it's a bit frozen, it hasn't been updated in a long time so we don't know what Russ thinks about all these now, if he has come up to some new revelation or what he thinks about C# approach ,etc.

I can agree 100% with Go core team main goal to avoid C++ template dependency problems and the like. WE all want our go code compile blazingly fast, as it does today...  or even faster if that were possible at all.

I was talking more in general about code generation. It is for sure a bad idea to have dependency-driven autogenerated code on your libraries, cause you open the "many hours a compile hell" upon you, but that does NOT cover all the uses cases for autogenerated code.

ORM-style like code autogeneration, for instance, is another case.  It can be done in YOUR package BEFORE compiling even started, while you are editing your source code. That is also branded (I think) as a bad Idea, and I was referring more to this.

Let me explain myself a little bit more. I have seen the database/sql approach to read Relational Values into Go variables, it is quite nice and I like it more than using DAO "mapper" patterns. This approach will probably eliminate the need to autogenerate most of your DAOs code but...

Will that be always the case?
Will it eliminate ALL your need to avoid repeating yourself in most your code?

Every time you find you have to write repetitive error prone code means that there is a way (without code autogeneration), that you can rethink or rewrite it so that you can avoid it at all?
In all cases?

On example. As my first learning go project I built a remotize package whose goal was to allow you to use Go's rpcs without you having to make your interfaces "ugly" nor forcing you to do the interface adaptor yourself if, for instance, you decided to remotize some type or interface afterwards.
So I guess the question is...
Why is this sort of thing a bad idea?

Paulo Pinto

unread,
Jul 3, 2012, 4:39:49 AM7/3/12
to golang-nuts
He also fails to address that Ada, Delphi and D have implemented
generics
with code expansion similar to C++, and yet when coupled with their
module
systems, they also have quite fast compile times.

--
Paulo

On Jul 2, 7:36 pm, Chandru <chandru...@gmail.com> wrote:
> The interesting thing about comments on Russ' post is that he does not
> address why Go cannot implement generics like C# does. Several posts
> mention it though. What are the technical difficulties in using the C# way?
>
> --
> Chandra Sekar.S
>
>
>
>
>
>
>
> On Mon, Jul 2, 2012 at 9:11 PM, Paul Borman <bor...@google.com> wrote:
> > Go is focused on the programmer.  Fast compilations help programmers.
> >  When you say "automatic code generation" I think you mean something like
> > C++ templates (which are just sophisticated Macros).  These slow down
> > compiles and bloat your code.  (And from my perspective, make your code
> > much more difficult to read.)  See Russ' blog post at
> >http://research.swtch.com/generic
>
> >     -Paul
>

Paul Borman

unread,
Jul 3, 2012, 11:04:05 AM7/3/12
to josvazg, golan...@googlegroups.com
The Go team has not said they are opposed to programs that generate Go code.  They have just said that the go tool is not the tool to use for that, use Make (or some other system).  Most projects do not need the complication and they are what the go tools is aimed at.

    -Paul

David Leimbach

unread,
Jul 3, 2012, 11:48:32 AM7/3/12
to golan...@googlegroups.com, josvazg


On Tuesday, July 3, 2012 8:04:05 AM UTC-7, Paul Borman wrote:
The Go team has not said they are opposed to programs that generate Go code.  They have just said that the go tool is not the tool to use for that, use Make (or some other system).  Most projects do not need the complication and they are what the go tools is aimed at.

    -Paul

But the go tools DO generate go code.  gofmt is a perfect example.  It reads go, creates a parse tree, then emits go code.
 
Why not a go templating system in go using techniques similar to gofmt?

Paul Borman

unread,
Jul 3, 2012, 12:15:22 PM7/3/12
to David Leimbach, golan...@googlegroups.com, josvazg
So my first sentence was "The Go team has not said they are opposed to programs that generate Go code."

There is a difference between the "go tools" and the "go tool".  The former is a collection of tools, including gofmt and cgo, the later is a specific tool that is used to build standard go programs (that do not require pre-compilation steps).

I think you are conflating two things.  There is nothing stopping you from making an external tool to create Go code to then compile.  Maybe it is not what you are suggesting, but I think most people who have suggested templates or such want the compiler to do it.  In so many words, a standard pre-processor (if not an outright change to the formal specification).   I can't find it off hand, but a standard pre-processor is something the Go team has argued against.  It annoys the heck out of me sometimes "oh, a macro would be so nice here" but I agree with them.

Uriel

unread,
Jul 3, 2012, 9:05:00 PM7/3/12
to josvazg, golan...@googlegroups.com
On Tue, Jul 3, 2012 at 9:25 AM, josvazg <jos...@gmail.com> wrote:
> Yes, I new that one and know about Russ blog, that, as someone posted, it's
> a bit frozen, it hasn't been updated in a long time so we don't know what
> Russ thinks about all these now,

Russ did answer a question about generics in a talk that he gave
recently, he included a transcript of the Q&A in:
http://research.swtch.com/gotour

And here is the specific question and answer about generics:

"Q. What about generics? How far off are they?

A. People have asked us about generics from day 1. The answer has
always been, and still is, that it’s something we’ve put a lot of
thought into, but we haven’t yet found an approach that we think is a
good fit for Go. We’ve talked to people who have been involved in the
design of generics in other languages, and they’ve almost universally
cautioned us not to rush into something unless we understand it very
well and are comfortable with the implications. We don’t want to do
something that we’ll be stuck with forever and regret.

Also, speaking for myself, I don’t miss generics when I write Go
programs. What’s there, having built-in support for arrays, slices,
and maps, seems to work very well.

Finally, we just made this promise about backwards compatibility with
the release of Go 1. If we did add some form of generics, my guess is
that some of the existing APIs would need to change, which can’t
happen until Go 2, which I think is probably years away."

> if he has come up to some new revelation or

The main "revelation" seems to be, and which most people actually
writing Go code seem to share, is that he doesn't miss generics.

There was even a question during the "Meet the Go team" at Google IO
asking to please keep generics out of the language, and I have seen
several people express similar opinions (but none from the Go team,
only from users, and I think it is a rather small minority, but is
important to note that not everyone believes generics are worth the
complexity they would add to the language).

Uriel

josvazg

unread,
Jul 4, 2012, 2:51:57 AM7/4/12
to golan...@googlegroups.com, josvazg
I read that one. I haven't had the time to watch the video in one go, though, I started the original one with those horrible sound problems and then I was able to watch parts of this one, but not sure I watch it all. But I read that question on the page.

I follow all golang team talks and slides I know about. I learn a lot from them and I really like how they explain things.

But in this particular case, there is not much new information on that answer, in my opinion.

I agree with Russ view's that Generics are overused most of the time and in Go you don't miss them so often, in most cases "generics needs" are container or type specification related. (I am tired of having to specify things like Map<String,Object> m=new HashMap<String,Object>(); over and over again...)

I also agree that Go should stay true to its goal to make a good simple  and powerful language by taking out more than taking in features. So yes, I quite understand that Russ should "rush" to generics ;-)

The more I think about this subject the more I believe we might be confronting the problem in the wrong way:
- Maybe we DON'T need generics at all.
- Maybe generics is just a NOT optimal but general solution to a set of different but related programming problems.
- Maybe we could identify those problems and give them other solutions WITHOUT generics.
(This is the reason I started this thread, although I admit I haven't got to any conclusion yet)

What do you think of this approach?

Jesse McNelis

unread,
Jul 4, 2012, 4:12:44 AM7/4/12
to David Leimbach, golan...@googlegroups.com, josvazg
On Wed, Jul 4, 2012 at 1:48 AM, David Leimbach <lei...@gmail.com> wrote:
> But the go tools DO generate go code. gofmt is a perfect example. It reads
> go, creates a parse tree, then emits go code.
>
> Why not a go templating system in go using techniques similar to gofmt?

I think keeping code generation tools out of the standard Go tool
chain helps discourage people from doing it just because they can.
The decision make your code generated becomes an annoyance because
users of your code need to build some other non-standard tool to build
your code.

If they added a templating system to the go tools then it would
essentially become part of the language and we'd immediately pull in
all the same problems that the C pre-processor creates.


--
=====================
http://jessta.id.au

Paulo Pinto

unread,
Jul 4, 2012, 4:22:08 AM7/4/12
to golang-nuts


On Jul 4, 8:51 am, josvazg <josv...@gmail.com> wrote:
> I read that one. I haven't had the time to watch the video in one go,
> though, I started the original one with those horrible sound problems and
> then I was able to watch parts of this one, but not sure I watch it all.
> But I read that question on the page.
>
> I follow all golang team talks and slides I know about. I learn a lot from
> them and I really like how they explain things.
>
> But in this particular case, there is not much new information on that
> answer, in my opinion.
>
> I agree with Russ view's that Generics are overused most of the time and in
> Go you don't miss them so often, in most cases "generics needs" are
> container or type specification related. (I am tired of having to specify
> things like Map<String,Object> m=new HashMap<String,Object>(); over and
> over again...)
>

This is Java specific.

The majority of languages that support generic programming don't
require you to type so much.

--
Paulo

Russel Winder

unread,
Jul 4, 2012, 5:28:05 AM7/4/12
to josvazg, golan...@googlegroups.com
On Tue, 2012-07-03 at 23:51 -0700, josvazg wrote:
[…]
> things like Map<String,Object> m=new HashMap<String,Object>(); over and
> over again...)

final Map<String,Object> m = new HashMap<>();

more likely. Arguably, generics in Java was a disastrous hack. Type
erasure undermines the whole point of generics. C# got this right by
reifying type parameters at the CLR level. Scala sort of reifies type
parameters using Manifests, though this should change for 2.10. Kotlin
and Ceylon reify type parameters by construction (as will Scala) since
the JVM gives no support.

Dynamic languages such as Python, Groovy, etc. have stuck to the
position of "heterogeneous type data containers are not evil". Obviously
though all type checking is at run time, with duck typing: if the object
responds to the messages sent when they are sent, then the object is of
the right type. Isn't the use of interface in Go the static typed
version of this: it isn't relevant what the construction type of the
object in the container is, as long as it responds to the right methods
then it is of the right type.

Given the interface mechanism, I have yet to be convinced that generics
are at all needed. What do generics add other than the imposition of
rigid homogeneity of construction type of contained objects. Is this
actually something useful or a left over fashion from the 1990s and
2000s?
signature.asc

Matt Joiner

unread,
Jul 4, 2012, 8:42:05 AM7/4/12
to Russel Winder, josvazg, golan...@googlegroups.com
Personally I think that type erasure
(http://en.wikipedia.org/wiki/Type_erasure) is the best approach here.
Generics are limited to single free values, and reuse the chan style:

chan int
MyType int

If you want to nest generic types they're just built up like so

List MyType int

Which is a List of Mytype int, whatever that may mean. The generic
type is compiled once, with all instances of the free type implemented
as interface{}. However at compile T is used as what it's known to
actually represent, no casting required. For instance for the List
example (actual syntax really doesn't matter much):

generic List struct {
Append(elem type)
PopFront() type
Insert(index int, elem type)
// etc.
}

In the machine code, this is just compiled once with "type" being
replace with "interface{}", so it's as tho I had written:

type List struct {
Append(elem interface{})
PopFront() interface{}
Insert(index int, elem interface{})
// etc.
}

There'd be some flag on interface{} values that are parametric at compile time.

However at compile time, "type" in the generic definition is replace
by whatever parametric type is given in the declaration:

List int

Would automatically cast the interface{} to int. After compile time
type checking, all this disappears.

I think it's worth mentioning that nobody here is so sick as to
believe that generics are desirable for performance reasons in Go, but
rather for better expression and type safety. I also don't think
anyone requires more than a single parametric type, this covers all
the existing uses of generics in Go, that is slices and channels, all
existing containers. I also think its straightfoward to reason about
parametric types to any necessary depth with the chan style
declaration.

I tried to explain a similar idea on reddit, it may augment my pitiful
explanation above:
http://www.reddit.com/r/golang/comments/vldyv/less_is_exponentially_more_rob_pike_on_the/c55q2af

chris dollin

unread,
Jul 4, 2012, 9:05:13 AM7/4/12
to Matt Joiner, Russel Winder, josvazg, golan...@googlegroups.com
On 4 July 2012 13:42, Matt Joiner <anac...@gmail.com> wrote:

> I also don't think
> anyone requires more than a single parametric type, this covers all
> the existing uses of generics in Go, that is slices and channels, all
> existing containers

Maps and map-like things want to paramterised types. I've written
parameterised classes in java with 10+ cross-referring types; admittedly
this was mostly a "will this work", but it did work, and it wasn't an
unreasonable idea.

[Details lost in the mists of time & job changes, but:

Consider a reusable parser P for some language L. Different uses of
the same P do different things on recognising the syntactic structures
of L. To capture these things, when some construct A with components
B and C is recognised, a function (method, whatever) ABC is called passing
in the values of B and C and returning the resulting value of A. In different
uses of P, the type of A may differ, as may that of B and C, but the function
ABC is always of type (type of B), (type of C) -> type of A.

P is parameterised on a bunch of methods (functions, whatever) which
match the abstract syntax of L. One such bunch may construct an
abstract syntax tree for the particular term of L. Another such bunch
may produce the value of that term (if L is say a functional programming
language) without (visible) construction of such a tree. Another might,
say, count uses of operators or accumulate idetifiers. The point is that
the parser P is deliberately insensitive to those details; the types associated
with lexical items and grammar fragments /do not matter/ to P so long as
they are correctly combined according to the ABC functions.

I don't think you can do this using Go-style interfaces. (Note that "do this"
includes "and the compiler spots your stupid mistakes".)
]

Chris

--
Chris "allusive" Dollin

Matt Joiner

unread,
Jul 4, 2012, 10:25:56 AM7/4/12
to chris dollin, Russel Winder, josvazg, golan...@googlegroups.com
I didn't think of maps, that really muddies the waters.

Clifford Hammerschmidt

unread,
Jul 6, 2012, 12:17:45 AM7/6/12
to Matt Joiner, chris dollin, Russel Winder, josvazg, golan...@googlegroups.com
re: c++ template hell, I complete agree that it should be avoided. generics != templates. We don't need a Turing complete language for anonymous types in an opaque manner. C#'s style of generics are a reasonable balance.

-- 
Clifford Hammerschmidt, P.Eng.

josvazg

unread,
Jul 6, 2012, 3:11:01 AM7/6/12
to golan...@googlegroups.com, Russel Winder, josvazg
"I think it's worth mentioning that nobody here is so sick as to 
believe that generics are desirable for performance reasons in Go, but 
rather for better expression and type safety."

I am SICK , sorry.
Not that I desire Generics, but I DO want something that, in the cases you need that kind speed, you can do without interface invoking costs, specially on primitive types.

One example it the Sort package. The interface is an elegant solution, and its speed is probably fine for most cases. I believe that for non primitive types it probably can't get much better than that.

BUT, for primitive types, the same algorithm, copied exactly the same EXCEPT changing Less() and Swap() for the inline implementation for int or float or whatever the primitive type renders TWICE the performance. Sometime you may need that, and if you do, I see just TWO possibilities:

1) The go team make magic in-lining on the compiler side; I don't think this is much realistic, I can't see how can they achieve interface in-lining unless parts of the program recompiles itself on runtime like a kind of JIT os something like that.

2) You repeat yourself for each an every type you need FULL speed sorting. (UNLESS you had some tool, even outside the language, before you even compile anything that is assisting you)

David Roundy

unread,
Jul 8, 2012, 9:26:10 AM7/8/12
to Uriel, josvazg, golan...@googlegroups.com
On Tue, Jul 3, 2012 at 6:05 PM, Uriel <ur...@berlinblue.org> wrote:
> Also, speaking for myself, I don’t miss generics when I write Go
> programs. What’s there, having built-in support for arrays, slices,
> and maps, seems to work very well.
...
>> if he has come up to some new revelation or
>
> The main "revelation" seems to be, and which most people actually
> writing Go code seem to share, is that he doesn't miss generics.

I would assert that this is false. People don't miss template or
other sorts of generics, but they've missed generics enough that
generic functions have been added to the language itself. If we
didn't miss generics, we wouldn't have the copy and append functions.
It's just that the current approach to generics is: add the generic
functions to the language definition itself. It's not good for rapid
prototyping of generic functions, but does ensure that they are
bug-free.

Perhaps Russ doesn't miss generics when programming in go because he
is able to write generic functions when he wants to do so! :)

David

Paulo Pinto

unread,
Jul 8, 2012, 10:16:16 AM7/8/12
to golang-nuts


On Jul 6, 11:28 am, Noel Grandin <noelgran...@gmail.com> wrote:
> On Friday, July 6, 2012 9:11:01 AM UTC+2, josvazg wrote:
>
> > One example it the Sort package. The interface is an elegant solution, and
> > its speed is probably fine for most cases. I believe that for non primitive
> > types it probably can't get much better than that.
>
> So copy the code.
> It's like Java - for the handful of cases where using primitive types
> really makes a difference, you cut and paste the code 10 times for the
> different primitive types.
> It's really not that big a deal, given how infrequently it really gives you
> a performance boost.

This advice is so 1990.

Thomas Bushnell, BSG

unread,
Jul 8, 2012, 1:05:05 PM7/8/12
to David Roundy, Uriel, josvazg, golan...@googlegroups.com
On Sun, Jul 8, 2012 at 6:26 AM, David Roundy <rou...@physics.oregonstate.edu> wrote:
Perhaps Russ doesn't miss generics when programming in go because he
is able to write generic functions when he wants to do so!  :)

Well, since Go 1.0 isn't changing, he can't add more by adding them to the compiler.

So if you're right, he'll agree by the time it's time for Go 2.0. If he's right, then we'll continue as we are.

Thomas
 

Kevin Gillette

unread,
Jul 16, 2012, 12:02:15 PM7/16/12
to golan...@googlegroups.com, Russel Winder, josvazg
On Friday, July 6, 2012 1:11:01 AM UTC-6, josvazg wrote:
Not that I desire Generics, but I DO want something that, in the cases you need that kind speed, you can do without interface invoking costs, specially on primitive types.

One example it the Sort package. The interface is an elegant solution, and its speed is probably fine for most cases. I believe that for non primitive types it probably can't get much better than that.

Yeah, as far as I can reason, proper generics in Go would only have two use cases: 1) operators. 2) range iteration.

In the case of #1, this would include channel ops on unknown channel types. In the case of #2, this could allow channel-style value range iteration over slices and such, if the generic type wasn't limited to slices (though this would mean passing a map value through that generic func would result in value-only iteration too, which is usually not desirable).

The problem is, you have to chose one of two tradeoffs: 1) compile time expansion (duplication), 2) attempt to do it at run-time.

The reasons people tend to desire generics? Two: 1) speed. 2) convenience (using the + operator on operands that happen to have matching numeric/string types).

For tradeoff #2 (runtime), you lose speed if you choose runtime-via-reflection. This would be tightly optimized internal/limited reflection with some compiler-provided partial-prevalidation/hints, but you'd still be at least ~2x as slow as something hand-written.  The other alternative is JIT code generation a la LLVM (though it's gnarly enough territory that I doubt anyone would ever want to implement/integrate it -- thus must implementations would opt for either compile-time or reflected-runtime).

All that said, I've never seen a Go application (package main), "in the wild", that would either need or truly benefit from generics (for either of the use cases or either of the desires). It's mostly library authors that could use generics (and lots of those libraries are just polished versions of application-specific code the author thought would be publicly useful).  Besides which, libraries *can* have a lot of reasonably code since the application programmer doesn't see that or care, so for many, it's still a non-issue :)

Footnote: the problem of implementing generics could be made somewhat simpler by adding tagged unions to the language, i.e.:

type Numeric union { int, int8, ....... uint64, complex64, complex128 }

func Sum(s []Numeric) Numeric {
var sum Numeric
for _, v := range s { sum += v }
return sum
}

The compiler (not the runtime) could require all interactions between two or more union values (that don't type-assert) to have the same underlying type (in this case, all Numeric references would evaluate to, i.e., int or complex64, but no mismatch of related input/output without an assert (usually in combination with an explicit conversion also). One issue is that this example is actually a symbolic union rather than a memory-layout union. If you got rid of the type def, and just used generic instead of Numeric, maybe a compiler could deterministically work out all transitive relationships (even if that task is done, generics are still hard, and there are a lot of problems to overcome, including semantic ambiguities that don't come up in an example as simple as the above). The above still also doesn't address generic iteration.


----------


Change of subject: in another generics thread (which is now too old to post in), the question was raised about how to write general Min/Max functions simply in Go. Some reference to a Haskell example lead to the suggestion of an Ord interface.

I assert that there's an exceptionally idiomatic way to handle these in Go -- piggy back one of the methods in sort.Interface: Less (well, and Len)

type LenLesser interface {
Len() int
Less(i, j int) bool
}

func Min(data LenLesser) int {
len := data.Len()
if len == 0 {
return -1
}
var min int
for i := 1; i < len; i++ {
if data.Less(i, min) {
min = i
}
}
return min
}

func Max(data LenLesser) int {
len := data.Len()
if len == 0 {
return -1
}
var max int
for i := 1; i < len; i++ {
if data.Less(max, i) {
max = i
}
}
return max
}

Now anything that implements sort.Interface (or at least those two methods) can be passed to Min and Max, and is slightly more time efficient (read-only, smaller constant factor) than running sort.Sort and pulling the first or last element.

A working example is at: <http://play.golang.org/p/Wh8IARMJBz>. Note that both functions return the earliest min/max. This is usually fine for most applications (where 'equality' uses the same definition as Go) -- other apps would also have issues with using the sort package anyway (when sort stability matters).

Robert Johnstone

unread,
Jul 16, 2012, 1:13:03 PM7/16/12
to golan...@googlegroups.com, Russel Winder, josvazg
Your sample has survivor bias.  Those applications that needed generics were stopped, and the programmers moved on to different tools (if they ever even started).  The bias may or may not be significant, but given the number of demands for generics, certainly some gophers are missing them.

Kevin Gillette

unread,
Jul 16, 2012, 1:35:43 PM7/16/12
to golan...@googlegroups.com, Russel Winder, josvazg
Fair enough :) Perhaps I'm subconsciously trying to bias gophers towards using existing methodological tunnels before they give up and raise the pointy red flag of language extension. Many, though not all, of these gophers will find an adequate remedy to their problem-space.

Jonathan Amsterdam

unread,
Jul 16, 2012, 4:50:15 PM7/16/12
to golan...@googlegroups.com, Russel Winder, josvazg
All that said, I've never seen a Go application (package main), "in the wild", that would either need or truly benefit from generics...

It's possible that no single application would benefit from generics, but that the set of applications as a whole would. E.g. one app implements a linked list of int, another a linked list of string, etc. 

Clifford Hammerschmidt

unread,
Jul 19, 2012, 7:43:03 PM7/19/12
to Jonathan Amsterdam, golan...@googlegroups.com, Russel Winder, josvazg
It's also because we need more than just generics to really make use of generics, e.g.:

func (this []T) Where<T>(f func(T) bool) []T {
for _,i := range this { if f(i) { yield i } }
}
odd := x => (x%2)==1
odds := []int{1,2,3,4}.Where(odd)

Short form lamdba, yield, extension methods and generics are the building blocks of LINQ in C#. I use them everyday (and often write my own) and sorely miss them in Go. Robert's point about survivor bias definitely applies in my case as I've nearly stopped using Go because it's missing these features.  

-- 
Clifford Hammerschmidt, P.Eng.

Steven Blenkinsop

unread,
Jul 20, 2012, 1:33:36 AM7/20/12
to Clifford Hammerschmidt, Jonathan Amsterdam, golan...@googlegroups.com, Russel Winder, josvazg
type Ts []T
func (ts Ts) Where(f func(T) bool) (out Ts) {

for _,i := range this { if f(i) { out = append(out, i) } }
}
odd := func(x T) bool { return x%2 == 1 }
odds := Ts{1,2,3,4}.Where(odd)

I can see lack of generics making this problematic, but the rest is all minor syntactic choices. Maybe the closure's a tad hefty, but not outrageously so. Just enough to discourage nesting it, which can be an iffy practice in many cases anyways.

Kevin Gillette

unread,
Jul 20, 2012, 8:39:01 AM7/20/12
to golan...@googlegroups.com, Jonathan Amsterdam, Russel Winder, josvazg
Besides which, Go's 'yield' is the channel send operation. Granted, it's not a 1:1 replacement, but then, most things in go don't replace (even same-named concepts/structures) from other languages in a 1:1 fashion.

It's feasible to do something entirely LINQ-like using method chaining (methods that return the receiver) and reflection to construct queries -- the solution demonstrates Go's general stance on where it stands on language "high levelness" for these things -- keep the application programmer aware of the memory layout and algorithms that are being used (I suspect this is also part of the reason that no language-standard 'magic methods' for use in 'generic' for range loops have been defined -- the language itself won't cross the boundary into treating any methods as special -- once it does, there'd be an avalanche of magic methods, backwards incompatibilities, and unreadable code).

Ben L.

unread,
Jul 20, 2012, 10:26:33 AM7/20/12
to golan...@googlegroups.com
Here's a use case:

I have numerous types and funcs like this one:

func (idx *index_element_string) less(in interface{}) bool {
        if s, ok := in.(string); ok {
                return idx._element < s
        }
        return false
}

In each func, the only thing that changes is the type of the type assertion. If I could write the code once and then define types with something like type index_element_string index_element_generic(string), it would make my code much easier to read while still maintaining the strong-typedness of the language.

Maybe this is something for source-to-source compilers, but I'd like it to be actual valid syntax.

DisposaBoy

unread,
Jul 20, 2012, 11:41:03 AM7/20/12
to golan...@googlegroups.com
If you know that `in` is always the same type as idx._element (that's the impression I get from your message) then why not write:

func (idx *index_element_string) less(in interface{}) bool {
        return idx._element < in.(string)
}

if someone passed the wrong type then I'd argue that that's a programmer error and you shouldn't be hiding the bug
 

Clifford Hammerschmidt

unread,
Jul 20, 2012, 2:34:33 PM7/20/12
to Kevin Gillette, golan...@googlegroups.com, Jonathan Amsterdam, Russel Winder, josvazg
Using a channel would require a fair amount more boiler-plating and make chaining calls pretty hard. It's not the same as yield. Yield is about lazy evaluation, not about queuing.

I'm guessing you're suggesting something like:

func Where(source chan int, f func(int) bool, destination chan int) {
  for i := range source {
    destination <- f(i)
  }
}
go Where(source, f, destination)
source <- ...

The benefit of yield comes when you chain functions and when you partially evaluate the slice:

func Repeat<T>(t T) : []T { for { yield t } } // note the infinite loop
func (source []T) Apply<T,U>(f func(t T) U) []U { for i := range source { yield f(i) } }
func (source []T) Take<T>(n int) : []T { for i:=0;i<n;++i { yield source[i] } }

i := 1
eg := Repeat(1).Apply(x => { i+=x; return i }).Apply(x=>x.String()).Take(5)

Maybe you can write the above in Go in an as readable fashion and I'm just missing the knowledge to do it.

-- 
Clifford Hammerschmidt, P.Eng.

Jonathan Amsterdam

unread,
Jul 20, 2012, 2:54:43 PM7/20/12
to Clifford Hammerschmidt, Kevin Gillette, golan...@googlegroups.com, Russel Winder, josvazg
Eliding some of the generic syntax for clarity:

type Seq[T] chan T


func SeqFunc(f func(Seq[T])) Seq[T]} {
    c := Seq[T]{make(chan T)}
    go f(c)
   return c
}

func Repeat(t T) Seq[T] { 
    return SeqFunc(func (c Seq[T]) { c <- t }) 
}

func (source Seq[T]) Apply(f func(t T) U) Seq[U] {
    return SeqFunc(func (c Seq[U]) {  for s := range source { c <- f(s) } })
}

func (source Seq[T]) Take(n int) Seq[T] {
    return SeqFunc(func (c Seq[T]) { for i := 0; i < n; i++ { c <- <-source }; close(c) })
}

func (source Seq[T]) ToSlice() (a []T) {
    for s := range source { a = append(a, s) }
}

i := 1
eg := Repeat(1).Apply(func (x int) int { i += x; return i }).Apply(func (x int) string { return strconv.Itoa(x) }).Take(5).ToSlice()

Clifford Hammerschmidt

unread,
Jul 20, 2012, 6:48:27 PM7/20/12
to Jonathan Amsterdam, Kevin Gillette, golan...@googlegroups.com, Russel Winder, josvazg
close, but it deadlocks when run. (And the ugliness of the non-generic version is a good example of why we want generics.)

package main
import (
 "fmt"
 "strconv"
)

type SeqInt chan int
type SeqString chan string

func SeqIntFunc(f func(SeqInt)) SeqInt {
    c := SeqInt(make(chan int))
    go f(c)
   return c
}

func SeqStringFunc(f func(SeqString)) SeqString {
    c := SeqString(make(chan string))
    go f(c)
   return c
}

func Repeat(t int) SeqInt { 
    return SeqIntFunc(func (c SeqInt) { c <- t }) 
}

func (source SeqInt) ApplyIntInt(f func(t int) int) SeqInt {
    return SeqIntFunc(func (c SeqInt) {  for s := range source { c <- f(s) } })
}

func (source SeqInt) ApplyIntString(f func(t int) string) SeqString {
    return SeqStringFunc(func (c SeqString) {  for s := range source { c <- f(s) } })
}

func (source SeqString) Take(n int) SeqString {
    return SeqStringFunc(func (c SeqString) { for i := 0; i < n; i++ { c <- <-source }; close(c) })
}

func (source SeqString) ToSlice() (a []string) {
    for s := range source { a = append(a, s) }
return;
}


func main() {
i := 1
eg := Repeat(1).ApplyIntInt(func (x int) int { i += x; return i }).ApplyIntString(func (x int) string { return strconv.Itoa(x) }).Take(5).ToSlice()
fmt.Print(eg)
}



-- 
Clifford Hammerschmidt, P.Eng.

Clifford Hammerschmidt

unread,
Jul 20, 2012, 7:41:11 PM7/20/12
to Jonathan Amsterdam, Kevin Gillette, golan...@googlegroups.com, Russel Winder, josvazg

func Repeat(t int) SeqInt { 
    return SeqIntFunc(func (c SeqInt) { for { c <- t } } ) 
}

fixes the deadlock...

but it also shows a difference between yield and goroutines... goroutines will fill the channel (up to the buffer amount) with the repeated value; basically it pushes the values in. In the yield model the values are pulled as needed (by resuming the computation in the callers thread).

goroutines potentially introduce concurrency issues, since the goroutine pushing values into the channel runs asynchronously.

the yield model doesn't introduce anything that runs asynchronously.

-- 
Clifford Hammerschmidt, P.Eng.

Jonathan Amsterdam

unread,
Jul 20, 2012, 8:09:55 PM7/20/12
to Clifford Hammerschmidt, Kevin Gillette, golan...@googlegroups.com, Russel Winder, josvazg
Thanks for fixing the bug.

I think with synchronous (unbuffered) channels the computations will be similar. I don't know the exact semantics of yield, but in the Go Repeat, for example, the only thing that will happen in the goroutine is the  (trivial) evaluation of t. The channel send won't happen until the receiver "asks" for the value by arriving at the channel read. Yes, there is concurrency, but only in the evaluation of the args to channel sends.

The Go model seems more general, since by adding buffers to the channels you can increase concurrency.

Kevin Gillette

unread,
Jul 20, 2012, 10:14:00 PM7/20/12
to golan...@googlegroups.com
Go channels are a fair replacement for all uses of yield in the theoretical sense, though -- whether or not it's fast in yield-like use cases is entirely implementation dependent - a complier that detects non-escaping, unbuffered channel based parent/child iteration could specialize the compiled output to have yield-like efficiency (using lockless cooperative scheduling or even messing the inlined function into the parent loop)

Kyle Lemons

unread,
Aug 10, 2012, 6:28:38 PM8/10/12
to djhar...@gmail.com, golan...@googlegroups.com
On Fri, Aug 10, 2012 at 2:41 PM, <djhar...@gmail.com> wrote:
I'm currently hitting stumbling blocks with the lack of generics in Go after hitting some issues in this SO question http://stackoverflow.com/questions/11908074/enforcing-type-in-generic-code-with-empty-interfaces

A lot of code in the book I'm reading uses core ADTs like Queue
Use a slice.
 
Stack
Use a slice.
 
Bag
Use a slice.
 
and so on that are containers that utilize generics to make the code concise and compact. 

I'm having trouble trying to work out how to translate these effectively to Go without having to write lots and lots of code that essentially does the same thing. 

Just write them using the usual append and slice functions.  You will thank yourself later.

var strs []string
strs = append(strs, "test")
fmt.Println(len(strs))

is much clearer than

var strs Bag<string>
strs.Put("test")
fmt.Println(strs.Length())

I'm just wondering if anyone has experienced anything similar to this in their code (e.g. a generic Stack or Queue ADT) and what they did to get around it. 

On Friday, April 20, 2012 11:05:15 AM UTC+1, josvazg wrote:
This is NOT yet another "I want generics in Go" or "why Go doesn't
have generics?" post.

In fact, on the contrary, the idea is to enumerate the Use Cases for
Generics and how Go solves them without Generics.

In this way we could:
1- Point any newcomer to this thread when he/she asks the same old
question again and no wasting more time in that.
2- Isolate the USE CASES that call for (or force) a Generics based
solution, one by one and identify:
 * Whether or not there are good enough solutions in Go right NOW,
with some sample of them.
 * If there is NOT a PROPER solution right now, or it is too complex,
ugly or gives bad performance or maintenance:
   * Would it be easily solvable (and worth) by adding an orthogonal
NON-generics feature to Go or not?

Who knows, we might find that generics always have good alternative
solutions! (or we may not)

Andy Balholm

unread,
Aug 11, 2012, 12:38:01 PM8/11/12
to golan...@googlegroups.com, djhar...@gmail.com
Kyle's point is that you don't _need_ to create a new data type. You can just use a slice, without wrapping it in a new data type and then wishing you had an automatic way to wrap all possible slices at the same time.

Rémy Oudompheng

unread,
Aug 12, 2012, 7:17:56 AM8/12/12
to djhar...@gmail.com, golan...@googlegroups.com
On 2012/8/12 <djhar...@gmail.com> wrote:
> I don't see how duplicating code or doing runtime type assertions is a
> better solution to generics to be honest.

It is not a solution, and not a "better solution" either. It just the
natural consequence of the non-existence of generics in Go. You will
be able to write generic code in Go when it becomes possible. For the
moment, it is not possible.

Use interfaces where applicable, and where not applicable, use what is
possible and simplest to write (using reflection to emulate generics
is not "simplest to write").

Rémy.

Jan Mercl

unread,
Aug 12, 2012, 11:01:45 AM8/12/12
to djhar...@gmail.com, golan...@googlegroups.com
On Sun, Aug 12, 2012 at 1:12 PM, <djhar...@gmail.com> wrote:
But even just using slices I still need to duplicate code to work with different types. That's the problem I'm trying to get across. A stack is a pretty fundamental computer science concept and even just with slices, you'll need to reimplement push/pop for each individual slice type, wether it be []int, []string,[]byte etc.

I don't think it's so bad. A typical stack of T would be half invisible somewhere like:

    s := []T

And than usually push is inlined:

    s = append(s, item)

as is pop:

    if n := len(s)-1; n >= 0 {
        item, s = s[n], s[:n]
        // process item
    }
 
Yes you can use a bit of reflection/casting but this is deferring the type checking to the runtime, and thus ultimately to the developer.

It's possible to divide by substraction and multiply by addition - but why to do it?

If it's about a line or two (http://code.google.com/p/go-wiki/wiki/SliceTricks) then it's not a real issue IMO.

-j

Clifford Hammerschmidt

unread,
Aug 16, 2012, 1:42:38 PM8/16/12
to Jan Mercl, djhar...@gmail.com, golan...@googlegroups.com
Jan,

What about uses for slices that require adherence to a convention. Go is rather famous for what it doesn't allow; what if I want the same thing for my data usage pattern? Exposing a slice gives the consumer the ability to violate conventions that I want to enforce on the data because the user of the data is free to use anything that operates on a slice, not just the functions I want to provide.

If I wrap the slice in an interface to restrict its usage I immediately hit the need to re-write that interface multiple times or to use interface{} and force casting/type assertions/plumbing onto the user.

For something less trivial, try writing a  priority queue, such that:
- The queue holds one specific type of data only (homogeneous)
- The queue can use one specific type of priority (comparable, homogeneous)
- The user of the queue decides on the two types above
- The user doesn't have to use casts or type assertions
- The user doesn't have to wrap or alter their data type
- The user does have to provide a comparable priority type, and int,float,etc. should all work out of the box.
- If the user breaks homogeneity the code doesn't even compile

With constrainable generics I can easily do the above as:

type PriorityQueue<TD,TP:IComparible> interface {
  Enqueue(TD,TP) Error
  Dequeue() (TD, TP, Error)
}

with go as it currently stands I can do something like (totally untested):

package pq

import (
    "error",
    "reflect"
)

type Comparible interface {
    Less(interface{}) bool
    Equal(interface{}) bool
}

// this has to be done for all native types: int, uint, float and thier bit count versions
func (a int) Less(b interface{}) bool {
    bi, ok := b.(int)
    if !ok { panic Error.New("type mismatch" }
    return a<b;
}

func (a int) Equal(b interface{}) bool {
    bi, ok := b.(int)
    if !ok { panic Error.New("type mismatch" }
    return a==b;
}


type PriorityQueue interface {
    Enqueue(interface{}, Comparible)
    Dequeue(*interface{}, *Comparible)
}

type pair struct {
    entry interface{}
    priority Comparible
}

type pq struct {
    dt Type
    ct Type
    entries pair[]
}

func New(dt Type, ct Type) PriorityQueue {
    return &pq{dt,ct,make(pair[])}
}

func (this *pq) Enqueue(data interface{}, priority Comparible) Error {
    if this.dt != reflect.TypeOf(data) { return Error.New("data type mismatch") }
    if this.pt != reflect.TypeOf(priority) { return Error.New("priority type mismatch") }
    ...
    // add data priority to this.entries
}

func (this *pq) Dequeue(data *interface{}, priority *Comparible) Error {
    if this.dt != reflect.TypeOf(*data) { return Error.New("data type mismatch") }
    if this.pt != reflect.TypeOf(*priority) { return Error.New("priority type mismatch") }
    ...
    // fill in data and priority with the correct entry from this.entries, removing the entry
}

Which enforces the type homogeneity rules at runtime and not at compile time.

Is there a way to avoid the runtime type checks?

-- 
Clifford Hammerschmidt, P.Eng.

Uriel

unread,
Aug 16, 2012, 4:21:50 PM8/16/12
to David Roundy, josvazg, golan...@googlegroups.com
On Sun, Jul 8, 2012 at 3:26 PM, David Roundy
<rou...@physics.oregonstate.edu> wrote:
> On Tue, Jul 3, 2012 at 6:05 PM, Uriel <ur...@berlinblue.org> wrote:
>> Also, speaking for myself, I don’t miss generics when I write Go
>> programs. What’s there, having built-in support for arrays, slices,
>> and maps, seems to work very well.
> ...
>>> if he has come up to some new revelation or
>>
>> The main "revelation" seems to be, and which most people actually
>> writing Go code seem to share, is that he doesn't miss generics.
>
> I would assert that this is false. People don't miss template or
> other sorts of generics, but they've missed generics enough that
> generic functions have been added to the language itself. If we
> didn't miss generics, we wouldn't have the copy and append functions.

I think this is descending into a rhetorical argument, but Go does
have copy() and append(), so it is not possible to 'miss' them. Go
also has + and - and it doesn't have operator overloading, and just
because some operators are overloaded doesn't mean Go programmers miss
operator overloading.


> It's just that the current approach to generics is: add the generic
> functions to the language definition itself. It's not good for rapid
> prototyping of generic functions, but does ensure that they are
> bug-free.
>
> Perhaps Russ doesn't miss generics when programming in go because he
> is able to write generic functions when he wants to do so! :)

This is not really fair, there was a consensus that append() added
something valuable to the language, if you have any similar
suggestions I'd like to hear it, append() alone obsoleted most of the
few usages people had container/*, since append() was added, I have
yet to find any code that really needs container/*, if Go had generics
and container/* took advantage of this, very little real world Go code
would benefit.

Uriel

Uriel

unread,
Aug 16, 2012, 4:22:31 PM8/16/12
to Paulo Pinto, golang-nuts
On Sun, Jul 8, 2012 at 4:16 PM, Paulo Pinto <paulo....@gmail.com> wrote:
> This advice is so 1990.

Good advice ages well.

Uriel

unread,
Aug 16, 2012, 4:44:10 PM8/16/12
to Robert Johnstone, golan...@googlegroups.com, Russel Winder, josvazg
On Mon, Jul 16, 2012 at 7:13 PM, Robert Johnstone
<r.w.jo...@gmail.com> wrote:
> Your sample has survivor bias.

I admit this might true.

> Those applications that needed generics were stopped, and the programmers moved on to different tools

I have not heard of any such application, I'd be happy to hear about
examples of this happening.

Most discussions about generics tend to be very abstract and very much
lacking in real world examples of real Go projects where there is a
big need for them.

> (if they ever even started).

This might be the case, but doesn't prove much, it is difficult to
know if Go could not have provided some solution to their needs if
they didn't even try.

> The bias may or may not be significant, but given the number of
> demands for generics, certainly some gophers are missing them.

The demands for generics are mostly from people that have not used Go
much (or more often, not at all), again there might be selection bias,
but there is also plenty of people using Go for all kinds of projects
and they don't seem to think it is an issue.

People also often forget that both C and Java didn't have generics for
a long time (yes, you can hack stuff up with the C preprocessor, but
people have built similar tools for Go, and they have been all
abandoned because, specially after append() was added, almost nobody
found them all that useful.)

Also there seems to be very little consensus about what kind of
generics Go should have and how to work out the trade offs involved,
nobody so far has provided a good answer to this:
http://research.swtch.com/generic

(And all the people saying C# has the answer, you might want to check
this post by one of the .NET team at MS:
http://www.bluebytesoftware.com/blog/2011/10/23/OnGenericsAndSomeOfTheAssociatedOverheads.aspx
there are always tradeoffs and costs, there is no free lunch.)

So far nobody has:

1) shown there is any overwhelming need for generics in Go

2) has proposed a design that makes trade offs that please most people
asking for generics

Also remember that there won't be any major language changes until Go
2, that is not even in the planning stages, precisely because the Go
designers want more experience actually using the current language
before considering any such changes.

Instead of this endless and repetitive discussions about generics it
would be much better if people actually went and built projects using
the language as it stands, and then, in a year or two, armed with
experience and evidence, we can think of applying what we have learned
to Go 2.

So, I very strongly suggest: lets stop this flamewars, lets go write
code, and come back to this topic if/when Go 2 starts to be
considered, until then, it is a waste of time.

Uriel

Rémy Oudompheng

unread,
Aug 16, 2012, 5:05:14 PM8/16/12
to Clifford Hammerschmidt, Jan Mercl, djhar...@gmail.com, golan...@googlegroups.com
On 2012/8/16 Clifford Hammerschmidt <tangl...@gmail.com> wrote:
> For something less trivial, try writing a priority queue, such that:
> - The queue holds one specific type of data only (homogeneous)
> - The queue can use one specific type of priority (comparable, homogeneous)
> - The user of the queue decides on the two types above
> - The user doesn't have to use casts or type assertions
> - The user doesn't have to wrap or alter their data type
> - The user does have to provide a comparable priority type, and
> int,float,etc. should all work out of the box.
> - If the user breaks homogeneity the code doesn't even compile
>
> With constrainable generics I can easily do the above as:
>
> type PriorityQueue<TD,TP:IComparible> interface {
> Enqueue(TD,TP) Error
> Dequeue() (TD, TP, Error)
> }
>
> with go as it currently stands I can do something like (totally untested):

Your word "easily" hides many things:
* what is IComparable and what does it mean?
* what is a constrainable generic and what does it mean?
* what are the syntax and rules the generics must follow (your set of
rules must be coherent, allow the implementation of the said heap and
fit in less than two computer screens)
* how do you implement this in the compiler ?
* how do you implement this in the build system ?

Rémy.

Clifford Hammerschmidt

unread,
Aug 16, 2012, 5:50:24 PM8/16/12
to Rémy Oudompheng, Jan Mercl, djhar...@gmail.com, golan...@googlegroups.com
True enough, I'm used C#'s rules.

the C# version is:

interface IComparable
{
  bool Less(IComparable other);
  bool Equal(IComparable other);
}

interface IPriorityQueue<TD,TP> where TP:IComparable
{
  void Enqueue(TD data, TP priority);
  Tuple<TD,TP> Dequeue();
}

(Errors would be thrown as exceptions)

A "constrainable generic" is the ability to require the type provided adhere to a specific interface. (c# also support other constraints like having a default ctor.) By using a generic for TP we ensure the type used is consistently the same implementer of IComparable rather than any implementer of IComparable.

Limiting the rules to two computer screens is a bit of an arbitrary requirement. I'm not saying it's easy to create the rules or build the result, just that generics do make this style of code easier, and examples of such systems already exist (C# for instance). Yes, those systems have trade offs, but on the whole the prevent worse code (using reflect, etc.) from being written. Repeated saying that this style isn't idiomatic doesn't change that several people are used to this style and are trying to figure out how to do it in go. Alienating these people means they won't use go at all, or will use it badly.

Having said that, I think I can do better than my first crack at the Go code and might be able to avoid generics.


-- 
Clifford Hammerschmidt, P.Eng.

Jeremy Wall

unread,
Aug 16, 2012, 6:22:15 PM8/16/12
to josvazg, golan...@googlegroups.com
For an example of a resuseable container with typesafe updates, using
a paradigm related to the sort packages, I came up with this set
example: http://code.google.com/u/jeremymzhs/containers/source/browse/set/

See set.go for the "base" generic containers. And impl.go for an
example implementation of that container for strings. It uses a
combination of interfaces and composition to accomplish the same thing
as generics. It has a little more code for the specialized
implementations of a set but not that much more and updates of the set
are safe. The only part I haven't come up with a typesafe solution I'm
happy with are the set operations in operators.go but I haven't tried
very hard yet.

I'm still playing with this but I suspect it's pretty close to what I
want in Go.

On Wed, Jul 4, 2012 at 1:51 AM, josvazg <jos...@gmail.com> wrote:
> I read that one. I haven't had the time to watch the video in one go,
> though, I started the original one with those horrible sound problems and
> then I was able to watch parts of this one, but not sure I watch it all. But
> I read that question on the page.
>
> I follow all golang team talks and slides I know about. I learn a lot from
> them and I really like how they explain things.
>
> But in this particular case, there is not much new information on that
> answer, in my opinion.
>
> I agree with Russ view's that Generics are overused most of the time and in
> Go you don't miss them so often, in most cases "generics needs" are
> container or type specification related. (I am tired of having to specify
> things like Map<String,Object> m=new HashMap<String,Object>(); over and over
> again...)
>
> I also agree that Go should stay true to its goal to make a good simple and
> powerful language by taking out more than taking in features. So yes, I
> quite understand that Russ should "rush" to generics ;-)
>
> The more I think about this subject the more I believe we might be
> confronting the problem in the wrong way:
> - Maybe we DON'T need generics at all.
> - Maybe generics is just a NOT optimal but general solution to a set of
> different but related programming problems.
> - Maybe we could identify those problems and give them other solutions
> WITHOUT generics.
> (This is the reason I started this thread, although I admit I haven't got to
> any conclusion yet)
>
> What do you think of this approach?
>
>
>
> On Wednesday, July 4, 2012 3:05:00 AM UTC+2, Uriel DeLarge wrote:
>>
>> On Tue, Jul 3, 2012 at 9:25 AM, josvazg <jos...@gmail.com> wrote:
>> > Yes, I new that one and know about Russ blog, that, as someone posted,
>> > it's
>> > a bit frozen, it hasn't been updated in a long time so we don't know
>> > what
>> > Russ thinks about all these now,
>>
>> Russ did answer a question about generics in a talk that he gave
>> recently, he included a transcript of the Q&A in:
>> http://research.swtch.com/gotour
>>
>> And here is the specific question and answer about generics:
>>
>> "Q. What about generics? How far off are they?
>>
>> A. People have asked us about generics from day 1. The answer has
>> always been, and still is, that it’s something we’ve put a lot of
>> thought into, but we haven’t yet found an approach that we think is a
>> good fit for Go. We’ve talked to people who have been involved in the
>> design of generics in other languages, and they’ve almost universally
>> cautioned us not to rush into something unless we understand it very
>> well and are comfortable with the implications. We don’t want to do
>> something that we’ll be stuck with forever and regret.
>>
>> Also, speaking for myself, I don’t miss generics when I write Go
>> programs. What’s there, having built-in support for arrays, slices,
>> and maps, seems to work very well.
>>
>> Finally, we just made this promise about backwards compatibility with
>> the release of Go 1. If we did add some form of generics, my guess is
>> that some of the existing APIs would need to change, which can’t
>> happen until Go 2, which I think is probably years away."
>>
>> > if he has come up to some new revelation or
>>
>> The main "revelation" seems to be, and which most people actually
>> writing Go code seem to share, is that he doesn't miss generics.
>>
>> There was even a question during the "Meet the Go team" at Google IO
>> asking to please keep generics out of the language, and I have seen
>> several people express similar opinions (but none from the Go team,
>> only from users, and I think it is a rather small minority, but is
>> important to note that not everyone believes generics are worth the
>> complexity they would add to the language).
>>
>> Uriel

Rémy Oudompheng

unread,
Aug 16, 2012, 7:13:38 PM8/16/12
to Clifford Hammerschmidt, Jan Mercl, djhar...@gmail.com, golan...@googlegroups.com
On 2012/8/16 Clifford Hammerschmidt <tangl...@gmail.com> wrote:
> True enough, I'm used C#'s rules.
>
> the C# version is:
>
> interface IComparable
> {
> bool Less(IComparable other);
> bool Equal(IComparable other);
> }
>
> interface IPriorityQueue<TD,TP> where TP:IComparable
> {
> void Enqueue(TD data, TP priority);
> Tuple<TD,TP> Dequeue();
> }
>
> (Errors would be thrown as exceptions)
>
> A "constrainable generic" is the ability to require the type provided adhere
> to a specific interface. (c# also support other constraints like having a
> default ctor.) By using a generic for TP we ensure the type used is
> consistently the same implementer of IComparable rather than any implementer
> of IComparable.

Does that mean a C# type implementing IComparable must use a weird
inconsistent typing for the Less and Equal methods with possible
runtime exceptions? How can that be better than Go?

> Limiting the rules to two computer screens is a bit of an arbitrary
> requirement. I'm not saying it's easy to create the rules or build the
> result, just that generics do make this style of code easier, and examples
> of such systems already exist (C# for instance).

Many things exist in the world, but it doesn't mean you can stuff
anything in anything.

> Yes, those systems have
> trade offs, but on the whole the prevent worse code (using reflect, etc.)
> from being written. Repeated saying that this style isn't idiomatic doesn't
> change that several people are used to this style and are trying to figure
> out how to do it in go. Alienating these people means they won't use go at
> all, or will use it badly.

It is certainly okay if people don't use Go when they obviously want
to do something that is not possible in Go. There are many other
programming languages in the wild that are best suited to various
programming paradigms, and Go is not meant to be used for all possible
paradigms, although it is already possible to use it in many ways.

Rémy.

Clifford Hammerschmidt

unread,
Aug 16, 2012, 7:42:42 PM8/16/12
to Rémy Oudompheng, Jan Mercl, djhar...@gmail.com, golan...@googlegroups.com
Does that mean a C# type implementing IComparable must use a weird
inconsistent typing for the Less and Equal methods with possible
runtime exceptions? How can that be better than Go? 

Sorry, you're right, you really want:

    interface ILesser<T>
    {
        bool Less(T other);
    }

    interface IPriorityQueue<TD, TP> where TP:ILesser<TD>
    {
        void Enq(TD data, TP priority);
        Tuple<TD, TP> Deq();
    }

(turns out you only need .Less)

So you can write:

    sealed class MyPriority : ILesser<MyPriority>
    {
        private readonly int _value;
        public MyPriority(int value)
        {
            _value = value;
        }
        public bool Less(MyPriority other)
        {
            return _value < other._value;
        }
    }

It is certainly okay if people don't use Go when they obviously want
to do something that is not possible in Go. 

Except that it is possible to solve the underlying problem using Go. This specific method (using generics) isn't possible, but that doesn't mean there isn't a way to do it using Go.


-- 
Clifford Hammerschmidt, P.Eng.

Paulo Pinto

unread,
Aug 17, 2012, 3:43:23 AM8/17/12
to golang-nuts
On Aug 17, 1:13 am, Rémy Oudompheng <remyoudomph...@gmail.com> wrote:
> On 2012/8/16 Clifford Hammerschmidt <tanglebo...@gmail.com> wrote:
>
> It is certainly okay if people don't use Go when they obviously want
> to do something that is not possible in Go. There are many other
> programming languages in the wild that are best suited to various
> programming paradigms, and Go is not meant to be used for all possible
> paradigms, although it is already possible to use it in many ways.
>
> Rémy.

That is why I stopped using Go for personal projects, and went with D
and C++11 depending
on the available libraries for the project at hand.

With Scala, Clojure, F#, C# being used on professional projects,
depending on what the Customer
requests on their RFPs.

--
Paulo

Aram Hăvărneanu

unread,
Aug 17, 2012, 5:27:18 AM8/17/12
to Paulo Pinto, golang-nuts
> That is why I stopped using Go for personal projects, and went with D
> and C++11 depending
> on the available libraries for the project at hand.
>
> With Scala, Clojure, F#, C# being used on professional projects,
> depending on what the Customer
> requests on their RFPs.

Thanks for letting us know something we never asked.

--
Aram Hăvărneanu

Paulo Pinto

unread,
Aug 17, 2012, 8:21:42 AM8/17/12
to golang-nuts
I was trolling a bit, sure, but also stating to one of Uriel's comment
that there are developers like myself
that have decided that despite some of the nice features Go offers, we
are currently better served
with other languages. As languages are only tools, nothing more.

But alas, you remark made me regret to still come here.

--
Paulo




TR NS

unread,
Aug 7, 2013, 2:48:56 PM8/7/13
to golan...@googlegroups.com, josvazg


On Friday, April 20, 2012 8:02:33 AM UTC-4, Ryan Betts wrote:
On Friday, April 20, 2012 6:52:35 AM UTC-4, Davies wrote:
Another one: map() in Python
map(lambda x:x*2, range(100))

- Polymorphic functions that operate on built-in generic types. 
  func KeyIntersection(a map[T1]T2, b map[T1]T2) map[T1]T2 {}

Is the only way to address this via method overloading? I.e. so that T1 and T2 can define multiple possibilities which automatically define the possible separate methods.

Or what about pass-by-reference?


Matt Sherman

unread,
Sep 26, 2013, 9:18:51 PM9/26/13
to golan...@googlegroups.com
Disclaimer: I am new to Go and am coming from a C# bias (am a dev at Stack O); also realize this is an old thread so thanks for the indulgence.

The main use case for generics is the 'family' of map-reduce functions: filters, aggregation, projection. It's entirely possible to encapsulate such functions for specific types in Go, of course, but doing so generically would allow for a lot less code. It's sugar, no doubt, but it's also brevity and clarity.

Chaining such functions feels like piping to me, which is a common and understandable metaphor. My current habits are such that, if I resort to an explicit loop, I feel like I haven't thought hard enough about the problem.
Reply all
Reply to author
Forward
0 new messages