# Why does my threaded function need to be substituted?

In my code I have

With[
{
rowCells=(genCells[#]&/@genSpecs[#])&/@clueRows,
colCells=(genCells[#]&/@genSpecs[#])&/@clueCols
},
While[Not@isDone@Flatten@constraintTable,
constraintTable=(Thread[f[rowCells,constraintTable]]/.f-> constraintStrip);
constraintTable=(Thread[f[colCells,constraintTable\[Transpose]]]
/.f-> constraintStrip)\[Transpose];
]
]


but when I attempt to replace the substitutions for f with

With[
{
rowCells=(genCells[#]&/@genSpecs[#])&/@clueRows,
colCells=(genCells[#]&/@genSpecs[#])&/@clueCols
},
While[Not@isDone@Flatten@constraintTable,
constraintTable=(Thread[constraintStrip[rowCells,constraintTable]]);
constraintTable=(Thread[constraintStrip[colCells,constraintTable\[Transpose]]]
/.f-> constraintStrip)\[Transpose];
]
]


I get

Transpose::nmtx: The first two levels of {Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0],Transpose[0]} cannot be transposed. >>
Transpose::nmtx: "The first two levels of {Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[],Transpose[]} cannot be transposed. \!\(\*ButtonBox[\">>\",


Why do I need to substitute in this way? How can avoid having to do so?

I have a similar issue with

showTable[t_]:=
Grid[
Join[
Join[
ConstantArray["",{9,9},(Style[#,Bold]&/@PadLeft[#,9,""]&/@clueCols)]\[Transpose],
(Thread[f[(Style[#,Bold]&/@PadLeft[#,9,""]&/@clueRows),
(t/.cellGraphics)
]
]/.f->Join)
],
gridSpecs
];


where a substitution is also required in Thread to avoid errors.

• Thread evaluates its argument before threading, so perhaps the problem comes from evaluating constraintStrip[rowCells,constraintTable]. – Simon Woods Dec 14 '15 at 21:20
• @SimonWoods: How can it thread over something if it evaluates the whole thing first? – orome Dec 14 '15 at 21:23
• For many things that's no problem: Thread[{a,b}->{1,2} yields {a->1,b->2}, which is quite useful. – Sjoerd C. de Vries Dec 14 '15 at 21:26
• If that is the source of the problem, the question is essentially a duplicate of this one – Simon Woods Dec 14 '15 at 21:27
• It's not messed up, {1,2,3}=={1,2,3} evaluates to True - what do you think the result of Thread[True] should be? – Simon Woods Dec 14 '15 at 22:06

## 1 Answer

If you want to avoid the substitution, it might be more "elegant" to use MapThread:

MapThread[Join, {colCells, constraintTable\[Transpose]}]


This works like Thread, but Join directly operates on the right arguments.

• Yes, MapThread gives the expected behavior, but why have Thread behave this way at all? – orome Dec 14 '15 at 23:07
• @raxacoricofallapatorius Beacause Thread has not attributes like HoldAll and the like, so it first evaluates its arguments, as you can see evaluating Thread[(Print["f"]; f)[(Print["a"]; {a1, a2, a3}), (Print["b"]; {b1, b2, b3})]]. This prints "f", "a" and "b" and then threads f over the two list. – user8074 Dec 14 '15 at 23:15
• But why have Thread do that? Why have Thread designed to not thread in some cases. – orome Dec 14 '15 at 23:16
• @raxacoricofallapatorius, the error comes from the effect of Join, not from from the behavior of Thread: when Join evaluates its arguments (before Thread acts, since the evaluations start from the leaves of the expression tree) it produces a single list, with the wrong shape for Thread. The reason why Thread is not holding it's argument should be explained by MMA designers. – user8074 Dec 14 '15 at 23:25
• I don't think Join comes into play in the first case though, where f is constraintStrip. – orome Dec 14 '15 at 23:28