{:check ["true"]}

Index

Map: a higher-order function for iteration

map is a built-in function that accepts two arguments:

map(<function>, <iterable>)
  • Simple iteration over a list:

    xs = [1, -2, 3, -4]
    ys = []
    
    for x in xs:
        ys.append(2*x + 1)
    
    print(ys) # -> [3, -3, 7, -7]
    
  • The for-loop is especially simple (and common):

    1. A new list is constructed.
    2. Each x produces a corresponding y.

    => This is a map-pattern.

  • Functional abstraction:

    1. Define the computation as a function:

      def f(x):
          return 2*x + 1
      
    2. Apply the computation to list, element-by-element:

      ys = map(f, xs)
      
    3. Even more succinctly, we can use lambda functions in conjunction with map:

      ys = map(lambda x: 2*x+1, xs)
      
  • Map is limited. It cannot express the following computations:

    split=8
    xs = [1, -2, 3, -4]
    ys = []
    for x in xs:
        if x > 0:
            ys.append(2*x+1)
    

    Note that the output elements do not correspond to the input elements one-to-one since we only apply computation to positive elements.

    split=8
    xs = [1, -2, 3, -4]
    total = 0
    for x in xs:
        total += x
    

    Note the output is a single value, not a list.

    We need other functional constructs to express these types of iteration.

  • Map is lazy.

    Map returns a lazy iterable: the iterable contains the results: $f(x_1)$, $f(x_2)$, $\dots$, but each computation $f(x_i)$ is evaluated only when it is needed.

    map(lambda x: x+1, [1,2,3]
    #=> <map at 0x1110e0510>
    
    list(map(lambda x: x+1, [1,2,3]))
    #=> [2,3,4]