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.

Problem:

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}

Question

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

2) What am I doing wrong?

share|improve this question

1 Answer 1

up vote 6 down vote accepted

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}}]

(*  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_] :=
  Module[{f},
     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.

EDIT

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.

share|improve this answer
    
Very nice. Thanks! I like the f @@@ Thread[arg] solution. –  user1602 Jul 16 '12 at 9:20
    
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}]] –  user1602 Jul 16 '12 at 9:21
    
@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. –  Leonid Shifrin Jul 16 '12 at 9:25
    
Darn, you got both forms. +1 :^) –  Mr.Wizard Jul 16 '12 at 17:22
    
@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. –  Leonid Shifrin Jul 16 '12 at 17:28

Your Answer

 
discard

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