I know of PHP and JavaScript. PHP was not designed at all so no point discussing it. JavaScript was initially written in a week so we forgive Brendan Eich.
Technically Javascript does not have hashes at all, and you use bare objects instead, the confusion between objects and Array comes from PHP reprobates.
Lua is an other language with no arrays, and where hashes are used in stead. Additional entrants in the category are ~~Tcl~~ (got corrected, Tcl's associative arrays are called "arrays" but it has a separate "list" type for indexed sequences) and Awk.
Ok don't include JavaScript. So there is only PHP that does this? I'm just trying to find out where the article is coming from. I didn't think this was a common theme amongst languages.
Javascript doesn't really conflate arrays and hashes in the way PHP does. It uses the same bracket syntax for both, but you either instantiate an array or a hash.
I don't think that allowing you to iterate over a hash as if it were an array is all that unforgivable, though it's often not the right thing to do and you can't expect the values in any particular order.
> I don't think that allowing you to iterate over a hash as if it were an array is all that unforgivable
it's not even doable in JavaScript: bare objects (~hashes) are iterated with for...in, using that with arrays gives inconsistent results: the array's keys will be iterated as if they were (string) properties, there are no guarantees they'll be iterated in numerical order, and any enumerable property added to the array itself or any of its ancestors will be iterated over as well.
Friends don't let friends iterate over arrays with for...in.
I just use Array.prototype.[forEach|map|filter] instead, or the equivalent Underscore.js function (which aliases to native when it can) if IE-compatibility is needed.
If you need performances, nothing will beat C-style access anyway. And FWIW, using for...in on an array is slower than using Array.prototype.forEach.
edit: FWIW, even hand-rolling an each() function (in the style of underscore's) will be faster than for...in.
Perl has 3 ways to iterate over a hash: "keys", "values", and "each". The first two do what you'd think; "each" in array context iterates over key/value pairs. All three return their results in an "apparently random" order.
You can also use "for" to iterate over a hash, same as you would over an array, but in that case the hash is converted to a list of alternating keys and values, which isn't as useful.
I had to look this up because I was thinking otherwise, but now I believe you are correct - it is just inconsistent between runs:
http://perldoc.perl.org/functions/each.html says "Hash entries are returned in an apparently random order. The actual random order is subject to change in future versions of Perl, but it is guaranteed to be in the same order as either the keys or values function would produce on the same (unmodified) hash. Since Perl 5.8.2 the ordering can be different even between different runs of Perl for security reasons (see Algorithmic Complexity Attacks in perlsec)."
"You either instantiate an array or a hash" suggests that arrays and hashes are distinct in Javascript, but they aren't. Arrays _are_ hashes (that is, Objects) with some extra functions in their prototype which let them, in the words of the standard, "give special treatment to a certain class of property names."
Yes, you're absolutely right. I meant that in usage you generally either instantiate a plan object and use it as a hash or you instantiate an array and use it as an array, but when you instantiate an array, you can treat it like any other object.
I'm not sure if I'd characterize Javascript's handling of arrays and hashes as conflated. The two are treated differently. To take an example from the post, Javascript Objects (hashes/Associative arrays) do not have a splice function.
To answer your question I don't know of many languages which conflate the two. I know a lot of languages which offer similar methods, to create parity between arrays and hashes (since they are similar enough data structures) but not many which treat them the same.
> I'm not sure if I'd characterize Javascript's handling of arrays and hashes as conflated.
Insomuch as [] and {} produce arrays and object, yes, you are correct. But those objects are strikingly similar and the functions in each prototype work on the other. To the outside observer, only the length bit works differently.
I can do:
a = new Array();
a["b"] = 1;
for (x in a) { /* x will be "b" here*/ }
a.length /* 0 */
and
d = {0:"a",1:"b",2:"c",3:"d",length:4}
Array.prototype.slice.call(d, 1,3) /* returns ["b", "c"] */
The point of preserving insertion order is not to be able to treat hashes as arrays. It's to get deterministic and repeatable iteration order between different runs. Java has LinkedHashMap and LinkedHashSet if you care about iteration order and HashMap and HashSet if you don't.
With the repeatability it's easier to write automatic tests.
I worked at a company making a compiler in Java and we got different binaries when compiling without changing the source code. After we changed to LinkedHashMap and LinkedHashSet that problem was gone. That's an example where we wanted the deterministic aspect of the Linked versions.
Another way to get the same behavior in Java is to use TreeMap and TreeSet, but that only works if the things you put in are comparable, and you get different time complexities as well.
I know of PHP and JavaScript. PHP was not designed at all so no point discussing it. JavaScript was initially written in a week so we forgive Brendan Eich.