package main
import "fmt"
// <Add one short line of valid Go code here>
func main() {
var n int = 1
fmt.Println(n)
}
Compiler: "prog.go:8: cannot use 1 (type int) as type int in assignment"
Here's a trick that I expected to work but doesn't. Would be interested to hear the rationale if anyone knows it.
> Here's a trick that I expected to work but doesn't. Would be interested to hear the rationale if anyone knows it.
m := map[[]int]int{}
... will not work, because []int is a slice—that is, a pointer to an array of undetermined state (also technically some more metadata like an offset/size). Think of a slice as a "view" into an array, which does not necessarily need to remain static. A slice does not necessarily "own" the data it's providing a view of; you can have many slices of one array.
m := map[[3]int]int{}
will work, because [3]int is an actual array.
To recap:
a := [3]int{1,2,3} // Array
b := a[:2] // Slice
var c []int = a[:] // Slice
var d [3]int // Array
copy(d[:], c) // Copy to (a slice of an) array from slice
Well, you could take the position that types that permit modification should not be allowed as keys but then you would not allow arrays as keys, which Go does allow. Check this out: http://play.golang.org/p/kocW1BjTco
Another approach to take, which I think could be quite useful, is that if you use something modifiable as a key, then the map takes a snapshot of it when you perform the insert. That way, I can go and modify the key after the insert and any time thereafter if I look for the same sequence of integers, the map will find the associated value.
The problem here is that, in a language like Go, where pointer values are significant (contrast with Haskell, where two lists allocated separately but having the same contents are indistinguishable), you sometimes want to use pointer identity as the key so maybe it's hard to have it both ways.
Oh well. It's just something that surprises someone like me, who has grown accustomed to more value-oriented languages.
> Here's a trick that I expected to work but doesn't. Would be interested to hear the rationale if anyone knows it.
Per the spec[0]:
The comparison operators == and != must be fully defined for operands
of the key type; thus the key type must not be a function, map, or
slice. If the key type is an interface type, these comparison
operators must be defined for the dynamic key values; failure will
cause a run-time panic.
"Map lookup requires an equality operator, which slices do not implement. They don't implement equality because equality is not well defined on such types; there are multiple considerations involving shallow vs. deep comparison, pointer vs. value comparison, how to deal with recursive types, and so on. We may revisit this issue—and implementing equality for slices will not invalidate any existing programs—but without a clear idea of what equality of slices should mean, it was simpler to leave it out for now.
In Go 1, unlike prior releases, equality is defined for structs and arrays, so such types can be used as map keys. Slices still do not have a definition of equality, though."
I was thinking that some people would want to figure it out for themselves so I didn't want to spoil the challenge for them... I kind of hoped someone else would post the solution.
The thing is, "int" is not a reserved word in Go. It's just a predeclared binding. You can rebind it -- even use "int" as a local variable name, like so: http://play.golang.org/p/0_iTzkg-5m
There are other interesting cases. For example,
var true = false // Perfectly valid Go code!
I think of it as a prank because you could sneak such a line into somebody's code and the compiler would not help them realize what had happened, it would just complain about a lot of nonsense like 1 not being an int. In the "var true = false" example, there would not even be a compiler error, you'd just get baffling runtime errors.