Exercise 5.2.1 from Wagner's Book: implement myMapThread in terms of Thread/Apply such that it works with the Power/Equal examples below.

My Attempt:

In[3]:= myMapThread[func_, list_] := 
  Thread[(Apply[func, #] &)[list]];
myMapThread[Power, {{a, b, c}, 3}]
myMapThread[Equal, {{1, 2, 3}, {1, 2, 4}}]

Out[4]= {a^3, b^3, c^3}

Out[5]= False

In[6]:= myMapThread[func_, list_] := 
  Thread[Unevaluated[(Apply[func, #] &)[list]]];
myMapThread[Power, {{a, b, c}, 3}]
myMapThread[Equal, {{1, 2, 3}, {1, 2, 4}}]

Out[7]= {a^b^c, 3}

Out[8]= {False, False}


1) I screwed up. What is the correct answer?

2) What am I doing wrong?


1 Answer 1


You were doing it right, but Equal is peculiar in that it is also defined on lists, and returns single False if the lists are not exactly equal, and single True if they are. During the evaluation of myMapThread (say, with a generic function f), there is a stage like this:


(*  f[{1,2,3},{1,2,4}]  *)

And if you have Equal in place of f, it evaluates at this stage, before Thread has a chance to execute. In fact, Wagner emphasized this point in his main text, and I also discussed this here.

This is how I would do this: use Apply at level 1:

myMapThreadLS[f_, arg_List] := f @@@ Thread[arg];

This avoids this problem, since threading is guaranteed to happen here before the function is applied. To cure your version, there are probably better alternatives, but one which comes to mind right now is to use a dummy symbol without rules attached to it, in place of the function being applied, and substitute it with that function at the end:

myMapThreadAlt[func_, list_] :=
     Thread[(Apply[f, #] &)[list]] /. f -> func];

But, if you look at it, essentially this is doing the same as my shorter solution above, just in a slightly more complex way.


Here is another way, which utilizes pattern-matching, and is closer to Wagner's discussion in the main text:

myMapThread2[f_, {parts__}] := Thread[Unevaluated[f[parts]]]

This has an advantage that you don't need two traversals of the threaded argument list, since pattern-matching is used to inject the list parts directly as a sequence, and then Apply is not needed.

  • $\begingroup$ Very nice. Thanks! I like the f @@@ Thread[arg] solution. $\endgroup$
    – user1602
    Jul 16, 2012 at 9:20
  • $\begingroup$ one more question. Where in "?Thread", does it suggest that "Thread[{{a, b, c}, 3}]" is valid use of Thread? it seems to imply we need Thread[f[{{a,b,c}, 3}]] $\endgroup$
    – user1602
    Jul 16, 2012 at 9:21
  • $\begingroup$ @term-rewritica Glad I could help, and thanks for the accept. As to your question: Thread[{{a, b, c}, 3}] is just Thread[List[{a, b, c}, 3]], if you recall that everything is an expression and {a,b,c} is List[a,b,c] (for example), so this is perfectly valid. $\endgroup$ Jul 16, 2012 at 9:25
  • $\begingroup$ Darn, you got both forms. +1 :^) $\endgroup$
    – Mr.Wizard
    Jul 16, 2012 at 17:22
  • $\begingroup$ @Mr.Wizard Well, I knew that if I leave any chance for another (not too exotic to be off-topic) solution, you'd take it :-). Thanks for the upvote. $\endgroup$ Jul 16, 2012 at 17:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.