idea: generic methods on slices with some generic type support []string.Map(string) []string => []<t>.Map(<t>) []<t>

2,084 views
Skip to first unread message

mhh...@gmail.com

unread,
May 24, 2017, 3:52:27 AM5/24/17
to golang-nuts
see the title, only for what s needed Slice/Splice/Each/Map/First/Last/Reverse/Sort ect ect not len, for reason. so interface system serves the userland by its definition of struct, and the basic slice type provided by the language is fully operational, without breaking, btw. i don t go further in evaluation, i leave that to the reader, just trying to work decently.

mhh...@gmail.com

unread,
May 26, 2017, 5:02:53 AM5/26/17
to golang-nuts
would not it be nice to write []string{"hello}.Map(strings.ToUpper) ?

And so for userland types the language accept, []*MyType.Filter(func(*MyType)*MyType).Map(...).First()//etc.

IRL, because the total lack of such struct in the language might let you think the idea is superfluous with the currrent language/idioms/whateveryounameit,
I have this example i like,

// GetByID read the Tomate of given ID
func (t Controller) GetByID(getID string) (jsonResBody *Tomate, err error) {
	t.backend.Transact(func(backend *Tomates) {
		jsonResBody = backend.
			Filter(FilterTomates.ByID(getID)).
			First()
	})
	if jsonResBody == nil {
		err = &NotFoundError{errors.New("Tomate not found")}
	}
	return jsonResBody, err
}

The code is not cluttered with extra if/else/for statements that i d have to introduce using regular constructs proposed by the language.


What are the example that needs extended generic support that interface can fulfilled ?
This one ?

type B string

func A([]string){}

func main(){
 var x []B
 A(x)
}

?
What else chan  ?
https://gist.github.com/mchirico/df9fad3e7a5ea0c4527a ?
map ?




in all cases, it ends up with a manual conversion should occur, can t the language handle it ?
Do the compatibility check needed to slice conversion and produce the results or err appropriately.
Even better, take advantage of it to implement compilation rules ?

sX, err := conv([]string, x) or panic(err)
A(sX)

outChan, err := conv(<- chan /whatever compatible/, inputChan) or panic(err)

Are there more examples in sight ?

mhh...@gmail.com

unread,
May 26, 2017, 5:23:41 AM5/26/17
to golang-nuts
as i m on it,

please consider, what below code might be with little imagination,


// Create a new Tomate
func
(t Controller) Create(postColor *string) (jsonResBody *Tomate, err error) {
 
   mustNot
(postColor, nil) or
     
return ... &UserInputError{errors.New("Missing color parameter")}
 
   color
, _ := mustNot(strings.TrimSpace(*postColor), "") or
     
return ... &UserInputError{errors.New("color must not be empty")}

   t
.backend.Transact(func(backend *Tomates) {
 
     must
(backend.Filter(FilterTomates.ByColor(color)).Empty(), true) or {
       err
= &UserInputError{errors.New("color must be unique")}
       
return
     
}
 
     jsonResBody
= &Tomate{ID: fmt.Sprintf("%v", backend.Len()), Color: color}
     backend
.Push(jsonResBody)
 
 
})

 
return jsonResBody, err
}

From that go compatible code,


// Create a new Tomate
func
(t Controller) Create(postColor *string) (jsonResBody *Tomate, err error) {
   
if postColor == nil {
       
return nil, &UserInputError{errors.New("Missing color parameter")}
   
}
    color
:= strings.TrimSpace(*postColor)
   
if color == "" {
       
return nil, &UserInputError{errors.New("color must not be empty")}
   
}
    t
.backend.Transact(func(backend *Tomates) {
        exist
:= backend.Filter(FilterTomates.ByColor(color)).Len()
       
if exist > 0 {
            err
= &UserInputError{errors.New("color must be unique")}
           
return
       
}
        jsonResBody
= &Tomate{ID: fmt.Sprintf("%v", backend.Len()), Color: color}
        backend
.Push(jsonResBody)
   
})
   
return jsonResBody, err
}



On Wednesday, May 24, 2017 at 9:52:27 AM UTC+2, mhh...@gmail.com wrote:

mhh...@gmail.com

unread,
May 26, 2017, 8:25:37 AM5/26/17
to golang-nuts
for the fun,

I want to write
[]string{"hello}.Map(strings.ToUpper).Each(fmt.Println)

would not work, func param are incompatible.

let s apply static rules to convert it,

printS, err := conv(func(s string), fmt.Println) or panic(err)
[]string{"hello}.Map(strings.ToUpper).Each(printS)

Now it s possible.

And if one does a fmt.MustPrintln to get ride of the error while still handling it (recoverable)
rather than ignore it as of today,
you can write that, and handle error via recover,
or simply ignore it as in the previous ex.

printS, err := conv(func(s string), fmt.MustPrintln) or panic(err)

[]string{"hello}.Map(strings.ToUpper).Each(printS)




On Wednesday, May 24, 2017 at 9:52:27 AM UTC+2, mhh...@gmail.com wrote:

mhh...@gmail.com

unread,
May 26, 2017, 8:45:33 AM5/26/17
to golang-nuts
or this,

printS, err := conv(func(s string, err error), fmt.Println) or panic(err)
_, err := []string{"hello}.Map(strings.ToUpper).MustEach(printS) or panic(err)

count, err := conv(func(n int), fmt.Println) or panic(err)
n := []string{"hello}.Map(strings.ToUpper).Sum(count)

count, err := conv(func(n int, err error), fmt.Println) or panic(err)
n, err := []string{"hello}.Map(strings.ToUpper).MustSum(count) or panic(err)

that'd be great...

mhh...@gmail.com

unread,
May 26, 2017, 8:47:45 AM5/26/17
to golang-nuts
oops... mistake in it.



printS, err := conv(func(s string, err error), fmt.Println) or panic(err)
_, err := []string{"hello}.Map(strings.
ToUpper).MustEach(printS) or panic(err)

count, err := conv(func(s string) n int, fmt.Println) or panic(err)

n := []string{"hello}.Map(strings.ToUpper).Sum(count)

count, err := conv(func(s string) (n int, err error), fmt.Println) or panic(err)

n, err := []string{"hello}.Map(strings.ToUpper).MustSum(count) or panic(err)

more like this, take advantage of return type and names to do more conversion.

mhh...@gmail.com

unread,
May 30, 2017, 10:43:54 AM5/30/17
to golang-nuts
I m just gonna add more examples as it come,

from
            hasPrefix := func(prefix string) func(string) bool {
                return func(s string) bool { return strings.HasPrefix(s, prefix) }
            } // this is not cool....

            if fnUtils.AllTypes().Filter(hasPrefix("post")).NotEmpty() {
                ...
            }

to
            hasPrefix, _ := conv(func(prefix string) func(s string) bool, strings.HasPrefix)
            // does this make sense given https://golang.org/pkg/strings/#HasPrefix ?

            if fnUtils.AllTypes().Filter(hasPrefix("post")).NotEmpty() {
                ...

mhh...@gmail.com

unread,
May 30, 2017, 11:14:57 AM5/30/17
to golang-nuts
I just realized what d be awesome is that the language
does not only provide boiler plate []basicType enhanced types,
but provides streamed version of them,
that d be much better.

when you do
[15Million]string.map().filter().count().

with a naive implementation over array of those intents,
you effectively end up with a copy at each stage,
which is not cool.

Instead if that d be a stream api,
that d be almost same call, with small changes to be determined,
but a much better allocation,
as each item is processed once by each function, one item at a time,
you don t need the intermediate (stupid, after all) arrays.

[15Million]string.map().filter().count().

The difference being
that some func call must become terminal, count() int
some must probably become contiguous to <something to be decided by the user>, filter() stream

can this help to reduce over multiple goroutine?

something like ?
[15Million]string.chunks(size int, concurrent int).Parrallel(receiver []string{}.filter() stream).count().

count is sequential, it receives results from // filters,
receiver is a worker space (memory+work) aka what a stream ? a []string ?,

so ParrallelChunk is (input stream/[]string) stream/[]string

why not ?

mhh...@gmail.com

unread,
May 30, 2017, 2:26:35 PM5/30/17
to golang-nuts
one more case where conv d be awesome,


with
fnUtils.InputParams() ParamSlice

Where
ParamSlice []struct{Name,Type string}

With little help, I can do stuff like

            ctxFilter := astutil.FilterParamSlice.ByType(ctxCtx)
            fnUtils.InputParams().Filter(ctxFilter).Map(func(p astutil.Param) astutil.Param {
                ...
                return p
            })

that works, but its not the best factorization possible,

let say the language provide a construct
- to make a getter of a type property
- a deep eq func of a type

such as an approximation would be

            typeGet := get.(Param.Type) // func() string
            strEq := conv(func(left func() string) func(right string) bool, eq.(string))
            ctxFilter := strEq(typeGet)

in short
- make a getter of Param.type => func()string
- convert string.eq from func(s,s) to a string consumer
     => strEq := func(left func() string) func(right string) bool
- create the value eqer, of a value getter,
    => ctxFilter := strEq(typeGet)

then pass it to a stream/array like data structure (to be defined)

the provider can provides struct only,
and the declarer has more ways to handle the declared api.

mhh...@gmail.com

unread,
Jun 1, 2017, 5:35:18 AM6/1/17
to golang-nuts
What d be awesome is that the stream like interface
i have bee thinking about provides a convert method,
so it can answer to this question

given []string how to move on to []int, or,

[]stream.Map(...) -> give me the length of each string

So if the interface contains a magic signature like this,
<inputType>Conv( conv(<inputType>)<outputType>, sink<outputType>) sink<outputType>

It s possible to write,

[]stream.Map(...).Conv(strToLen, []int{}).Sum()

where
strToLen := func(s string) int { return len(s) }

which, for the fun, could be turned into

strLen := conv(func(v string) int, len)
[]stream.Map(...).Conv(strLen, []int{}).Sum()
// twice conv looks not so good.

Florin Pățan

unread,
Jun 2, 2017, 4:17:54 AM6/2/17
to golang-nuts
Since everyone thinks it but nobody bothers to reply to it: this whole thing you propose can be currently done with a for loop, which not only is explicit about what it doing, but it also lets you control if you want to exit early from it and so on. Complicating the whole language because something is cool (yet looks like a really complex thing that you need to think about while reading the code) is in no one's benefit. Stop trying to avoid a couple of extra rows of for {} (where the third row is literally just an "}") and start embracing the fact that you can understand the code by looking at it and not apply any complex mental acrobatics to figure out what those three lines of code are doing. Your future self/person after you will thank you for that.

mhh...@gmail.com

unread,
Jun 2, 2017, 5:06:54 AM6/2/17
to golang-nuts
Sorry for this crime of thought, i was thinking it was a chance to talk about it and explore different paths.
That, this, is the only answer, well, life is hard.

Just for the records, i did stop thinking like that when i started golang, its not like you are given the choice.

Psst ... I must ask you about the address of the shop where you bought this wonderful magical crystal bowl you use to read in the future.
I kind of fail to find one for my current self.
thanks ;)

Egon

unread,
Jun 2, 2017, 6:05:52 AM6/2/17
to golang-nuts
On Friday, 2 June 2017 12:06:54 UTC+3, mhh...@gmail.com wrote:
Sorry for this crime of thought, i was thinking it was a chance to talk about it and explore different paths.
That, this, is the only answer, well, life is hard.

Thinking and discussion is helpful, but I think the format here could be improved.

The problem in this thread is that these comments are "random thoughts" instead of "organized thoughts" about different aspects, without referencing any prior art.

Organizing these thoughts and points works for these things much, much better. Even better is a article / blog-post for something bigger.

E.g. I would consider this form:

1. real-world problem (no "animal" or "bunny" examples)
1.1. where it exists
1.2. how frequent
2. Current solutions
2.1. current solution 1 (pros/cons)
2.2. current solution 2 (pros/cons)
2.3. current solution 3 (pros/cons)
3. Alternative approaches
3.1 alternative approach 1 (pros/cons/prior-art)
3.2 alternative approach 2 (pros/cons/prior-art)
3.3 alternative approach 3 (pros/cons/prior-art)
4. Comparison between solutions.
5. Cost / benefit discussion.

Each of these around 1-3 paragraphs.

This has a good basis for a good discussion, whereas random thoughts often don't. Also there's always room for a middle-ground.

Thinking aloud and random thoughts work somewhat in chats, but often doesn't end-up in something tangible that can be used later on.

+ Egon

gary.wi...@victoriaplumb.com

unread,
Jun 2, 2017, 8:59:41 AM6/2/17
to golang-nuts
Generics enable more than just replacing loops. For example, they can enable libraries of generic algorithms to be used with any type of array. Here's an example:

foo := GetArray()
result := foo.Take(10).map(...).Sort(...).Reduce(...)

That is simple to understand and in one line of code. Imagine the acrobatics (and lines of code) needed to do this using Go's loops!

You can read my full article on why Go needs generics here: http://nomad.so/2015/03/why-gos-design-is-a-disservice-to-intelligent-programmers/

Egon

unread,
Jun 2, 2017, 9:26:47 AM6/2/17
to golang-nuts
On Friday, 2 June 2017 15:59:41 UTC+3, gary.wi...@victoriaplumb.com wrote:
Generics enable more than just replacing loops. For example, they can enable libraries of generic algorithms to be used with any type of array. Here's an example:

foo := GetArray()
result := foo.Take(10).map(...).Sort(...).Reduce(...)

Why stop there? It also could be:

result := average wage by country

This is much more readable than the map/reduce stuff.

gary.wi...@victoriaplumb.com

unread,
Jun 2, 2017, 10:16:09 AM6/2/17
to golang-nuts
Right, now show me the contents of the average wage by country function! It's not going to be one line or as readable is it?!?!

Henrik Johansson

unread,
Jun 2, 2017, 10:20:22 AM6/2/17
to gary.wi...@victoriaplumb.com, golang-nuts
I have seen syntactic sugar like that in Scala. It can be very powerful but at the same time very confusing when you need to fix a bug since you have the mental overhead of the dsl to actual code to worry about as well.


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

Egon

unread,
Jun 2, 2017, 10:21:38 AM6/2/17
to golang-nuts
On Friday, 2 June 2017 17:16:09 UTC+3, gary.wi...@victoriaplumb.com wrote:
Right, now show me the contents of the average wage by country function! It's not going to be one line or as readable is it?!?!

You can try http://www.wolframalpha.com/, which is somewhat close to the principle.

mhh...@gmail.com

unread,
Jun 3, 2017, 6:06:02 AM6/3/17
to golang-nuts
yes true.

I m not sure i intend to change that asap,
but this another topic,
i want not deep into right now.

That being said again agreed, understood, prone to happen, maybe.

mhh...@gmail.com

unread,
Jun 3, 2017, 6:11:04 AM6/3/17
to golang-nuts
Hi,

yes generics / not generics.

That is, in what i proposed, only the consumer is enhanced, thus generics are not required anymore on the declarer, except for this conv method, indeed.

also as the declarer can rely on more powerful tool on the consumer,
it needs to declare less to able more.

That being said,

Can you take a look to that, genericity less, it works


https://gist.github.com/mh-cbon/2062efef48e246592bdb0665f0ab8547

IMHO, its simple, it does what i need, it helps me to avoid obvious gotchas,  after many attempt i feel satisfy,
please critic it.

mhh...@gmail.com

unread,
Jun 3, 2017, 6:34:15 AM6/3/17
to golang-nuts
> Generics enable more than just replacing loops. For example, they can enable libraries of generic algorithms to be used with any type of array. Here's an example:

in my demonstration every type got this kind of method,
the problem become how do you jump from Type A to type B.
in []A to []B or A -> B

indeed it works on the item level, no more on the collections.

This question is solved in two ways,
- interface definitions (not interface value)
- static conversion, which always resumes to
func(in-type) out-type

and some alternatives for convenience (producer/consumer)
func (func(in-type) out-type
func (in-type) func() out-type
func (func(in-type) func() out-type
// this is unfinished explanation it should include error management to be handled more completely. see please previous conv() fn introduced earlier to statically re decorate a func signature.

So far the sum/reduce things operation,
i left them as exercise to the stream declarer
and did not consider them as core.
Take become => filter (func(10 elements))
Map is map
Sort is All(fn sorter) []out
Reduce is a map operation, preceded by a conv if it reduces to a different type.



On Friday, June 2, 2017 at 2:59:41 PM UTC+2, gary.wi...@victoriaplumb.com wrote:

mhh...@gmail.com

unread,
Jun 3, 2017, 12:24:31 PM6/3/17
to golang-nuts
for the fun, with early return,

https://play.golang.org/p/I9AORKOYQm

Egon

unread,
Jun 3, 2017, 12:35:49 PM6/3/17
to golang-nuts
On Saturday, 3 June 2017 13:11:04 UTC+3, mhh...@gmail.com wrote:
Hi,

yes generics / not generics.

That is, in what i proposed, only the consumer is enhanced, thus generics are not required anymore on the declarer, except for this conv method, indeed.

also as the declarer can rely on more powerful tool on the consumer,
it needs to declare less to able more.

That being said,

Can you take a look to that, genericity less, it works

https://gist.github.com/mh-cbon/2062efef48e246592bdb0665f0ab8547

IMHO, its simple, it does what i need, it helps me to avoid obvious gotchas,  after many attempt i feel satisfy,
please critic it.

I think this version is much clearer: https://play.golang.org/p/9DfxObeDj3 :P

mhh...@gmail.com

unread,
Jun 4, 2017, 6:23:40 AM6/4/17
to golang-nuts
I feel much better with this,
than its counter part,
but what s the point, this is so much about a personal opinion.

func (p PackageInfo) DeepEmbeddeds(structName string) (ret StringSlice) {
    strut := p.GetStruct(structName)
    if strut.GetName() == structName {
        e := strut.Embeddeds()
        e.Filter(p.IsInterface).Each(ret.Append)
        e.Filter(p.IsStruct).Each(func(s string) {
            p.DeepEmbeddeds(s).Each(ret.Append)
        })
    }
    return
}

Ain t exactly what i want,
still can t convert with ease,
but so much clearer.

If you put performance issue aside,
i feel like the only argument opposed so far
is a about
- a somehow more complex code,
- a subjective matter of taste.

for 1, take a look at SO and newbies questions
about chan, you should have some fun.
fun² I remember some trying to build very similar constructs on top of chan.

for 2,
2.1 YOLO, i want better structure to program faster, i might not be doing the right thing because i ain t yet understood the language correctly, yet, i want to benefit the whole environment provided by it, ultimately, that i m right or wrong, does not matter in the immediate terms of getting productive, i m only looking for ways to program faster by reducing all those additional constructs.

In other words,
I want to trade write speed Vs write clarity.

See also that unwinding such constructs, when its not non sense, is trivial.
Thus, if you do a performance analysis and you find that construct in a hot path, you can tell,
lets unwind it.

2.2 blah, if google wants to try to rule the world
with its internal guideline book,
well it look likes it might keep trying,
users will still look for this kind of structure, i believe.

Down that path, the question does not become,
what s acceptable for my guidelines book,
but,
how i can best handle user needs,
provides what s needed to avoid a disaster with the tools given by the language.

Anyway, if golang is to be successful (I mean like java),
i don t doubt that down the road
it will come to something similar,
with generics, or not.

gettin' the pop corn : )

mhh...@gmail.com

unread,
Jun 4, 2017, 12:09:17 PM6/4/17
to golang-nuts
given the fact that actually everybody disagrees on that idea,
or even something similar according to some feedback.

I want to put the question differently.

My mean is to say that golang is a basis to build upon in general that is better
than other existing solutions.

imho, golang is governed by its compatibility requirement,
and, an extremely vertical approach,
which blocks every possible update to the dogma:
is it go 1.0 compatible ?

And because its vertical, is it to my taste ?

The go 1.0 compatibility requirement makes everybody very happy.

Still, I dont believe the language is considered as finalized by a majority of users.
Some will say it misses generics, some other (..) will try different approach.

Why should it be that much of frictions ?

Why can t we evaluate a solution where multiple vision co exists ?
Handle the change.

Aint there existing case of such kind of symbiosis which benefits each other on the long term ?

A solution where the go 1.0 requirement is kept valuable,
and a new language target where this requirement has been removed.
A transpiler to go 1.0 compatible code ?
So both can exist ?

my 2 cents,
that close and negative answer i got,
is not helpful nor inclusive,
its like take or leave attitude,

it d just be more inclusive to say that
it is ok to make a transpiler/or whatever it should be/ implementing your idea,
check that resource for further implementation come back here for questions.

Other consideration,
the idea that golang 1.0 is used to build a different language target that compiles back to go1.0,
looks cool.

Egon

unread,
Jun 4, 2017, 12:25:17 PM6/4/17
to golang-nuts
I think you are missing the point of my comment.

I'm all for generics, but I also can survive without them without much of a problem. (I'm even maintaining https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4 to understand the problem better)

The issue I was trying to highlight was that you are proposing solutions to a problem, but other people don't know what your exact problem is. Hence my 3 lines version are equivalent in their result and value, because the problem is missing.

Similarly, when we don't have a concrete problem we could over-engineer the generics or alternatively solve the wrong problems.

For example, when the solution you propose only solves 5% of the problems that generics needs to solve... or vice-versa... a generics solution 100x simpler would solve 99% of the cases... then what is the value of the proposed solution?

So, which of the 147 different generics approaches/implementations works better for Go and why? (I'm also counting the ones that aren't known yet :D)

When you would use a real-world example and problem, it would be possible to argue that one approach is better than the other... without one, this discussion doesn't lead to anywhere.

+ Egon

utyug...@mail.com

unread,
Jun 4, 2017, 11:59:46 PM6/4/17
to golang-nuts


On Sunday, June 4, 2017 at 12:25:17 PM UTC-4, Egon wrote:
I think you are missing the point of my comment.

I'm all for generics, but I also can survive without them without much of a problem. (I'm even maintaining https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4 to understand the problem better)

create a custom container type that I can use with any type out-of-the-box.

for example: iset := make(Set[int],9); sset := make(Set[string],9); pset := make(Set[Person]);

right now, my solution is to rewrite the source with go generate calling a tool i wrote which grew out from a great talk from robert griesemer. The video: https://www.youtube.com/watch?v=vLxX3yZmw5Q

This solution has nearly twice the performance increase over maps with almost every type used so far. Now I could have just written the 500 lines of code over and over again for every type needed until the end of time(or copy and paste and edit until the end of time), or I could use empty interfaces which throws type safety out the window, but I chose to write a tool, and when go generate came to be I chose to use that tool like a simple script executed within a '//go:generate go run..' tag.


Over time golang(I do this now to annoy the zealots) provided the tools(reflection, /go packages, go generate) that made creating custom generic type safe containers easier. These things weren't always this easy, and these things could be easier.

And I am serious about create a custom container type that I can use with any type out-of-the-box. Please indulge me, how would you solve this problem. Provide a solution for a simple type-safe container type Set that takes any type, with a simple api of insert,remove,contain,union,difference,intersection, complement,superset,subset.

I've seen you provide solutions in the past, so I would like to see your solution to this not-much-of-a-problem.
 

utyug...@mail.com

unread,
Jun 5, 2017, 12:14:17 AM6/5/17
to golang-nuts
Why such a vicious attack? This type of behavior against those exploring generics in golang(i call Go this to spite the zealots) is a scourge gone uncheck for too long. No need for comments to be speckled with demeaning overtone.

Egon

unread,
Jun 5, 2017, 12:52:47 AM6/5/17
to golang-nuts


On Monday, 5 June 2017 06:59:46 UTC+3, utyug...@mail.com wrote:


On Sunday, June 4, 2017 at 12:25:17 PM UTC-4, Egon wrote:
I think you are missing the point of my comment.

I'm all for generics, but I also can survive without them without much of a problem. (I'm even maintaining https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4 to understand the problem better)

create a custom container type that I can use with any type out-of-the-box.

for example: iset := make(Set[int],9); sset := make(Set[string],9); pset := make(Set[Person]);

right now, my solution is to rewrite the source with go generate calling a tool i wrote which grew out from a great talk from robert griesemer. The video: https://www.youtube.com/watch?v=vLxX3yZmw5Q

This solution has nearly twice the performance increase over maps with almost every type used so far. Now I could have just written the 500 lines of code over and over again for every type needed until the end of time(or copy and paste and edit until the end of time), or I could use empty interfaces which throws type safety out the window, but I chose to write a tool, and when go generate came to be I chose to use that tool like a simple script executed within a '//go:generate go run..' tag.


Over time golang(I do this now to annoy the zealots) provided the tools(reflection, /go packages, go generate) that made creating custom generic type safe containers easier. These things weren't always this easy, and these things could be easier.

And I am serious about create a custom container type that I can use with any type out-of-the-box. Please indulge me, how would you solve this problem. Provide a solution for a simple type-safe container type Set that takes any type, with a simple api of insert,remove,contain,union,difference,intersection, complement,superset,subset.

I would use copy-paste. That action to specialize and clean-up API is pretty trivial, it might take me 3min (probably less), but it isn't a problem. I often spend more time on tweaking CSS or figuring out what the customer needs. Copy-pasteing code is annoying, but it's trivial low-effort work... so it's not a problem. There of course are probably domains where this 3min might be a problem. Then you might use a reflect/interface based solution and create a type-safe wrapper. Or use code-generation.

3min writing code, isn't a problem for me.

There's also a subtle problem here, I consider "insert,remove,contain,union,difference,intersection,complement,superset,subset" API somewhat unclear... it loses domain knowledge and may provide more functions than strictyl necessary... this of course it depends on the context.

Also, where will this set be used? Set data-structures have a ton of different trade-offs. I really don't know how to write a really good general purpose Set. (see https://github.com/golang/go/wiki/HowToAsk#the-story-of-a-bad-question)

Florin Pățan

unread,
Jun 5, 2017, 2:28:41 AM6/5/17
to utyug...@mail.com, golang-nuts
Feel free to report me to the CoC committee if you think that telling someone point blank they are wasting their time and creating noise without having a well defined problem or solution. 

And yes, I'm one of those "zealots" who can actually read and know that this programming language is called Go, unlike you apparently.

Believe me, if I wanted to "vicious" I would have been.

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/Oo5s6ryBCYI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

mhh...@gmail.com

unread,
Jun 5, 2017, 4:47:29 AM6/5/17
to golang-nuts
I want to emphases that go generate
is so far an awesome solution,
but not a definitive answer.

Yes, it could made easier,
about that, its already great that all the tools we need
are written in go itself, this is really really really helpful.

mhh...@gmail.com

unread,
Jun 5, 2017, 5:00:45 AM6/5/17
to golang-nuts
as anyway the thread has completely derived,
its the right place to put about that.

I recently read about stanford choosing to use JS over Java
for some its courses.
https://www.theregister.co.uk/2017/04/24/stanford_tests_javascript_in_place_of_java/

I can t understand.
If a beginner ask me which language he should learn,
i d say go,
i d say him, stay put, its unfortunately not easy to enter, but its gonna be a great learning place.

I was an heavy user of javascript,
i loved it for its stream api,
i hated it because of its stream api.

I say its not a good language for beginners,
its apparent ease hides a much greater complexity,
and it does not teach the traditional programming science,
but it has those good things like
its a local problem solver rather than a define all the world approach.

Anyway, my point is to say that i see in this decision of the stanford university
the proof that something has to happen.

THey were teaching Java before, how it come they chosen JS over go ?

mhh...@gmail.com

unread,
Jun 5, 2017, 5:30:33 AM6/5/17
to golang-nuts

mhh...@gmail.com

unread,
Jun 5, 2017, 5:50:18 AM6/5/17
to golang-nuts


On Sunday, June 4, 2017 at 6:25:17 PM UTC+2, Egon wrote:
I think you are missing the point of my comment.

I'm all for generics, but I also can survive without them without much of a problem. (I'm even maintaining https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4 to understand the problem better)

that s actually a good pointer.
 

The issue I was trying to highlight was that you are proposing solutions to a problem, but other people don't know what your exact problem is. Hence my 3 lines version are equivalent in their result and value, because the problem is missing.
 
if i m right you argue the fact i did not come up with a complete formalized approach.
I did not intended to, i think i tried to force open door of what is hiding under the noise, to think out loud.
In the end i expect to either provide one example where its a definitive no-go and its possible to explain why.
or sufficient expected real world use cases to start consider it for later implementation.
But in one-way-communication this obviously can not happen.
 

Similarly, when we don't have a concrete problem we could over-engineer the generics or alternatively solve the wrong problems.

For example, when the solution you propose only solves 5% of the problems that generics needs to solve... or vice-versa... a generics solution 100x simpler would solve 99% of the cases... then what is the value of the proposed solution?

So, which of the 147 different generics approaches/implementations works better for Go and why? (I'm also counting the ones that aren't known yet :D)

When you would use a real-world example and problem, it would be possible to argue that one approach is better than the other... without one, this discussion doesn't lead to anywhere.

+ Egon


Just to clarify,
i m not really in favor of generics per se,
i have enough to deal with right now to not add more complexity here.
In here I mean both declarer and consumer sides of an api programming.

But still i can t go with the existing,
so i did try to solve the problem on my hand,
but it happens it simply require a more in depth solution,
the current superficial solution i can think about will always be limited
by what has been well resumed earlier by utyug
"or I could use empty interfaces which throws type safety out the window".
 

mhh...@gmail.com

unread,
Jun 5, 2017, 6:48:09 AM6/5/17
to golang-nuts

still because its a lot of fun, testing reader / writer,

https://play.golang.org/p/6TBnlY3h6L


On Saturday, June 3, 2017 at 6:24:31 PM UTC+2, mhh...@gmail.com wrote:

Egon

unread,
Jun 5, 2017, 6:55:50 AM6/5/17
to golang-nuts
On Monday, 5 June 2017 12:30:33 UTC+3, mhh...@gmail.com wrote:
just to add,

https://www.youtube.com/watch?v=gHCtEjzZ-rY

I could not agree more on the end,
i could argue about some arguments ;)

btw, is there a channel that gathers all talks about go ?

mhh...@gmail.com

unread,
Jun 5, 2017, 7:33:57 AM6/5/17
to golang-nuts
generics, quick sorter,

i agree to say its fallacies you can provide one func to quicksort string or Vegetables{}.

in my understanding you are doing a quickSorter of Values you can compare.

quicksort([]Valuer)

type Valuer interface {
Value() int
}

So what s a Valuer when you intent to quicksort a []string ?

well maybe its func(string) int,
if you were to sort by length,
len() is almost compatible,
but in current go its not,
its an additional by-hand boiler plate construct to make it compatible.

further, quicksort([]Valuer)  could also be quicksort(readable func() int) []Valuer,
the difference being that the first version works on existing store,
the second must build its own, as a sort works on data set with limits.

but, i dont feel like i want to write quicksort(<T>)

utyug...@mail.com

unread,
Jun 5, 2017, 9:15:01 AM6/5/17
to golang-nuts, utyug...@mail.com
This is golang-nuts, a place where you let shit(ideas) fly.

Trust me guy, I've been light on you. I suggest you cool your jets. This isn't my first rodeo. That is your only warning. This won't end with a report to the CoC committee or some flame war on the forum. I cut much deeper.

utyug...@mail.com

unread,
Jun 5, 2017, 9:16:50 AM6/5/17
to golang-nuts
I've seen you make silly visual aids. Make a '3 minute' video to show your solution.

utyug...@mail.com

unread,
Jun 5, 2017, 9:26:25 AM6/5/17
to golang-nuts
I gave you a simple problem, don't over think it. A Set data structure with a simple api that can work out-of-the-box - just as slices and maps with the builtins. I kept the requirements minimal. I'd like to see your solution.

On Monday, June 5, 2017 at 12:52:47 AM UTC-4, Egon wrote:

Egon

unread,
Jun 5, 2017, 10:31:24 AM6/5/17
to golang-nuts
On Monday, 5 June 2017 16:26:25 UTC+3, utyug...@mail.com wrote:
I gave you a simple problem, don't over think it. A Set data structure with a simple api that can work out-of-the-box - just as slices and maps with the builtins. I kept the requirements minimal. I'd like to see your solution.

As I've already mentioned, my current problem-free approach is not out-of-the-box solution. Maybe, you misunderstood what I meant by problem-free. I mean that this is something I don't care about when writing code and the workaround is trivial-low-effort work...

I didn't know what the set was intended for; so I wasn't able to add Universe -- or don't have a good idea how you would construct one in Go for infinite constrained type. Not sure what you meant by superset/subset; -- if that one set contains another set, then there would be more code similar to Add/Sub. If you meant a superset that returns all possible supersets, then it would need Universe.

By no means I would consider it a good set implementation / API, but since that wasn't one of the criteria.


I ran into 3/4 bugs while renaming types:
1. I forgot to save the file.
2. I forgot to remove the original set entry type.
3. I forgot what the original set api was
4. Confused a,b,c and x,y in the demo.

At the moment I had to specially write generic code for Set, because it seems in ~5 years I've never found it worthwhile to write one. I had a delta-encoded intset, sparse-set, different bitset implementations, but nothing else.

I know the video is not 3minutes long, the rest of 3-minutes I would have used for searching the general purpose set, if I had one.

Depending on the situation the actual approach may vary..

+ Egon
Reply all
Reply to author
Forward
This conversation is locked
You cannot reply and perform actions on locked conversations.
0 new messages