Map Function

map is one of the CommonHigherOrderFunctions which transforms a list by applying a function to each of its elements. Its return value is the transformed list.

For example:

  (map double (list 1 2 3 4 5))
=> (2 4 6 8 10)
  (map send-email (list message1 message2 message3))
=> (ok bad-recipient-list ok)
There are many variations on the map function, the one described here is called map in Scheme, and mapcar in most Lisps.

map is doubly (ha) useful when used with anonymous functions

In CommonLisp:

(mapcar (lambda (x) (* 2 x)) (list 1 2 3 4 5))
=> (2 4 6 8 10)
In PerlLanguage:

DB<1> x map { 2 * $_ } (1,2,3,4,5)
  0  2
  1  4
  2  6
  3  8
  4  10
(this is using the perl debugger as a poor man's top-level loop. The comand "x" means "evaluate and display the return value")

In SmalltalkLanguage: #collect:

  #(1 2 3 4 5) collect: [:each | 2 * each]
In PythonLanguage:

  map(lambda x: 2*x, (1, 2, 3, 4, 5) )
Version 2.0 of PythonLanguage has ListComprehensions, which are nice syntactic sugar for map:

  [2*x for x in (1, 2, 3, 4, 5)]
In RubyLanguage

  [1, 2, 3, 4, 5].map { |x| 2*x }
In CsharpLanguage 2.0 or greater

  int[] a = { 1, 2, 3, 4, 5 };
  int[] b = Array.ConvertAll(a, delegate(int n) { return n*2; });
In CsharpLanguage 3.0 or greater

  int[] a = { 1, 2, 3, 4, 5 };
  var b = a.Select(n => n * 2); // uses built-in Select operator over sequences
  var c = from n in a select n * 2; // list comprehension syntax over previous example
In CeePlusPlus (C++) using the StandardTemplateLibrary

  int a[5] = {1, 2, 3, 4, 5};
  transform( a, a+5, a, bind1st( times<int>(), 2 ) );
(or a.begin() and a.end() if you instead used a vector for 'a') Note: You can use another collection or the same collection to store the result.

In HaskellLanguage

  map (2*) [1,2,3,4,5]
In OcamlLanguage ((*) 2) [1;2;3;4;5] ((*) 2) [|1;2;3;4;5|]
In SmlLanguage

  map (fn x => x * 2) [1,2,3,4,5] (fn x => x * 2) #[1,2,3,4,5]
In JavaScript 1.6, arrays have a method called "map":

  var evens ={return x * 2;});
In SchemeLanguage:

  (map (lambda (x) (* x 2)) numbers)
Note that Scheme's map is more general than described here. It actually accepts an n-ary function followed by n lists, each of length M. The output is a single list of length M, composed by calling the given function with arguments taken from the 'm'th element of each list. e.g.:

  (map add (list 1 2 3) (list 4 5 6))
  -> (5 7 9)
In PhpLanguage:

  array_map(create_function('$x', 'return 2 * $x;'), array(1, 2, 3, 4, 5))
In SwiftLanguage:

  [1,2,3,4,5].map { 2 * $0 }
In StructuredQueryLanguage (SQL):

  select x * 2 as Double   // make sure not a reserved word
  from original_list
Note you must use an expression, since many dialects don't allow user-defined functions (or don't make it easy).

One of the nice things about the RubyLanguage is that these iterated constructs can be programmed in the language. A method may be passed a closure, and within the method you can coroutine with that closure using the 'yield' construct.

  def silly
yield "one"
yield "two"
yield "three"

silly { |s| puts s }# outputs one, two, three
So, for example, Ruby doesn't have the equivalent of Smalltalk's 'inject'. However, it's simple to write one. If we assume the existence of an InternalIterator in the current class called 'each', which invokes its closure for each element in a collection (a Ruby convention), then 'inject' would be

  class ACollection
# ...
def inject(n)
each { |value| n = yield(n, value) }

a = sum = a.inject(0) { |result, value| result + value } product = a.inject(1) { |result, value| result * value |
and so on.

In fact, you'd probably define inject as a method in the existing module Enumerable, and every collection would automatically support it from then on.

It's fun to be able to code so flexibly in this functional style.

Actually ruby has #inject since version 1.8

Hmmmm... I"ve always thought of map as being more like #do in SmallTalk. It allows you to create a new list, but it doesn't necessarily create a new collection object. For example, the map function in Perl acts much like #do in SmallTalk. You can print each item in the list, apply a procedure, create a new collection just of evaluation results, or not. I think the problem is the way input and output work in a Functional Language as opposed to an ObjectOriented language like SmallTalk. In something like map, you can compose by giving it another iterator as an argument, instead of just some expression to evaluate on each member. This makes it seems like it works as #collect but it actually operates like #do, just in a functional environment. I'm just kind of guessing, is this assumption incorrect?

I'm afraid it is incorrect. map as in Scheme always creates a new list. The equivalent of 'do:' is for-each (a standard scheme procedure). See

 (define (for-each f lst)
(if (not (null? lst))
 (f (car lst))
 (for-each f (cdr lst)))))
In CommonLisp, mapcar is the MapFunction as described here, and mapc behaves like Scheme's for-each. There are a few related functions: maplist, mapl, mapcan, and mapcon. The last two are very seldom needed...

If we construe lists (and kindred collection types) as mappings (input is the index, hash key or whatever; bags and similar need to be construed, via iteration, as lists to fit them into this concept) then we can regard map as simply the composition operation among functions. A list h, in these terms, is just a function

    h[i] <- i
from some initial subset, n, of the naturals (so i is in n). Our function f is then
    f(x) <- x
and map(f, h) is just
    f(h[i]) <- i
which is simply the result of composing f after h; it's f function from n, just as h was (so it's a list) which feeds h's input through h and h's output through f.

One of the distinguishing characteristics of ExBase is a kind of MapFunction capability over a given table, but also with predicate filtering, similar to an SQL "WHERE" clause. (Early dialects only allowed this on built-in functions, not user-defined ones.)

Pseudo-code for it would resemble:

  Perform function a() on table b where x > y and foo=7
Ideally, a reference to the current "row" would be passed to the function, but ExBase used a more primitive default scope for such. This simplified rapid prototyping and interactive work, but would not work well for large shared libraries.

CategoryFunctionalProgramming CategoryInManyProgrammingLanguages CategoryObjectFunctionalPatterns

EditText of this page (last edited June 15, 2014) or FindPage with title or text search