Skip to main content

functional style - Why are we so sure about Map results?


I do abuse it often but when I have faced this feature first time I was really suprised:


i = 0;
(i++; # - i) & /@ Range[5]



{0, 0, 0, 0, 0}



What am I asking about is how do we know Map will do 'mapping' position after position? Of course it might look logical but it is not stated, and then, since I know nothing about memory allocation etc., I could expect strange results. To be more precise, I could expect them only in cases where mapping funcion is changing during mapping.


I have failed to find a word in documentation, only related but not important in this case:



Leaves are visited before roots





Have I missed something?




Answer



I'm afraid my comment was too obscure to be noticed. Further, I disagree with one premise somewhere in the commentary, and I wish to make a fuller explanation to see if I understand correctly or incorrectly. Finally, I think the question is answered in the documentation on the Standard Evaluation Procedure:




  • Evaluate the head of the expression.

  • Evaluate each element in turn.

  • Apply transformations associated with the attributes Orderless, Listable, and Flat.

  • Apply any definitions that you have given.

  • Apply any built-in definitions.

  • Evaluate the result.




The first two implies that parts 0, 1, 2,... will be evaluated in order (unless one cavils that "in turn" does not imply order).


When Map[f, {1, 2, 3}] is evaluated, we get, after Map, f, and {1, 2, 3} are evaluated,


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

Next this List is evaluated, with f[1], f[2], f[3] being evaluated in turn. Thus with the OP's function, the side effect on i is defined. Trace will show that what happens conforms to standard evaluation (of course).


Note that the mapping part (applying f to each element of {1, 2, 3}) might be done in any order. What matters is that the intermediate list {f[1], f[2], f[3]} is then evaluated in a defined order (left-to-right).


So, I think this behavior is defined by the documentation.





Edit: An additional Reference


In the tutorial on Evaluation, it states in "an expression like h[Subscript[e, 1], Subscript[e, 2]\[Ellipsis]], Mathematica evaluates "each element Subscript[e, i] in turn." I think the "in turn" with the reference to the subscript i must mean in the natural order of 1, 2,.... There always seem to be questions of interpretation in documentation, but if writers did not mean that, I think they could be fairly criticized for misleading users, which I doubt they are.


Comments

Popular posts from this blog

front end - keyboard shortcut to invoke Insert new matrix

I frequently need to type in some matrices, and the menu command Insert > Table/Matrix > New... allows matrices with lines drawn between columns and rows, which is very helpful. I would like to make a keyboard shortcut for it, but cannot find the relevant frontend token command (4209405) for it. Since the FullForm[] and InputForm[] of matrices with lines drawn between rows and columns is the same as those without lines, it's hard to do this via 3rd party system-wide text expanders (e.g. autohotkey or atext on mac). How does one assign a keyboard shortcut for the menu item Insert > Table/Matrix > New... , preferably using only mathematica? Thanks! Answer In the MenuSetup.tr (for linux located in the $InstallationDirectory/SystemFiles/FrontEnd/TextResources/X/ directory), I changed the line MenuItem["&New...", "CreateGridBoxDialog"] to read MenuItem["&New...", "CreateGridBoxDialog", MenuKey["m", Modifiers-...

How to thread a list

I have data in format data = {{a1, a2}, {b1, b2}, {c1, c2}, {d1, d2}} Tableform: I want to thread it to : tdata = {{{a1, b1}, {a2, b2}}, {{a1, c1}, {a2, c2}}, {{a1, d1}, {a2, d2}}} Tableform: And I would like to do better then pseudofunction[n_] := Transpose[{data2[[1]], data2[[n]]}]; SetAttributes[pseudofunction, Listable]; Range[2, 4] // pseudofunction Here is my benchmark data, where data3 is normal sample of real data. data3 = Drop[ExcelWorkBook[[Column1 ;; Column4]], None, 1]; data2 = {a #, b #, c #, d #} & /@ Range[1, 10^5]; data = RandomReal[{0, 1}, {10^6, 4}]; Here is my benchmark code kptnw[list_] := Transpose[{Table[First@#, {Length@# - 1}], Rest@#}, {3, 1, 2}] &@list kptnw2[list_] := Transpose[{ConstantArray[First@#, Length@# - 1], Rest@#}, {3, 1, 2}] &@list OleksandrR[list_] := Flatten[Outer[List, List@First[list], Rest[list], 1], {{2}, {1, 4}}] paradox2[list_] := Partition[Riffle[list[[1]], #], 2] & /@ Drop[list, 1] RM[list_] := FoldList[Transpose[{First@li...

plotting - Magnifying Glass on a Plot

Although there is a trick in TEX magnifying glass but I want to know is there any function to magnifying glass on a plot with Mathematica ? For example for a function as Sin[x] and at x=Pi/6 Below, this is just a picture desired from the cited site. the image got huge unfortunately I don't know how can I change the size of an image here! Answer Insetting a magnified part of the original Plot A) by adding a new Plot of the specified range xPos = Pi/6; range = 0.2; f = Sin; xyMinMax = {{xPos - range, xPos + range}, {f[xPos] - range*GoldenRatio^-1, f[xPos] + range*GoldenRatio^-1}}; Plot[f[x], {x, 0, 5}, Epilog -> {Transparent, EdgeForm[Thick], Rectangle[Sequence @@ Transpose[xyMinMax]], Inset[Plot[f[x], {x, xPos - range, xPos + range}, Frame -> True, Axes -> False, PlotRange -> xyMinMax, ImageSize -> 270], {4., 0.5}]}, ImageSize -> 700] B) by adding a new Plot within a Circle mf = RegionMember[Disk[{xPos, f[xPos]}, {range, range/GoldenRatio}]] Show...