Previous Page Next Page Contents

map -- apply a function to all operands of an object

Introduction

map(object, f) applies the function f to all operands of object.

Call(s)

map(object, f <, p1, p2, ...>)

Parameters

object - an arbitrary MuPAD object
f - a function
p1, p2, ... - any MuPAD objects accepted by f as additional parameters

Returns

a copy of object with f applied to all operands.

Overloadable:

object

Related Functions

eval, mapcoeffs, misc::maprec, op, select, split, subs, subsex, subsop, zip

Details

Example 1

map works for expressions:

>> map(a + b + 3, sin)
                         sin(a) + sin(b) + sin(3)

The optional arguments of map are passed to the function being mapped:

>> map(a + b + 3, f, x, y)
                   f(a, x, y) + f(b, x, y) + f(3, x, y)

In the following example, we add 10 to each element of a list:

>> map([1, x, 2, y, 3, z], _plus, 10)
                   [11, x + 10, 12, y + 10, 13, z + 10]

Example 2

Like most other MuPAD functions, map does not modify its first argument, but returns a modified copy:

>> a := [0, PI/2, PI, 3*PI/2]:
   map(a, sin)
                               [0, 1, 0, -1]

The list a still has its original value:

>> a
                           --    PI      3 PI --
                           |  0, --, PI, ----  |
                           --    2        2   --

Example 3

map does not decompose rational and complex numbers:

>> map(3/4, _plus, 1), map(3 + 4*I, _plus, 1)
                               7/4, 4 + 4 I

map does not decompose strings:

>> map("MuPAD", text2expr)
                                   MuPAD

map does not decompose polynomials:

>> map(poly(x^2 + x + 1), _plus, 1)
                               2
                         poly(x  + x + 1, [x]) + 1

Use mapcoeffs to apply a function to all coefficients of a polynomial:

>> mapcoeffs(poly(x^2 + x + 1), _plus, 1)
                                 2
                         poly(2 x  + 2 x + 2, [x])

Example 4

The first argument is not flattened:

>> map((1, 2, 3), _plus, 2)
                                  3, 4, 5

Example 5

Sometimes a MuPAD function returns a set or a list of big symbolic expressions containing mathematical constants etc. To get a better intuition about the result, you can map the function float to all elements, which often drastically reduces the size of the expressions:

>> solve(x^4 + x^2 + PI, x)
      {    1/2            1/2     1/2   1/2            1/2     1/2
      {   2    ((1 - 4 PI)    - 1)     2    ((1 - 4 PI)    - 1)
      { - ---------------------------, ---------------------------,
      {                2                            2
      
            1/2              1/2     1/2
           2    (- (1 - 4 PI)    - 1)
         - -----------------------------,
                         2
      
          1/2              1/2     1/2 }
         2    (- (1 - 4 PI)    - 1)    }
         ----------------------------- }
                       2               }
>> map(%, float)
      {- 0.7976383425 - 1.065939457 I,
      
         - 0.7976383425 + 1.065939457 I,
      
         0.7976383425 - 1.065939457 I, 0.7976383425 + 1.065939457 I}

Example 6

In the following example, we delete the values of all global identifiers in the current MuPAD session. The command anames(All, User) returns a set with the names of all user-defined global identifiers having a value. Mapping the function _delete to this set deletes the values of all these identifiers. Since the return value of _delete is the empty sequence null(), the result of the call is the empty set:

>> x := 3: y := 5: x + y
                                     8
>> map(anames(All, User), _delete)
                                    {}
>> x + y
                                   x + y

Example 7

It is possible to perform arbitrary actions with all elements of a data structure via a single map call. This works by passing an anonymous procedure as the second argument f. In the following example, we check that the fact ``an integer n >= 2 is prime if and only if phi(n) = n - 1'', where phi denotes Euler's totient function, holds for all integer 2 <= n < 10. We do this by comparing the result of isprime(n) with the truth value of the equation phi(n) = n - 1 for all elements n of a list containing the integers between 2 and 9:

>> map([2, 3, 4, 5, 6, 7, 8, 9],
       n -> bool(isprime(n) = bool(numlib::phi(n) = n - 1)))
             [TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE]

Example 8

The result of map is not evaluated further. If desired, you must request evaluation explicitly by eval:

>> map(sin(5), float);
   eval(%)
                                 sin(5.0)
      
                               -0.9589242747

Nevertheless, certain internal simplifications take place, such as the calculation of arithmetical operations with numerical arguments. The following call replaces sqrt(2) and PI by floating point approximations, and the system automatically simplifies the resulting sum:

>> map(sin(5) + cos(5), float)
                               -0.6752620892

Example 9

map applied to a table changes only the right sides (the entries) of each operand of the table. Assume the entries stand for net prices and the sales tax (16 percent in this case) must be added:

>> T := table(1 = 65, 2 = 28, 3 = 42):
   map(T, _mult, 1.16)
                               table(
                                 3 = 48.72,
                                 2 = 32.48,
                                 1 = 75.4
                               )

Example 10

map can be overloaded for elements of library domains, if a slot "map" is defined. In this example d is a domain, its elements contains two integer numbers: an index and an entry (like a table). For nice input and printing elements of this domain the slots "new" and "print" are defined:

>> d := newDomain("d"):
   d::new := () -> new(d, args()):
   d::print := object -> _equal(extop(object)):
   d(1, 65), d(2, 28), d(3, 42)
                          1 = 65, 2 = 28, 3 = 42

Without a slot "map" the function f will be applied to the domain element itself. Because the domain d has no slot "_mult", the result is the symbolic _mult call:

>> map(d(1, 65), _mult, 1.16),
   type(map(d(1, 65), _mult, 1.16))
                          1.16 (1 = 65), "_mult"

The slot "map" of this domain should map the given function only onto the second operand of a domain element. The domain d gets a slot "map" and map works properly (in the authors sense) with elements of this domain:

>> d::map := proc(obj, f)
             begin
               if args(0) > 2 then
                 d(extop(obj, 1), f(extop(obj, 2), args(3..args(0))))
               else
                 d(extop(obj, 1), f(extop(obj, 2)))
               end_if
             end_proc:
   map(d(1, 65), _mult, 1.16),
   map(d(2, 28), _mult, 1.16),
   map(d(3, 42), _mult, 1.16)
                      1 = 75.4, 2 = 32.48, 3 = 48.72

Example 11

map does not work recursively. Suppose that we want to de-nest a nested list. We use map to apply the function op, which replaces a list by the sequence of its operands, to all entries of the list l. However, this only affects the entries at the first level:

>> l := [1, [2, [3]], [4, [5]]]:
   map(l, op)
                            [1, 2, [3], 4, [5]]

Use misc::maprec to achieve the desired behavior:

>> [misc::maprec(l, {DOM_LIST} = op)]
                              [1, 2, 3, 4, 5]

Changes




Do you have questions or comments?


Copyright © SciFace Software GmbH & Co. KG 2000