Best sum up of the language i've ever seen (plus it seems completely coherent with what i've supposed so far about that language, both pros and cons).
About the "no generic / you have to cast ,recast / the make issue" , could anyone here with a bit of experience gives an example of what that would look like in real code ?
About the "no generic / you have to cast ,recast / the make issue" , could anyone here with a bit of experience gives an example of what that would look like in real code ?
Sure. Say you have a Set type (which is custom, since Go doesn't provide a `container/set` type.
type Set struct {
set map[interface{}]bool
}
All of the methods (`Add()`, `Contains()`, etc.) are going to be declared with `interface{}` parameters, e.g.,
func (set *Set) Add(x interface{}) bool
You would also want a method to get a slice of all members, e.g.,
func (set *Set) Members() []interface{}
If you want to use this as a set of strings, you would add without a cast:
mySet.Add("foo")
However, when pulling it out you would need to cast it to a string. So if you were converting `[]interface{}` to `[]string`, it would look like this:
values := make([]string, mySet.Len())
for i, member := range mySet.Members() {
values[i] = member.(string)
}
Yes, but the `container/list` standard library uses the same approach.
I wrote a Cartesian product library that took a different tack--it splits the index and iterator cursor logic (integer fiddling) into one struct and the actual type into another, so it's easy to build type-checked objects.
In full disclosure, though, that was mainly because the alternative (using `interface{}`) was so utterly painful.
You pretty much can't write your own container without significant pain. That said, with the built in objects you have a map, list, set (map of bools, which is actually very nice since maps return default types - false - for missing entries), and concurrent blocking or non-blocking queue (chan). Stacks get a bit cludgy, but can be done without too much pain. Apart from those, I've really never had to roll my own collection class. Someday I may, but it is surely not something you need to do very often.
On the contrary, I found it significantly easier to write a custom container (a trie in my case) in Golang than in Ruby (which let's stipulate is pin-compatible with Python). In particular, Golang provides fine-grained control over memory layout, and is even expressive enough to implement allocators, both of which are practically impossible in Ruby.
It's true that Golang grants a very useful power to its builtin maps, which makes it rankle that you have to cast in and out of interface{} to make your own general-purpose container. But apart from the fact that interface{} is a stupid name, I don't find it much more painful to write general purpose containers in Golang than I found it to write templated containers in C++.
Cool, I didn't know that. will change my Set implementation :)
BTW You should remember that if you really want a python-like set, map[interface{}]struct{} is not enough - you still have to implement intersection, union, diff yourself. Not that it's rocket science, but I do think this warrants at least a package in the std library, if not a first class type.
There's nothing "out of idiom" of custom containers in Python (or are numpy arrays or pandas dataframes "out of idiom" now? I could swear that wasn't the case yesterday), and pretty much anything available to builtin containers are also available to custom ones (the exceptions being literal syntax, and true immutability unless the container is written in C).
In fact there are a few domains where they are rather common (e.g. multidict implementations in web framework, pretty much every web framework has one for query and form data; optimized or analysis-focused structures in scientific python)
About the "no generic / you have to cast ,recast / the make issue" , could anyone here with a bit of experience gives an example of what that would look like in real code ?