Content deleted Content added
mNo edit summary |
undo User:Ushkin N |
||
Line 90:
==Language comparison==
The map function originated in [[functional programming]] languages.
The [[Lisp (programming language)|Lisp programming language]] introduced a map function called <code>maplist</code><ref>[http://www.softwarepreservation.org/projects/LISP/MIT/LISP_Prog_Man-Mar_1959.pdf/view J. McCarthy, K. Maling, S. Russell, N. Rochester, S. Goldberg, J. Slagle. LISP Programmer's Manual. March-April, 1959]</ref> in 1959, with slightly different versions already appearing in 1958.<ref>[http://www.softwarepreservation.org/projects/LISP/MIT/AIM-004.pdf/view J. McCarthy: Symbol Manipulating Language - Revisions of the Language. AI Memo No. 4, October 1958]</ref> This is the original definition for <code>maplist</code>, mapping a function over successive rest lists:
<source>
maplist[x;f] = [null[x] -> NIL;T -> cons[f[x];maplist[cdr[x];f]]]
</source>
The function <code>maplist</code> is still available in newer Lisps like [[Common Lisp]],<ref>[http://www.lispworks.com/documentation/HyperSpec/Body/f_mapc_.htm Function MAPC, MAPCAR, MAPCAN, MAPL, MAPLIST, MAPCON in ANSI Common Lisp]</ref> though functions like <code>mapcar</code> or the more generic <code>map</code> would be preferred.
Squaring the elements of a list using <code>maplist</code> would be written in s-expression notation like this:
<source lang="lisp">
(maplist (function (lambda (l)
(sqr (car l))))
'(1 2 3 4 5))
</source>
Using the function <code>mapcar</code>, above example would be written like this:
<source lang="lisp">
(mapcar (function sqr) '(1 2 3 4 5))
</source>
Today mapping functions are 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>std::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 [[CFML]], [[Perl]], [[Python (programming language)|Python]] and [[Ruby (programming language)|Ruby]]; the operation is called <code>map</code> in all four 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, <code>map</code> may be [[partial application|partially applied]] to ''lift'' a function that only works on a single value to an element-wise equivalent that works on an entire container; for instance, <code>map square</code> is a Haskell function which squares each element of a list.
{| class="wikitable"
|+ Map in various languages
! Language !! Map !! Map 2 lists !! Map n lists !! Notes !! Handling lists of different lengths
|- valign="top"
| [[Common Lisp]]
| <code>(mapcar ''func'' ''list'')</code>
| <code>(mapcar ''func'' ''list1'' ''list2'')</code>
| <code>(mapcar ''func'' ''list1'' ''list2'' ...)</code>
|
| stops after the length of the shortest list
|- valign="top"
| [[C++]]
| <code>std::transform(<wbr/>''begin'', ''end'', ''result'', ''func'')</code>
| <code>std::transform(<wbr/>''begin1'', ''end1'', ''begin2'', ''result'', ''func'')</code>
|
| in header <algorithm><br /> ''begin'', ''end'', and ''result'' are iterators<br /> result is written starting at ''result''
|
|- valign="top"
| [[C Sharp (programming language)|C#]]
| <code>''ienum''.Select(''func'')</code><br/>or<br/>[https://msdn.microsoft.com/en-us/library/bb384087.aspx The <code>select</code> clause]
| <code>''ienum1''.Zip(''ienum2'', ''func'')</code>
|
| <code>Select</code> is an extension method<br /> ''ienum'' is an IEnumerable<br /><code>Zip</code> is introduced in .NET 4.0<br />Similarly in all .NET languages
| stops after the shortest list ends
|- valign="top"
| [[CFML]]
| <code>obj.map(func)</code>
|
|
| Where <code>obj</code> is an array or a structure. <code>func</code> receives as arguments each item's value, its index or key, and a reference to the original object.
|
|- valign="top"
| [[Clojure]]
| <code>(map ''func'' ''list'')</code>
| <code>(map ''func'' ''list1'' ''list2'')</code>
| <code>(map ''func'' ''list1'' ''list2'' ...)</code>
|
| stops after the shortest list ends
|- valign="top"
| [[D (programming language)|D]]
| <code>''list''.map!''func''</code>
| <code>zip(''list1'', ''list2'').map!''func''</code>
| <code>zip(''list1'', ''list2'', ...).map!''func''</code>
|
| Specified to zip by StoppingPolicy: shortest, longest, or requireSameLength
|- valign="top"
| [[Erlang (programming language)|Erlang]]
| <code>lists:map(''Fun'', ''List'')</code>
| <code>lists:zipwith(''Fun'', ''List1'', ''List2'')</code>
| <code>''zipwith3''</code> also available
|
| Lists must be equal length
|- valign="top"
| [[Elixir (programming language)|Elixir]]
| <code>Enum.map(''list'', ''fun'')</code>
| <code>Enum.zip(''list1'', ''list2'') |> Enum.map(fun)</code>
| <code>List.zip([''list1'', ''list2'', ...]) |> Enum.map(fun)</code>
|
| stops after the shortest list ends
|- valign="top"
| [[F sharp (programming language)|F#]]
| <code>List.map ''func'' ''list''</code>
| <code>List.map2 ''func'' ''list1'' ''list2''</code>
|
| Functions exist for other types (''Seq'' and ''Array'')
| Throws exception
|- valign="top"
| [[Haskell (programming language)|Haskell]]
| <code>map ''func'' ''list''</code>
| <code>zipWith ''func'' ''list1'' ''list2''</code>
| <code>zipWith''n'' ''func'' ''list1'' ''list2'' ...</code>
| <code>''n''</code> corresponds to the number of lists; predefined up to <code>''zipWith7''</code>
| stops after the shortest list ends
|- valign="top"
| [[Groovy (programming language)|Groovy]]
| <code>list.collect(func)</code>
| <code>[list1 list2]<wbr>.transpose()<wbr>.collect(func)</code>
| <code>[list1 list2 ...]<wbr>.transpose()<wbr>.collect(func)</code>
|
|
|- valign="top"
| [[Haxe]]
| <code>''array''.map(''func'')<br>
''list''.map(''func'')<br>
Lambda.map(''iterable'', ''func'')
</code>
|
|
|
|
|- valign="top"
| [[J (programming language)|J]]
| <code>''func'' ''list''</code>
| <code>''list1'' ''func'' ''list2''</code>
| <code>''func''/ ''list1'', ''list2'', ''list3'' ,: ''list4''</code>
| J's array processing capabilities make operations like map implicit
| length error if list lengths not equal
|- valign="top"
| [[Java (programming language)|Java]] 8+
| <code>''stream''.map(''func'')</code>
|
|
|
|
|- valign="top"
| [[JavaScript]] 1.6<br>[[ECMAScript]] 5
| [https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map <code>''array''#map(''func'')</code>]
| <code>''List1''.map(function (elem1, i) { <br />return ''func''(elem1, ''List2''[i]); })</code>
| <code>''List1''.map(function (elem1, i) { <br />return ''func''(elem1, ''List2''[i], ''List3''[i], ...); })</code>
| 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]]
| <code>map(''Closure'', ''List'')</code>
| <code>map(''Closure'', ''List1'', ''List2'')</code>
| <code>map(''Closure'', ''List1'', ''List2'', ''List3'', ...) (up to seven lists)</code>
| Only the ''Closure'' argument must be instantiated.
| Failure
|- valign="top"
| [[Mathematica]]
| <code>''func'' /@ ''list'' <br /> Map[''func'', ''list'']</code>
| <code>MapThread[''func'', {''list1'', ''list2''}]</code>
| <code>MapThread[''func'', {''list1'', ''list2'', ...}]</code>
|
| Lists must be same length
|- valign="top"
| [[Maxima (software)|Maxima]]
| <code>map(''f'', ''expr<sub>1</sub>'', ..., ''expr<sub>n</sub>'')<br />maplist(''f'', ''expr<sub>1</sub>'', ..., ''expr<sub>n</sub>'')</code>
|
|
| map returns an expression whose leading operator is the same as that of the expressions;<br />maplist returns a list
|
|- valign="top"
| [[OCaml]]
| <code>List.map ''func'' ''list''<br /> Array.map ''func'' ''array''</code>
| <code>List.map2 ''func'' ''list1'' ''list2''</code>
|
|
| raises Invalid_argument exception
|- valign="top"
| [[PARI/GP]]
| <code>apply(''func'', ''list'')</code>
|
|
|
| {{n/a}}
|- valign="top"
| [[Perl]]
| <code>map ''block'' ''list''<br /> map ''expr'', ''list''</code>
|
|
| In ''block'' or ''expr'' special variable ''$_'' holds each value from list in turn.
| Helper <code>''List::MoreUtils::each_array''</code> combines more than one list until the longest one is exhausted, filling the others with <code>''undef''.</code>
|- valign="top"
| [[PHP]]
| <code>array_map(''callable'', ''array'')</code>
| <code>array_map(''callable'', ''array1'',''array2'')</code>
| <code>array_map(''callable'', ''array1'',''array2'', ...)</code>
| The number of parameters for ''callable''<br />should match the number of arrays.
| extends the shorter lists with ''NULL'' items
|- valign="top"
| [[Prolog]]
| <code>maplist(''Cont'', ''List1'', ''List2'').</code>
| <code>maplist(''Cont'', ''List1'', ''List2'', ''List3'').</code>
| <code>maplist(''Cont'', ''List1'', ''...'').</code>
| List arguments are input, output or both. Subsumes also zipWith, unzip, all
| Silent failure (not an error)
|- valign="top"
| [[Python (programming language)|Python]]
| <code>map(''func'', ''list'')</code>
| <code>map(''func'', ''list1'', ''list2'')</code>
| <code>map(''func'', ''list1'', ''list2'', ...)</code>
| Returns a list in Python 2 and an [[iterator]] in Python 3.
| <code>''zip()''</code> and <code>''map()''</code> (3.x) stops after the shortest list ends, whereas <code>''map()''</code> (2.x) and <code>''itertools.zip_longest()''</code> (3.x) extends the shorter lists with <code>''None''</code> items
|- valign="top"
| [[Ruby (programming language)|Ruby]]
| <code>''enum''.collect {''block''}<br /> ''enum''.map {''block''}</code>
| <code>''enum1''.zip(''enum2'')<wbr/>.map {''block''}</code>
| <code>''enum1''.zip(''enum2'', ...)<wbr/>.map {''block''} <br /> [''enum1'', ''enum2'', ...]<wbr/>.transpose.map {''block''}</code>
| <code>''enum'' is an Enumeration</code>
| 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]]
| <code>lapply(''list'', ''func'')</code>
| <code>mapply(''func'', ''list1'', ''list2'')</code>
| <code>mapply(''func'', ''list1'', ''list2'', ...)</code>
|
| Shorter lists are cycled
|- valign="top"
| [[Scala (programming language)|Scala]]
| <code>''list''.map(''func'')</code>
| <code>(''list1'', ''list2'')<wbr/>.zipped.map(''func'')</code>
| <code>(''list1'', ''list2'', ''list3'')<wbr/>.zipped.map(''func'')</code>
| note: more than 3 not possible.
| stops after the shorter list ends
|- valign="top"
| [[Scheme (programming language)|Scheme]], [[Racket (programming language)|Racket]]
| <code>(map ''func'' ''list'')</code>
| <code>(map ''func'' ''list1'' ''list2'')</code>
| <code>(map ''func'' ''list1'' ''list2'' ...)</code>
|
| lists must all have same length
|- valign="top"
| [[Smalltalk]]
| <code>''aCollection'' collect: ''aBlock''</code>
| <code>''aCollection1'' with: ''aCollection2'' collect: ''aBlock''</code>
|
|
| Fails
|- valign="top"
| [[Standard ML]]
| <code>map ''func'' ''list''</code>
| <code>ListPair.map ''func'' (''list1'', ''list2'') <br /> ListPair.mapEq ''func'' (''list1'', ''list2'')</code>
|
| For 2-argument map, ''func'' takes its arguments in a tuple
| <code>''ListPair.map''</code> stops after the shortest list ends, whereas <code>''ListPair.mapEq''</code> raises <code>UnequalLengths</code> exception
|- valign="top"
| [[Swift (Apple programming language)|Swift]]
| <code>''array''.map(''func'')</code><br /> <code>map(''sequence'', ''func'')</code>
| <code>map(zip(''sequence1'', ''sequence2''), ''func'')</code>
|
|
| stops after the shortest list ends
|- valign="top"
| [[XPath 3|XPath]] 3<br/>[[XQuery]] 3
| <code>list ! block</code><br /> <code>for-each(list, func)</code>
| <code>for-each-pair(list1, list2, func)</code>
|
| In <code>block</code> the context item <code>.</code> holds the current value
| stops after the shortest list ends
|}
==See also==
Line 108 ⟶ 369:
[[Category:Higher-order functions]]
[[Category:Programming language comparisons]]
[[Category:Articles with example Haskell code]]
[[Category:Iteration in programming]]
|