|
|
Line 1: |
Line 1: |
| {{single source|date=November 2012}}
| | Hi there. My title is Sophia Meagher even though it is not the title on my beginning certificate. What I adore performing is soccer but I don't have the time recently. My working day job is a journey psychic phone ([http://www.youronlinepublishers.com/authWiki/AdolphvhBladenqq www.youronlinepublishers.com]) agent. For a while I've been in Alaska but I will have to move in a year or two.<br><br>Check out my blog post :: [http://www.edmposts.com/build-a-beautiful-organic-garden-using-these-ideas/ online psychic readings] phone - [http://gcjcteam.org/index.php?mid=etc_video&document_srl=696611&sort_index=regdate&order_type=desc simply click the up coming website] - |
| In many [[programming language]]s, <code>'''map'''</code> is the name of a [[higher-order function]] that applies a given [[Procedural parameter|function]] to each element of a [[list (computing)|list]], returning a list of results. It is often called ''apply-to-all'' when considered in [[functional form]]. This is an example of [[homomorphism]]. <!-- ex, map f = foldr ((:) . f) [] -->
| |
| | |
| For example, if we define a function <code>square</code> as follows:
| |
| | |
| <source lang="haskell">
| |
| square x = x * x
| |
| </source>
| |
| | |
| Then calling <code>map square [1,2,3,4,5]</code> will return <code>[1,4,9,16,25]</code>, as <code>map</code> will go through the list and apply the function <code>square</code> to each element.
| |
| | |
| ==Generalization==
| |
| In the [[Haskell (programming language)|Haskell programming language]], the [[Type polymorphism|polymorphic]] function <code>map :: (a -> b) -> [a] -> [b]</code> is generalized to a [[Polytypic function|polytypic]] function called <code>fmap :: Functor f => (a -> b) -> f a -> f b</code>, which applies to any type in the [[functor (category theory)|<code>Functor</code>]] class.
| |
| | |
| ''map'' is used in Haskell's Prelude to define the list type constructor (<code>[]</code>) an instance of the <code>Functor</code> type class as follows
| |
| | |
| <source lang="haskell">
| |
| instance Functor [] where fmap = map
| |
| </source>
| |
| | |
| But trees may belong to <code>Functor</code> too, for example:
| |
| <source lang="haskell">
| |
| data Tree a = Leaf a | Fork (Tree a) (Tree a)
| |
| instance Functor Tree where
| |
| fmap f (Leaf x) = Leaf (f x)
| |
| fmap f (Fork l r) = Fork (fmap f l) (fmap f r)
| |
| | |
| fmap (1+) (Fork(Fork(Leaf 0)(Leaf 1))(Fork(Leaf 2)(Leaf 3)))
| |
| </source>
| |
| evaluates to:
| |
| | |
| <source lang="haskell">
| |
| Fork (Fork(Leaf 1)(Leaf 2))(Fork(Leaf 3)(Leaf 4)) | |
| </source>
| |
| | |
| For every instance of the <code>Functor</code> [[type class]], <code>fmap</code> is expected to be defined such that it obeys the functor laws:
| |
| <source lang="haskell">
| |
| fmap id = id -- identity
| |
| fmap (f . g) = fmap f . fmap g -- composition
| |
| </source>
| |
| | |
| Among other uses, this allows defining element-wise operations for various kinds of [[collection (computer science)|collections]].
| |
| | |
| Moreover, if <math>F</math> and <math>G</math> are two functors, a [[natural transformation]] is a function of polymorphic type <math>h: \, \forall T.\, F \, T \rarr G \, T</math> which respects ''fmap'':
| |
| :<math>h_{Y} \circ (\mathrm{fmap} \, k) = (\mathrm{fmap} \, k) \circ h_{X}</math> for any function <math>k: X \rarr Y</math>.
| |
| | |
| If the ''h'' function is defined by [[parametric polymorphism]] as in the type definition above, this specification is always satisfied.
| |
| | |
| ==Optimizations==
| |
| The mathematical basis of maps allow for a number of [[Optimization (computer science)|optimizations]]. If one has <code>(map f . map g) xs</code> ('.' is [[function composition (computer science)|function composition]]) then it is the same as the simpler <code>map (f . g) xs</code>; that is,
| |
| <math>\left( \text{map}\,f \right) \circ \left( \text{map}\,g \right) = \text{map}\,\left( f \circ g \right)</math>. This particular optimization eliminates an expensive second map by fusing it with the first map; thus it is a "map fusion".<ref>[http://www.randomhacks.net/articles/2007/02/10/map-fusion-and-haskell-performance "Map fusion: Making Haskell 225% faster"]</ref>
| |
| | |
| Map functions can be and often are defined in terms of a [[Fold (higher-order function)|fold]] such as <code>foldr</code>, which means one can do a "map-fold fusion": <code>foldr f z . map g</code> is equivalent to <code>foldr (f . g) z</code>.
| |
| | |
| The implementation of map above on singly linked lists is not [[tail recursion|tail-recursive]], so may build up a lot of frames on the stack when called with a large list. Many languages alternately provide a "reverse map" function, which is equivalent to reversing a mapped list, but is tail-recursive. Here is an implementation which utilizes the [[fold (higher-order function)|fold]]-left function.
| |
| | |
| <source lang="haskell">
| |
| rev_map f = foldl (\ys x -> f x : ys) []
| |
| </source>
| |
| | |
| Since reversing a singly linked list is also tail-recursive, reverse and reverse-map can be composed to perform normal map in a tail-recursive way.
| |
| | |
| ==Language comparison==
| |
| The map function originated in [[functional programming]] languages but is today supported (or may be defined) in many [[procedural programming|procedural]], [[object oriented]], and [[multi-paradigm]] languages as well: In [[C++]]'s [[Standard Template Library]], it is called <code>transform</code>, in C# (3.0)'s LINQ library, it is provided as an extension method called <code>Select</code>. Map is also a frequently used operation in high level languages such as [[Perl]], [[Python (programming language)|Python]] and [[Ruby (programming language)|Ruby]]; the operation is called <code>map</code> in all three of these languages. A <code>collect</code> alias for <code>map</code> is also provided in Ruby (from [[Smalltalk]]). [[Common Lisp]] provides a family of map-like functions; the one corresponding to the behavior described here is called <code>mapcar</code> (<code>-car</code> indicating access using the [[CAR and CDR|CAR operation]]). There are also languages with syntactic constructs providing the same functionality as the map function.
| |
| | |
| Map is sometimes generalized to accept dyadic (2-argument) functions that can apply a user-supplied function to corresponding elements from two lists; some languages use special names for this, such as ''map2'' or ''zipWith''. Languages using explicit [[variadic function]]s may have versions of map with variable [[arity]] to support ''variable-arity'' functions. Map with 2 or more lists encounters the issue of handling when the lists are of different lengths. Various languages differ on this; some raise an exception, some stop after the length of the shortest list and ignore extra items on the other lists; some continue on to the length of the longest list, and for the lists that have already ended, pass some placeholder value to the function indicating no value.
| |
| | |
| In languages which support [[first-class function]]s, map may be [[partial application|partially applied]] to "lift" functions to element-wise versions; for instance, <code>(map square)</code> is a Haskell function which squares lists element-wise.
| |
| | |
| {| class="wikitable"
| |
| |+ Map in various languages
| |
| ! Language !! Map !! Map 2 lists !! Map n lists !! Notes !! Handling lists of different lengths
| |
| |- valign="top"
| |
| | [[Common Lisp]]
| |
| | <tt>(mapcar ''func'' ''list'')</tt>
| |
| | <tt>(mapcar ''func'' ''list1'' ''list2'')</tt>
| |
| | <tt>(mapcar ''func'' ''list1'' ''list2'' ...)</tt>
| |
| |
| |
| | stops after the length of the shortest list
| |
| |- valign="top"
| |
| | [[C++]]
| |
| | <tt>std::transform(<wbr/>''begin'', ''end'', ''result'', ''func'')</tt>
| |
| | <tt>std::transform(<wbr/>''begin1'', ''end1'', ''begin2'', ''result'', ''func'')</tt>
| |
| |
| |
| | in header <algorithm><br /> ''begin'', ''end'', & ''result'' are iterators<br /> result is written starting at ''result''
| |
| |
| |
| |- valign="top"
| |
| | [[C Sharp (programming language)|C#]] 3.0
| |
| | <tt>''ienum''.Select(''func'')</tt>
| |
| |
| |
| |
| |
| | <tt>Select</tt> is an extension method<br /> ''ienum'' is an IEnumerable<br /> Similarly in all .NET languages
| |
| |
| |
| |- valign="top"
| |
| | [[Clojure]]
| |
| | <tt>(map ''func'' ''list'')</tt>
| |
| | <tt>(map ''func'' ''list1'' ''list2'')</tt>
| |
| | <tt>(map ''func'' ''list1'' ''list2'' ...)</tt>
| |
| |
| |
| | Clojure: stops after the shortest list ends
| |
| |
| |
| |- valign="top"
| |
| | [[C Sharp (programming language)|C#]] 4.0
| |
| | <tt>''ienum''.Select(''func'')</tt>
| |
| | <tt>''ienum1''.Zip(''ienum2'', ''func'')</tt>
| |
| |
| |
| | <tt>Select</tt> is an extension method<br /> ''ienum'' is an IEnumerable<br /> Similarly in all .NET languages
| |
| | stops after the shortest list ends
| |
| |- valign="top"
| |
| | [[Erlang (programming language)|Erlang]]
| |
| | <tt>lists:map(''Fun'', ''List'')</tt>
| |
| | <tt>lists:zipwith(''Fun'', ''List1'', ''List2'')</tt>
| |
| | <tt>''zipwith3''</tt> also available
| |
| |
| |
| | Lists must be equal length
| |
| |
| |
| |- valign="top"
| |
| | [[F sharp (programming language)|F#]]
| |
| | <tt>List.map ''func'' ''list''</tt>
| |
| | <tt>List.map2 ''func'' ''list1'' ''list2''</tt>
| |
| |
| |
| | Functions exist for other types (''Seq'' and ''Array'')
| |
| | Throws exception
| |
| |
| |
| |- valign="top"
| |
| | [[Haskell (programming language)|Haskell]]
| |
| | <tt>map ''func'' ''list''</tt>
| |
| | <tt>zipWith ''func'' ''list1'' ''list2''</tt>
| |
| | <tt>zipWith''n'' ''func'' ''list1'' ''list2'' ...</tt>
| |
| | <tt>''n''</tt> corresponds to the number of lists; predefined up to <tt>''zipWith7''</tt>
| |
| | stops after the shortest list ends
| |
| |- valign="top"
| |
| | [[Groovy (programming language)|Groovy]]
| |
| | list.collect(lambda)
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |- valign="top"
| |
| | [[haXe]]
| |
| | <tt>''array''.map(''func'')</tt>
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |- valign="top"
| |
| | [[J (programming language)|J]]
| |
| | <tt>''func'' ''list''</tt>
| |
| | <tt>''list'' ''func'' ''list''</tt>
| |
| | <tt>''func''/ ''list1'', ''list2'', ''list3'', : ''list4''</tt>
| |
| | J's array processing capabilities make operations like map implicit
| |
| | length error if lists not equal
| |
| |- valign="top"
| |
| | [[JavaScript]] 1.6
| |
| | [https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map ''array''#map(''func'')]
| |
| | <tt>''List1''.map(function (elem1, i) { <br />return ''func''(elem1, ''List2''[i]); })</tt>
| |
| | <tt>''List1''.map(function (elem1, i) { <br />return ''func''(elem1, ''List2''[i], ''List3''[i], ...); })</tt>
| |
| | Array#map passes 3 arguments to ''func'': the element, the index of the element, and the array. Unused arguments can be omitted.
| |
| | Stops at the end of ''List1'', extending the shorter arrays with ''undefined'' items if needed.
| |
| |- valign="top"
| |
| | [[Logtalk]]
| |
| | <tt>map(''Closure'', ''List'')</tt>
| |
| | <tt>map(''Closure'', ''List1'', ''List2'')</tt>
| |
| | <tt>map(''Closure'', ''List1'', ''List2'', ''List3'', ...) (up to seven lists)</tt>
| |
| | Only the ''Closure'' argument must be instantiated.
| |
| | Failure
| |
| |- valign="top"
| |
| | [[Mathematica]]
| |
| | <tt>''func'' /@ ''list'' <br /> Map[''func'', ''list'']</tt>
| |
| | <tt>MapThread[''func'', {''list1'', ''list2''}]</tt>
| |
| | <tt>MapThread[''func'', {''list1'', ''list2'', ...}]</tt>
| |
| |
| |
| | Lists must be same length
| |
| |- valign="top"
| |
| | [[Maxima (software)|Maxima]]
| |
| | <tt>map(''f'', ''expr<sub>1</sub>'', ..., ''expr<sub>n</sub>'')<br />maplist(''f'', ''expr<sub>1</sub>'', ..., ''expr<sub>n</sub>'')</tt>
| |
| |
| |
| |
| |
| | map returns an expression whose leading operator is the same as that of the expressions;<br />maplist returns a list
| |
| |
| |
| |- valign="top"
| |
| | [[OCaml]]
| |
| | <tt>List.map ''func'' ''list''<br /> Array.map ''func'' ''array''</tt>
| |
| | <tt>List.map2 ''func'' ''list1'' ''list2''</tt>
| |
| |
| |
| |
| |
| | raises Invalid_argument exception
| |
| |- valign="top"
| |
| | [[PARI/GP]]
| |
| | <tt>apply(''func'', ''list'')</tt>
| |
| |
| |
| |
| |
| |
| |
| | {{n/a}}
| |
| |- valign="top"
| |
| | [[Perl]]
| |
| | <tt>map ''block'' ''list''<br /> map ''expr'', ''list''</tt>
| |
| |
| |
| |
| |
| | In ''block'' or ''expr'' special variable ''$_'' holds each value from list in turn.
| |
| | Helper <tt>''List::MoreUtils::each_array''</tt> combines more than one list until the longest one is exhausted, filling the others with <tt>''undef''.</tt>
| |
| |- valign="top"
| |
| | [[PHP]]
| |
| | <tt>array_map(''callback'', ''array'')</tt>
| |
| | <tt>array_map(''callback'', ''array1'',''array2'')</tt>
| |
| | <tt>array_map(''callback'', ''array1'',''array2'', ...)</tt>
| |
| | The number of parameters for ''callback''<br />should match the number of arrays.
| |
| | extends the shorter lists with ''NULL'' items
| |
| |- valign="top"
| |
| | [[Prolog]]
| |
| | <tt>maplist(''Cont'', ''List1'', ''List2'').</tt>
| |
| | <tt>maplist(''Cont'', ''List1'', ''List2'', ''List3'').</tt>
| |
| | <tt>maplist(''Cont'', ''List1'', ''...'').</tt>
| |
| | List arguments are input, output or both. Subsumes also zipWith, unzip, all
| |
| | Silent failure (not an error)
| |
| |- valign="top"
| |
| | [[Python (programming language)|Python]]
| |
| | <tt>map(''func'', ''list'')</tt>
| |
| | <tt>map(''func'', ''list1'', ''list2'')</tt>
| |
| | <tt>map(''func'', ''list1'', ''list2'', ...)</tt>
| |
| | Returns a list in Python 2 and an [[iterator]] in Python 3.
| |
| | <tt>''zip()''</tt> and <tt>''map()''</tt> (3.x) stops after the shortest list ends, whereas <tt>''map()''</tt> (2.x) and <tt>''itertools.zip_longest()''</tt> (3.x) extends the shorter lists with <tt>''None''</tt> items
| |
| |- valign="top"
| |
| | [[Racket (programming language)|Racket]]
| |
| | <tt>(map ''func'' ''list'')</tt>
| |
| | <tt>(map ''func'' ''list1'' ''list2'')</tt>
| |
| | <tt>(map ''func'' ''list1'' ''list2'' ...)</tt>
| |
| |
| |
| | lists must all have the same length
| |
| |- valign="top"
| |
| | [[Ruby (programming language)|Ruby]]
| |
| | <tt>''enum''.collect {''block''}<br /> ''enum''.map {''block''}</tt>
| |
| | <tt>''enum1''.zip(''enum2'')<wbr/>.map {''block''}</tt>
| |
| | <tt>''enum1''.zip(''enum2'', ...)<wbr/>.map {''block''} <br /> [''enum1'', ''enum2'', ...]<wbr/>.transpose.map {''block''}</tt>
| |
| | <tt>''enum'' is an Enumeration</tt>
| |
| | stops at the end of the object it is called on (the first list); if any other list is shorter, it is extended with ''nil'' items
| |
| |- valign="top"
| |
| | [[S (programming language)|S]]/[[R (programming language)|R]]
| |
| | <tt>lapply(''list'', ''func'')</tt>
| |
| | <tt>mapply(''func'', ''list1'', ''list2'')</tt>
| |
| | <tt>mapply(''func'', ''list1'', ''list2'', ...)</tt>
| |
| |
| |
| | Shorter lists are cycled
| |
| |- valign="top"
| |
| | [[Scala (programming language)|Scala]]
| |
| | <tt>''list''.map(''func'')</tt>
| |
| | <tt>(''list1'', ''list2'')<wbr/>.zipped.map(''func'')</tt>
| |
| | <tt>(''list1'', ''list2'', ''list3'')<wbr/>.zipped.map(''func'')</tt>
| |
| | note: more than 3 not possible.
| |
| | stops after the shorter list ends
| |
| |- valign="top"
| |
| | [[Scheme (programming language)|Scheme]]
| |
| | <tt>(map ''func'' ''list'')</tt>
| |
| | <tt>(map ''func'' ''list1'' ''list2'')</tt>
| |
| | <tt>(map ''func'' ''list1'' ''list2'' ...)</tt>
| |
| |
| |
| | lists must all have same length
| |
| |- valign="top"
| |
| | [[Smalltalk]]
| |
| | <tt>''aCollection'' collect: ''aBlock''</tt>
| |
| | <tt>''aCollection1'' with: ''aCollection2'' collect: ''aBlock''</tt>
| |
| |
| |
| |
| |
| | Fails
| |
| |- valign="top"
| |
| | [[Standard ML]]
| |
| | <tt>map ''func'' ''list''</tt>
| |
| | <tt>ListPair.map ''func'' (''list1'', ''list2'') <br /> ListPair.mapEq ''func'' (''list1'', ''list2'')</tt>
| |
| |
| |
| | For 2-argument map, ''func'' takes its arguments in a tuple
| |
| | <tt>''ListPair.map''</tt> stops after the shortest list ends, whereas <tt>''ListPair.mapEq''</tt> raises <tt>UnequalLengths</tt> exception
| |
| |}
| |
| | |
| ==See also== | |
| * [[Filter (higher-order function)]]
| |
| * [[List comprehension]]
| |
| * [[foreach]]
| |
| * [[Fold (higher-order function)]]
| |
| * [[Convolution (computer science)]], (also known as ''conv'' or ''zip'')
| |
| * [[Free monoid]]
| |
| * [[MapReduce]]
| |
| | |
| ==References==
| |
| <References/>
| |
| | |
| [[Category:Higher-order functions]]
| |
| [[Category:Programming language comparisons]]
| |
| [[Category:Articles with example Haskell code]]
| |
| [[Category:Iteration in programming]]
| |