I hope this is not a silly question, since there are plenty of questions on Thread and MapThread. However, I still cannot quite understand the relationship between them. It seems MapThread can take a level argument, but Thread cannot. Thread can do something like Thread[f[{a, b, c}, x]], MapThread cannot. Why we have two of them?

Following two commands give the same results:

MapThread[f, {{a, b, c}, {x, y, z}}]
Thread[f[{a, b, c}, {x, y, z}]]
• "MapThread works like Thread, but takes the function and arguments separately..." - straight from the documentation. They can be used to get the same results, and each has some giblets the other lacks (e.g., specifying the head to thread over in Thread). Read, understand and experiment with the examples in the documentation, everything you ever wanted to know is there.
– ciao
Commented Jun 2, 2015 at 4:12
• @ciao does it means actually these two function are almost the same? It is a redundant design for convince. Commented Jun 2, 2015 at 4:27
• Thread has been here since V1. MapThread was added in V2, since the need to map something over sets of equal length lists is common (effectively mapping the threading over sets made up from the Nth elements of each list), made sense to add it. In addition, there are differences in evaluation - MapThread evaluates on each set as you progress, Thread attempts to evaluate the whole expression before attempting to thread it. Room (and need) for both...
– ciao
Commented Jun 2, 2015 at 5:16
• @ciao An example of this is Thread[Plus[{{1, 2, 3}, {4, 5, 6}}]] vs MapThread[Plus, {{1, 2, 3}, {4, 5, 6}}]. Commented Jun 2, 2015 at 14:32
• @ChipHurst, Shouldn't the example be "Thread[Plus[{1, 2, 3}, {4, 5, 6}]] vs MapThread[Plus, {{1, 2, 3}, {4, 5, 6}}]", which doesn't quite show what you wanted to. Perhaps Thread[Equal[{1, 2, 3}, {4, 2, 6}]] vs MapThread[Equal, {{1, 2, 3}, {4, 2, 6}}]? Commented Jun 3, 2015 at 16:55

With one addition the difference is as you describe in your own question:

• MapThread only operates upon List expressions
• MapThread does not distribute singletons
• MapThread accepts a level specification

The first characteristic simplifies threading functions that are eager to evaluate:

f = Print;
one = {a, b, c};
two = {x, y, z};

ax

by

cz

{a,b,c}{x,y,z}

In the second form Print evaluates to Null giving Thread nothing to do. To make Thread work one would need to keep Print unevaluated while allowing one and two to resolve:

Block[{Print},
];

That MapThread does not distribute singletons is something I have no explanation for. I have wished that it would work that way but I may have failed to comprehend the ramifications of that behavior. Perhaps it was determined that the interaction with level specification would be too confusing or arbitrary.

### Exploration

Here is an attempt at implementing a MapThread variant with both level and head parameters that threads over singletons, based on my earlier raggedMapThread; perhaps experimentation with it will demonstrate limitations or implementation difficulties that illuminate the reason for the existing design.

Apply[f,
Flatten[expr, List /@ Range[2, level]],
{level - 1}],
{level}]

An example:

foo,
{ReplacePart[Array[a, {3, 2, 3}], {{1, 2} -> x, {3, 2} -> z}],
ReplacePart[Array[b, {3, 2, 3}], {2, 1} -> y]},
3
] // MatrixForm

A smaller example with a different head:

foo,
bar[Array[a, {3, 2}, 1, bar], ReplacePart[Array[b, {3, 2}, 1, bar], 2 -> x]],
2,
bar
]
bar[
bar[foo[a[1, 1], b[1, 1]], foo[a[1, 2], b[1, 2]]],
bar[foo[a[2, 1], x], foo[a[2, 2], x]],
bar[foo[a[3, 1], b[3, 1]], foo[a[3, 2], b[3, 2]]]
]
• The example is very helpful! Commented Jun 4, 2015 at 6:53