in reply to Does Go steal from Perl? :-)

All languages are built using concepts from others, perl is no exception (is takes a lot from C, shell languages, awk...), so even if there was autovivification in Go, there wouldn't be much to say about it.

But this is not autovivification for two reasons. First, autovivification is about nested structure. When you try to use a non existing element of a structure (array or hash) as a structure itself, perl may create that element for you. For example, if %hash is empty and you try to modify $hash{Clef}[0], you are trying to access the array at key Clef, so perl will create an array. In your Go example, it just shows that a non existing int value in a map is treated as 0.

The second reason this is not autovivification, is because it is impossible to have autovivification (AFAICT) in this language. You'll notice that in perl, you know that $hash{Key} is an hash value because of { }. And you know that it contains an array because [0] acccesses an array element. Go, like Python, doesn't have such a distinction, thing[value] could be an array item, a map (dict, or hash) access, or access to a char in a string. In those languages, it's the operand that defines which operation to use, while in perl it's the operator that defines what the operand is. This means that in python* if you try to access thing[value][otherValue] and the first level doesn't exist, python has no idea if you were trying to access a string, an array, a dict or something else, so it can't create it for you.

*I know python better than Go, but the idea still applies

Replies are listed 'Best First'.
Re^2: Does Go steal from Perl? :-)
by kikuchiyo (Hermit) on Aug 03, 2018 at 20:29 UTC

    Go, like Python, doesn't have such a distinction, thingvalue could be an array item, a map (dict, or hash) access, or access to a char in a string. In those languages, it's the operand that defines which operation to use

    Again, no.

    Go is a strongly typed language, every variable has a well-defined type associated it. You can have a nested map type c := map[string]map[string]int, in which case you (and the compiler) can know that its element c["key"] is of type map[string]int and the sub-elements of that (c["key"]["subkey"]) are of type int. Assigning a value of any other type to those keys would result in a compile time error.

    So in theory, you could have autovivification in the language - but in practice you can't, you have to explicitly initialize the mid-level maps yourself, as explained by this blog post: Go maps in action.

    The underlying reason for this, I think, is that Go differentiates between a nil map and an empty map. The zero value of a(n uninitialized) map is a nil map, you have to initialize yourself with make. A nil map can be safely read from, but assigning any key to it results in a runtime panic. When you declare a nested map as the example above, the mid-level maps will be nil maps, and as such, are not safe to assign to. (I consider this to be a design wart of the language.)

      Thanks for the clarification, it was pretty unwise of me to say so much without checking my facts more. So while Go can't have the full power of autovivification on undeclared structures, it would be conceivable when declared as nested data but undefined. It's just not the case. Not sure I'm going to put that knowledge to good use any time soon, but at least I relearned not to assume what a language dis or is like :-)