In what way is that item an answer to Serge's comment? The
item says "Map lookup requires an equality operator", and
Serge's suggestion /provides/ one (and a hash, if hashing is
to be used, although some kind of ordering relation might
work instead; It All Depends. Without generics, it's harder to
test-drive plausible alrernatives).
> Why are maps built in?, FAQ.
> http://golang.org/doc/go_faq.html#builtin_maps
Similarly.
Chris
--
Chris "allusive" Dollin
Yes, Peter, I did.
You answered Serge's
> Personally, I think that besides *string maps* and *integer
> maps*, Go should define *maps for interfaces* (which
> implement the methods: equal() and hash() )
with those references, one of which says that Go doesn't do
structs and arrays as map keys because equality isn't well
defined -- but Serge's suggestion says
>define *maps for interfaces* (which implement the
> methods: equal() and hash() )
where I had assumed that the equals() method /provided/
the well-definition of equality, making the cite you chose
inappropriate.
The other reference says
> We believe that Go's implementation of maps is strong
> enough that it will serve for the vast majority of uses
It certainly serves for a /lot/ of uses, but not being able to
have structs for keys has certainly been an issue for me,
and it looks like for Serge, and this isn't the first time this
has come up (of course it might be the same few complainers
each time).
I'd be quite happy to write my own map type for these
purposes, if I had generics so I could write the dratted
thing ONCE. But I can't.
So I don't think your cites address the issue that Serge
had laid before us.
On Sun, 2010-12-19 at 06:00 -0800, Paulo Pinto wrote:
> Personally I don't agree with this reasoning.
>
> In more expressive languages, maps are part of the library and I
> honestly doubt
> that they are less performant than in Go.
At the risk of having taken the comment out of context: maps are
library types in Java and hence Groovy -- though there is significant
syntactic support in Groovy so they look part of the language -- but in
Python, maps (dicts for dictionaries) are integral to the whole Python
system. Python dict are very fast compared to the rest of Python,
albeit slow compared to maps in C++, Go, D, etc.
--
Russel.
=============================================================================
Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel...@ekiga.net
41 Buckmaster Road m: +44 7770 465 077 xmpp: rus...@russel.org.uk
London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
He said /identity/, not /equality/, and specifically "not of the struct "value".
Which of course is the point. Two separate literals stored in memory may well contain the same data at a given point in time, but that's a transient correspondence which may or may not be indicative of equality.
On the face of it the easiest way to get around this would be for Go to accept struct values as keys and under the hood to calculate a hash based purely on the binary data they represent and the type signature. This would be nice from a developer perspective as we'd never have to worry about implementing our own hashing interfaces, but it would have the unfortunate consequence of mandating a given view of equality which might well be a poor fit with any given real-world usage. And there would always be the possibility of hash collisions which thanks to the extra layer of magic might be very difficult to debug...
Another alternative would be to give the language default interfaces which have an incestuous and privileged relationship with builtin data types and functions. This is how Ruby, Python. (un)Icon and a number of other languages with first-class map types handle things - but it feels contrary to the nature of Go in its current form.
So the best compromise is probably the one we all seem to adopt: a Hash interface which returns a unique key for a given type. I agree this is ugly, but this is a systems language we're talking about so it seems quite reasonable that it should be the implementer of a type who decides what constitutes equality for that type.
Ellie
Eleanor McHugh
Games With Brains
http://feyeleanor.tel
----
raise ArgumentError unless @reality.responds_to? :reason
> So the best compromise is probably the one we all seem to adopt: a Hash
> interface which returns a unique key for a given type. I agree this is ugly,
> but this is a systems language we're talking about so it seems quite
> reasonable that it should be the implementer of a type who decides
> what constitutes equality for that type.
I think that's true independant of any "systems language" issues.
We don't need to use interfaces for this. We could pass an equality
function and hash function to the map-making version of make.
(That allows the same type to be used in maps with different equality
and hashing functions, which sounds plausible to me.)
They're not duplicates. They're just pointers to things that happen,
at this moment, to have the same contents.
> A map which stores pointers to data as keys will not reject
> duplicates, therefore it can hardly be regarded as a map, in the sense
> of an associative container.
The definition of "duplicate" is up to the definer. That's why, for example,
pop11 has newproperty (for address-based properties) and newanyproperty
(for whatever-yopu-like based properties), and Java has identity maps as
well as equality ones.
That's a very good idea idea, although even better would be having a runtime properties set for types which would allow equality, ordering, etc. to be specified directly. Can't really think of a clean way of doing that with the existing structure of Go though.
That's a very good idea idea, although even better would be having a runtime properties set for types which would allow equality, ordering, etc. to be specified directly. Can't really think of a clean way of doing that with the existing structure of Go though.On 20 Dec 2010, at 12:40, chris dollin wrote:
> I think that's true independant of any "systems language" issues.
>
> We don't need to use interfaces for this. We could pass an equality
> function and hash function to the map-making version of make.
>
> (That allows the same type to be used in maps with different equality
> and hashing functions, which sounds plausible to me.)
One possible syntax which springs to mind would be
prop (t T) Equals(o T) bool {
...
}
where the set of properties which can be implemented is defined in the language spec and T cannot be an interface. This could also be a nice way to add constructors into Go by allowing 'new' and/or 'allocate' properties.
Handled this way I see properties as similar to the various callbacks in a Ruby or Python system which potentially opens the door to a go-friendly meta-programming model.
One possible syntax which springs to mind would be
prop (t T) Equals(o T) bool {
...
}
where the set of properties which can be implemented is defined in the language spec and T cannot be an interface. This could also be a nice way to add constructors into Go by allowing 'new' and/or 'allocate' properties.
Handled this way I see properties as similar to the various callbacks in a Ruby or Python system which potentially opens the door to a go-friendly meta-programming model.
I'd see properties as only being called by the runtime rather than explicitly by function or method invocation within code. As for interrogation and manipulation, that should probably be restricted to the reflection and unsafe APIs for conformity with other safety-breaking features.
> But here I am arguing syntax for a feature that smells suspiciously like something the Go team would object to ;-). Whatever the syntax, I think that, hypothetically, if properties were implemented, they should be specified using either library functions/constants, or using strings (like in imports or tags), rather than introducing identifiers that have special meaning.
That would leave properties very restricted in their utility, however I freely concede that this could be another one of those cases where my Ruby-brain's conflicting with the core principles of Go ;)