Maps vs. map

In functional languages, map traditionally refers to everyone's favourite1 high-order function. C++ and Java, on the other hand, follow a common mathematical usage: a “map” is a dictionary (an associative array, if anyone still uses that term). Clojure and Scala, being of mixed parentage, have both: their map is the high-order function, and their dictionaries also have names containing Map. This is only a little bit confusing, but both concepts are so important that they ought to have unambiguous names.

I usually prefer to reserve map for the function, and dismiss the use of the same name for dictionaries because it's less familiar and it doesn't make much sense. But map doesn't make much sense as a name for the function either. You can make excuses for it (it maps old elements of the list to new ones? it maps2 the function across the list?) but they're not very compelling; you can make equally good excuses for many other functions. The name is standard, but it's not a very good one.

Meanwhile, dictionaries are a common concept in need of a good name. “Dictionary” is four syllables, and “associative array” six (and misleading). “Hash” is too specific (and also a little misleading, since it ought to mean a hash function). But “map” is short, already somewhat well-known, and if not clear then at least not actively misleading. So maybe I should give up and call them maps, and find some other name for map-the-function.

Is this outrageous?

There's no obvious better name. image might be clear to mathematicians, but it's opaque to everyone else. elementwise is too long. each is comfortable, but suggests for-each (as in Ruby) or every. Repurposed prepositions like across or through are opaque, and tend to collide with natural-language uses (consider how annoying the C++/Java this is in speech). Symbolic names are even more opaque, not to mention unpronounceable. Perhaps it acquired the name map for lack of a good alternative.

It might be possible to avoid the issue by making the function unnecessary. If scalar operations are overloaded to operate elementwise on collections, as in APL, explicit map would be much less common, so its name would be less important. It wouldn't be rare enough to ignore, though; many of its calls use operations that aren't scalar-only, or at least aren't obviously so, so they would still be written with explicit map.

Another alternative is to merge it with some other function. If collections are seen as functions, map is almost equivalent to compose (especially in a lazy language). If compose on a collection does map, then there's no need for a separate map function, especially if compose has a short name like . or . However, I have some difficulty understanding f . xs as map f xs. Composition and elementwise application may nearly coincide in meaning, but they're conceptually quite different.

1Except possibly for compose.

2This use of “map” as a verb is presumably derived from the function, so it's a poor excuse.


Here's another trivial convenience function:

divides? : int → int → boolean
divides? a b = mod b a == 0

This makes divisibility tests read more like the mathematical a | b notation:

prime? n = n ≥ 2 && not (some (2 .. isqrt n) (divides? _ n))

Argument order and name are debatable. (I find the ? suffix surprisingly uncomfortable, perhaps because divides? is a binary mathematical predicate, so I expect it to be a single-character infix operator like < ≤ ∈ ⊂, not an “ordinary” function.)

I initially wrote divides? off as a feature useful only in toy problems. It certainly comes up a lot in Project Euler problems, since those (as befits their name) are heavy on number theory. But even in real code, many (most?) uses of mod are divisibility tests. So divides? may be worth having, because it expresses this directly rather than via a slightly awkward use of mod.

(Real-world divisibility tests, incidentally, are often used to do something every nth iteration, e.g. updating a progress indicator, flushing a buffer, updating a cache. This pattern is so common that it might deserve an abstraction of its own. However, it's often a mistake — many periodic operations should be periodic in time, not number of iterations. So there's another useful operation: periodically interval timer.)