Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I cannot understand the difference between Apply, Scan, and Map.

I have tried to play with these function by the codes below:

f[x_] := x^2

Map[f, {{a, b}, c}]

Output:

{{a^2, b^2}, c^2}

 Apply[f, {{a, b}, c}]

Output:

f[{a, b}, c]

Scan[f, {{a, b}, c}]

There is no output for this one.

The function of Map is understandable. But I cannot get the purpose of Apply and

Scan. What are the differences between these three function?

share|improve this question
2  
Do not define f when you do this, then it'll be much easier to understand what's going on. ...^2 threads over lists so your results don't reflect only the effect of Map, etc. but also this auto-threading. Take a look here and in the documentation page of each function. There are plenty of examples. For example the documentation clearly explains that Scan is the same as Map except it doesn't return anything. If is useful when f has a side-effect, e.g. f=Print. –  Szabolcs Apr 16 at 16:11
4  
In addition to the references given by @Szabolcs: I covered these functions in considerable detail here. –  Leonid Shifrin Apr 16 at 16:28

2 Answers 2

up vote 15 down vote accepted

These three functions are similar (speaking commonly), and in some applications any of them could be used, yet they have very different special applications.

Rudimentarily:

  • Map wraps (sub)expressions in a given Head, and returns the modified input
  • Apply replaces Heads in (sub)expressions, and returns the modified input
  • Scan "visits" (sub)expressions, evaluates each of them, and returns Null

(For each example below f should be undefined; start with ClearAll[f].)

Map

Most basically Map works like this:

f /@ head[1, 2, 3]      (* shorthand for Map[f, head[1, 2, 3], {1}] *)
head[f[1], f[2], f[3]]

As with each of the functions under discussion it can operate at different levels:

Map[f, {{1, 2}, {3, 4}}, {0}]
Map[f, {{1, 2}, {3, 4}}, {1}]
Map[f, {{1, 2}, {3, 4}}, {2}]
Map[f, {{1, 2}, {3, 4}}, {0, 2}]
f[{{1, 2}, {3, 4}}]

{f[{1, 2}], f[{3, 4}]}

{{f[1], f[2]}, {f[3], f[4]}}

f[{f[{f[1], f[2]}], f[{f[3], f[4]}]}]

Map is an additive process; it inserts additional heads into an expression at the specified levelspec and then evaluates it.

If the expression is held nothing evaluates. (Held meaning the outermost Head has an Attribute such as HoldAll. Hold has this attribute. Do not confuse the Head with the Attribute.)

Print /@ Hold[a[1, 2], b[3, 4]]
Hold[Print[a[1, 2]], Print[b[3, 4]]]

Apply

Apply works like Map, except that instead of adding a Head it replaces an existing one, if a head exists at the specified level. Unlike Map it is frequently used at levelspec {0} with the short form @@, which replaces the outermost head:

f @@ head[1, 2, 3]   (* short form of Apply[f, head[1, 2, 3], {0}] *)
f[1, 2, 3]

A second short form (@@@) exists for levelspec {1}:

f @@@ {{1, 2}, {3, 4}}
{f[1, 2], f[3, 4]}

If a sub-expression is atomic (has no operable Head) Apply does not modify it:

f @@@ head[1, 2, x + y]
head[1, 2, f[x, y]]

Note that 1 and 2 are unmodified, while x + y (which has a FullForm of Plus[x, y]) had its Head replaced.

As with Map, Apply transforms an expression and then evaluates it in entirety; if it is held evaluation does not continue:

Print @@@ Hold[a[1, 2], b[3, 4]]
Hold[Print[1, 2], Print[3, 4]]

One way to "release" this expression for evaluation is to replace Hold with something else, like List:

List @@ Print @@@ Hold[a[1, 2], b[3, 4]]

12

34

{Null, Null}

Note here that the elements 1, 2, and 3, 4 are printed by Print, but since Print[. . .] itself evaluates to Null the output of the line is {Null, Null}.

Scan

Scan is also like Map, except that each individual expression which is wrapped in the specified head is evaluated outside of the main expression, and the main expression is never returned. If we Scan a function without side-effects over an expression we get nothing:

Scan[f, head[1, 2, 3]]

(This could also be written f ~Scan~ head[1, 2, 3].) We do not even get an output line because the output is Null and Mathematica does not print a lone Null output line (by convention). If we use a function with side-effects, such as Print, we get a different result:

Scan[Print, head[1, 2, 3]]

1

2

3

Crucially Scan will carry out its evaluation even when an expression is held because it only looks at the subexpressions:

Print ~Scan~ Hold[a[1, 2], b[3, 4]]

a[1,2]

b[3,4]

Its evaluation can also be interrupted because, unlike Map and Apply which transform the entire expression, then evaluate it, Scan works incrementally:

(Print[#]; If[# > 2, Return[]]) & ~Scan~ {1, 2, 3, 4, 5}

1

2

3


Conclusion

I hope these simple examples illustrate that these three functions, while closely related, have unique characteristics that differentiate their use, and each has powerful applications that the others do not.


Notes on atomic objects

Not all expressions that have the appearance head[arguments] in FullForm are actually standard expressions in that form that can be manipulated with structural tools such as Apply. Instead they have a special internal format and they are merely displayed in the form head[arguments].

From the documentation on Atomic Objects:

All expressions in Mathematica are ultimately made up from a small number of basic or atomic types of objects.

These objects have heads that are symbols that can be thought of as "tagging" their types. The objects contain "raw data", which can usually be accessed only by functions specific to the particular type of object. You can extract the head of the object using Head, but you cannot directly extract any of its other parts.

Standard objects such as strings and integers are atomic, but so are other expressions that may not appear to be:

list = {1, "test", 1/2, 2 + 3 I};
list // FullForm
AtomQ /@ list
List[1, "test", Rational[1, 2], Complex[2, 3]]

{True, True, True, True}

Also atomic are more complex structures such as SparseArray, Graph, BooleanFunction, and (in recent versions) Image.

Atomic objects (or atoms) are handled differently from standard (compound) expression forms.

  • Rational[1, 2] is atomic even though it appears otherwise.
  • Even though 1 is formatted without an obvious head, Head will return Integer.
    (See Is there a summary of answers Head[] can give? for other examples.)

  • Apply does not work in the "normal" way on atoms:

    new @@@ list
    
    {1, "test", 1/2, 2 + 3 I}
    
  • Replace and kin often work on the apparent FullForm of atoms:

    Replace[list, head_[args__] :> {head, args}, {1}]
    
    {1, "test", {Rational, 1, 2}, {Complex, 2, 3}}
    
  • Functions may be overloaded to handle atoms differently; e.g. many functions treat a SparseArray as they would the Normal form expression:

    new @@ SparseArray[{1, 2, 3}]
    
    new[1, 2, 3]      (* not new[{1, 2, 3}] *)
    
  • Handling may appear somewhat irregular even within functions; Part will "extract" (or return) the head of Rationa[1, 2] but not anything else:

    Part[1/2, 0]
    
    Rational
    
    Part[1/2, 1]
    

    Part::partd: Part specification (1/2)[[1]] is longer than depth of object. >>

    (1/2)[[1]]
    

(Somewhat related, and perhaps of interest: Head and everything except Head?)

share|improve this answer
    
Worth to link question I think you should now :P Quite relevant but not closely related. –  Kuba Apr 16 at 20:21
1  
It may be worthwhile adding a note about things that are atomic, but not immediately obviously so, like AtomQ@Complex[1, 1] == True vs. AtomQ@Complex[1, a] == False. +1 –  rcollyer Apr 17 at 16:08
    
@Mr.Wizard Could you point me to an explanation for the syntax f ~Scan~ head[1, 2, 3]? –  Sascha Apr 18 at 9:12
    
@Sascha It is infix notation. Please see this. a ~op~ b is equivalent to op[a, b]. I use it a lot because I find it more readable than many nested brackets, but I know a lot of people don't agree with me. –  Mr.Wizard Apr 18 at 9:22
    
@Mr.Wizard Nice! +1 –  George Wolfe Apr 19 at 14:56

For a visual, animated, description of basic behavior of such functions, I recommend:

http://reference.wolfram.com/legacy/flash/

(You may want to turn on your computer's sound.)

share|improve this answer
    
As a rule we try to avoid link-only answers. (Excepting large collections.) Perhaps you could include a screen capture or something? Also, I don't see an animation for Scan. –  Mr.Wizard Apr 19 at 17:08
    
@Mr.Wizard: The whole point is that the link points to animations of how the various operators work! And given that the pages are copyright by Wolfram Research, I'm not sure it's legal to post even a static screenshot (would it be "fair use"?) But the animations are very useful ways to understand what Map, Apply, etc., do -- using a different modality than the usual static examples. –  murray Apr 19 at 21:04

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.