Message Boards Message Boards

0
|
4095 Views
|
4 Replies
|
3 Total Likes
View groups...
Share
Share this post:

Relationship between "Apply" and "Map"

Posted 5 years ago

I'm looking for basic help with a simple aspect of the Wolfram Language, as it's been a several years since I've actively used Mathematica (now running 12.0), and I'm stuck. (If there's a better place to post such questions, please let me know. Being retired denies me direct access to colleagues who might answer them.)

The simplest form of Map says it, "applies f to each element on the first level in expr."

The simplest form of Apply says it, "replaces the head of expr by f."

In my case "solidWorksData," is a 1-D list of 1-D lists (all the same length). If I extract one element of solidWorksData, call it "subList," and Apply a pure function of two arguments, call it "radiusOperator," to that element, I get the expected result (in this case the RMS of the two elements in "slots" 2 and 4, X and Y if you will, of subList):

radiusOperator = Sqrt[#2^2 + #4^2] &

In[42]:= solidWorksData[[1]]

Out[42]= {266138, 106.75, 73.533, -85.006, -0.00230909, -0.000852509, \
0.00228309, 0.00335725}

In[34]:= radiusOperator @@ (solidWorksData[[1]])

Out[34]= 136.461

Here's my quandary: If I now Map radiusOperator onto the entire solidWorksData, I get an error as follows:

temp = Map[radiusOperator, solidWorksData];

Function::slotn: Slot number 2 in Sqrt[#2^2+#4^2]& cannot be filled from (Sqrt[#2^2+#4^2]&)[{266138,106.75,73.533,-85.006,-0.00230909,-0.000852509,0.00228309,0.00335725}].

Function::slotn: Slot number 4 in Sqrt[#2^2+#4^2]& cannot be filled from (Sqrt[#2^2+#4^2]&)[{266138,106.75,73.533,-85.006,-0.00230909,-0.000852509,0.00228309,0.00335725}].

Function::slotn: Slot number 2 in Sqrt[#2^2+#4^2]& cannot be filled from (Sqrt[#2^2+#4^2]&)[{266139,4.3061,73.533,136.39,-0.000458164,-0.000952748,-0.00251939,0.00273221}].

General::stop: Further output of Function::slotn will be suppressed during this calculation.

It must be obvious what I'm doing wrong, but I can't see it. Can somebody please help me? -- John Willett

POSTED BY: John Willett
4 Replies

UPDATE, NOT ANSWER: This works, the levelspec = 1 being required:

In[58]:= temp = Apply[radiusOperator, solidWorksData, 1];

In[59]:= temp[[1]]

Out[59]= 136.461

But I still don't understand why Map does not work, with or without levelspec = 1. -- John Willett

POSTED BY: John Willett

You function should be called as

radiusOperator[arg1,arg2,arg3,...]

And this happened when you use Apply, since you replace the head List with a head which is your function radiusOperator

When you used Map the way you called it, the function accepts (in each call) a single argument which is a list. So, it cannot find the second and forth arguments, since there is only one argument

From the result of calling solidWorksData [[1]] it seems that solidWorksData is a matrix (or a list of lists). So, all you have to do, it to use Apply at level one

Apply[radiusOperator, solidWorksData, 1]

or just

radiusOperator@@@ solidWorksData
Posted 5 years ago

Hi John,

The use of "applies" in the documentation for Map is misleading. Map does not Apply. A better description might be "Map evaluates f for each element of the first level in expr". The following examples should help you understand the difference.

ClearAll@f;
list = {266138, 106.75, 73.533, -85.006, -0.00230909, -0.000852509, 0.00228309, 0.00335725};

(* Head of list is List *)
list // Head
(* List *)

(* Head of f applied to list is f *)
f @@ list // Head
(* f *)

(* f applied to list passes each element of list as an argument to f *)
f @@ list
(* f[266138, 106.75, 73.533, -85.006, -0.00230909, -0.000852509, 0.00228309, 0.00335725] *)

(* f mapped over list *)
f /@ list
(* {f[266138], f[106.75], f[73.533], f[-85.006], f[-0.00230909], f[-0.000852509], f[0.00228309], f[0.00335725]} *)

(* Define f that returns a list of the second and fourth arguments passed to it *)
f = {#2, #4} &

(* Apply f to list *)
f @@ list
(* {106.75, -85.006} *)

(* Since f expects 4 arguments Map fails because only one argument is passed *)
f /@ list
(* "Slot number 2 in {#2,#4}& cannot be filled from ({#2,#4}&)[266138]" *)

(* This also fails since a single argument is passed to f *)
f[list]
(* "Slot number 2 in {#2,#4}& cannot be filled from 
({#2,#4}&)[{266138,106.75,73.533,-85.006,-0.00230909,-0.000852509,0.
00228309,0.00335725}]" *)

(* To make it work, change the Head of list to Sequence *)
f[Sequence @@ list]
(* {106.75, -85.006} *)
POSTED BY: Rohit Namjoshi

The use of "applies" in the documentation for Map is misleading. Map does not Apply. A better description might be "Map evaluates f for each element of the first level in expr".<

Rohit -- This seems to be the crux of my problem. I wish Wolfram would fix it, as I think it's tripped me up in the past. If I had written my f like this:

radiusOperator = (Sqrt[#2^2 + #4^2] &) @@ # &

with two layers of slots to replace the heads of the list-of-list elements, it would have worked as originally used in Map. Nevertheless

Apply[radiusOperator, solidWorksData, 1]

with the old definition f is simpler and more direct.

Thanks much for your (and Yehuda's) help! -- John Willett

POSTED BY: John Willett
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract