Programing Language: Syntactic and Semantic Difference of Map Function

By Xah Lee. Date: . Last updated: .

In most language today, there's a “map” function, and encouraged by programers as good style. Map is typically used like this: map(function, list).

There's a critical point in the language spec on the behavior of “map”. Namely, whether the language specifies that the function passed to map must not have side-effects.

JavaScript Example

in JavaScript, its map is Array.prototype.map(f). However, the spec says it must be computed as a loop, that is, apply the function to elements in order.

JavaScript map spec 2015 0b3b5744
JavaScript spec on its array map function. ECMAScript 2015 §Indexed Collections#sec-array.prototype.map

[see JS: Array.prototype.map]

This means, JavaScript compiler cannot compile it into running parallel on multiple CPUs. It must apply the function to array element one at a time, in order.

Automatic parallel computation advantage of using map is lost.

See: Guy Steele Says: Don't Iterate, Recurse, and Get rid of lisp cons!

So, when you use “map” in JavaScript, the advantage is merely syntactical.

Lisp Example

In emacs lisp, the spec says the list elements are applied “in turn”.

emacs lisp manual on mapcar 2015-09-20
Emacs Lisp manual on mapcar. Mapping Functions (ELISP Manual)

So, this also means, it thwarts automatic parallel computation.

Consequence of the Map Function Spec

When a language, specifies the map behavior such that:

Then, such language's “map” function can safely do automatic parallel computation.

Without the above requirement, the “map” is simply useful as a clean syntax of iteration.

Enforce or Not, and How

If a language specifies that the function passed to map must not have side-effects, then, there is the question of whether the language enforces it. If so, how.

If the language does not enforce it, then, the result can be tricky. Because, programers may just ignore it, or due to ignorance, and use map with function that has side-effect. The result is that, sometimes it may not work, and is hard to debug. Then, it creates a shroud of confusion.

If the language does enforce it, then the question is how. It will need a way to make sure that function does not have side effects. For most languages, such as lisp, JavaScript, Java, Python, there is no mechanism in the language to do this.

Conclusion

So, the conclusion here is, that even many of today's languages have “map”, but it is merely a trivial advantage of readability or syntactic style. The real fruit, the math properties that propel automatic transparent parallel computation, isn't there.

Then, given the situation, there's the question of whether you should still use “map” (or just go with iteration.).

It is still better to use map. Because, using “map” gives a explicit indication to readers, that the function does not have side-effects, and the order of application to list doesn't matter. In practice, most use of map does follow this.

In GNU Emacs community, I believe there's implicit coding style convention that tell people to use iteration (dotimes and related) instead of “mapcar”. That's not good.

Programing Language Design