i'm not using constant key values.
i'm happy with the fact the code works - i'm just wondering
if i will always be guaranteed that the last element with the
same key will win.
it seems a sensible enough strategy to use (add each element
in turn) but i'm not sure the spec defines it.
i agree. we should define the order of map insertion for this casein the spec. please file an issue if you agree.
Reads and writes of values larger than a single machine word behave as multiple machine-word-sized operations in an unspecified order.You'd have to make and exception for the ElementList in a map type composite literal. Obviously a map that is being initialised and read from at the same time is a programmer error, but the memory model definition contradicts the proposal that the insertion order is guaranteed...
On Friday, January 25, 2013 8:01:38 PM UTC+2, Kevin Gillette wrote:Certainly interesting behavior -- I stumbled upon http://play.golang.org/p/xmyvYZmesI before reading your post.
On Jan 25, 2013 8:01 PM, "Kevin Gillette" <extempor...@gmail.com> wrote:
>
> http://play.golang.org/p/mfmdzGrTLM
>
Can't touch this: http://play.golang.org/p/QIHQoO2okk
-j
Sounds like closure evaluations...
Yep, I think that's known to all of us. I don't get how it relates to
the insertion order specification (b3 not derived from b1 and b3 not
derived from b2).
I agree. or "In a map literal, the rules are undefined for resolving the result of using multiple expressions as keys which evaluate to be equal, or using identifiers which change during evaluation of the literal as keys or values. You should not depend on the observed behavior."
Again, I don't really understand the complication.
IMO, the major complexity come from line 27 of http://play.golang.org/p/inaHlQRYgQ.
IMO, the major complexity come from line 27 of http://play.golang.org/p/inaHlQRYgQ.It's true. The only unexpected fact from this whole discussion, given the spec, is that values get evaluated before keys in composite literal map assignment. I think the zero value of an int is just confusing the issue and allowing for the demonstration of some particularly obfuscated code :-)
On Saturday, January 26, 2013 9:31:46 PM UTC+2, kortschak wrote:Changing the snippet I used previously to this shows this http://play.golang.org/p/aDHPFgOuVv
I believe that is a convoluted way to say this: http://play.golang.org/p/KyVn2i--B5
a, aOk, b, bOk take zero-values upon initialization. If the assignment fails, those keep the zero-values.
I agree. or "In a map literal, the rules are undefined for resolving the result of using multiple expressions as keys which evaluate to be equal, or using identifiers which change during evaluation of the literal as keys or values. You should not depend on the observed behavior."
V
On Jan 26, 2013 8:31 PM, "Dan Kortschak" <dan.ko...@adelaide.edu.au> wrote:
>
> Again, I don't really understand the complication.
>
> Changing the snippet I used previously to this shows this http://play.golang.org/p/aDHPFgOuVv
>
> Here you get the same behaviour shown with the map literal construction form, but with the added benefit that you see explicitly when initialisation of the map must be required. Translating this in the literal construction, we have three phases rather than the normal two for assignment:
>
> 1. map initialisation (else step 2 would panic).
> 2. recursive evaluation of the rhs in left to right order
> 3. assignment of the evaluated values to the lhs in left to right order
>
> Am I missing something here?
>
This IMO discusses the parts already worked out in this thread.
What it seems to miss is that a) the current behavior cannot be explained (well defined, deterministic) by the specs in some cases and b) those cases cannot be explained by any permutation of "insertion order" as evaluation side effects kick in - in an (yet another) unspecified way. Thus defining (just) the insertion order is not sufficient.
-j
On Sun, Jan 27, 2013 at 2:52 AM, Kevin Gillette <extempor...@gmail.com> wrote:
I agree. or "In a map literal, the rules are undefined for resolving the result of using multiple expressions as keys which evaluate to be equal, or using identifiers which change during evaluation of the literal as keys or values. You should not depend on the observed behavior."please also consider this: http://play.golang.org/p/jg8yO6yFPg
my proposed specification can also explain this result (after changing map to slice/array).
On Jan 26, 2013 9:01 PM, "minux" <minu...@gmail.com> wrote:
>
> The problem is not specific to map.
Agreed, my earlier proposal covers that.
-j
--
a := 1
f := func() int { a = 2; return 3 }
x := []int{a, f()} // x may be [1, 3] or [2, 3]: evaluation order between a and f() is not specifieda := 1 f := func() int { a = 2; return 3 } x := []int{a, f()} // x may be [1, 3] or [2, 3]: evaluation order between a and f() is not specifiedThat is kind of scary! At least the playground does what you'd expect after this long thread :-)
Why is the order unspecified? Does it make it easier to writer the lexer or the compiler?
Thanks minux. That is what I have been trying to get across.
Actually, minux, the first line of the proposed spec example will always be 2:2, if it comes after the slice assignment:
In every example I've translated from map literal initialisation and assignment to initialisation and the multiple assignment I see exactly the same outcome, so I don't think it's more safe. I (possibly) is less obfuscated, but even that is, I think, just a consequence of people thinking about literal initialisation and multiple assignment differently. I don't think they are, but my assembler is not adequate to be able to determine that.
In every example I've translated from map literal initialisation and assignment to initialisation and the multiple assignment I see exactly the same outcome, so I don't think it's more safe. I (possibly) is less obfuscated, but even that is, I think, just a consequence of people thinking about literal initialisation and multiple assignment differently. I don't think they are, but my assembler is not adequate to be able to determine that.
It will be interesting to look at what the output of the new exp/ssa package will be for composite literal assignment compared to multiple assignment. Should be easier than diff-ing assembly :-)
I think, from the tests, that is very well defined: http://play.golang.org/p/dZDgIdi-Jr
From the map or slice literal, it results a code block, where functions are evaluated first, in source code order, closure style, then the variables.
a := 1
f := func() int { a = 2; return 3 }
x := []int{a, f()} // x may be [1, 3] or [2, 3]: evaluation order between a and f() is not specifiednow i think if we can have a compiler option to randomly reorder all sub-expressionswith unspecified order of evaluation with each other just to flush out this sort of bugs.and preferably "go vet" should be aware of this sort of problem.
As a general rule (even though the "evaluation order is not specified"), it looks like the literal keys are evaluated first while the variable keys are evaluated last, leaving functions, methods etcetera somewhere in between.
On Monday, January 28, 2013 7:03:58 AM UTC+2, kortschak wrote:The outcome of this assignment requires that the index evaluation of the second lhs term (specified as happening in phase one) happens after the assignment of the first lhs term (specified as happening in phase two).
I would expect the output to be map[0:2] rather than map[1:2 0:1].
If you expect the first lhs element to take the value of the second rhs element, that would break the order of parallel assignment, where there has to be a 1:1 match for the number of elements.
I see your example as this:m[0] = 1m[m[0]] = 2
which accounts for the map[1:2 0:1] result.Mitică
Right. That has a "const" as the map key.
If you try a "var" as the map key of a const literal map,
http://play.golang.org/p/2Ull2Ib4L2
you get "prog.go:12: const initializer must be constant".
So, while keys can't be references or slices,
but variables are currently allowed for non-const maps.