I admit that I have been reluctant to use Reap
and Sow
for years and that I used it only when I had no choice with EvaluationMonitor
.
That is partly because the documentation was difficult for me and partly because I could not think of any scenario where that would be useful. My impression is that I am not the only one that avoids Reap/Sow constructs.
However, I am noticing that it can be useful. Here are some examples:
Sub expressions
Obtaining a list of sub-expressions :
Reap[expression /.
x : pattern :> Sow[x]]
Depending on the pattern that might differ from
Cases[expression,pattern,All]
Example:
Cases[{x, x^2, m[x]*m[y]*e}, m[a_]*m[b_], All]
{}
Reap[{x, x^2, m[x]*m[y]*e} /. x : m[a_]*m[b_] :> Sow[x]][[2, 1]]
{m[x] m[y]}
Substitution for AppendTo
.
Compare :
l = {};
Do[AppendTo[l, RandomReal[]], 10^5] // AbsoluteTiming
10.8
seconds
with
l = {};
Reap[Do[Sow[RandomReal[]], 10^5]][[2, 1]]; // AbsoluteTiming
0.06
seconds
AppendTo
is slow because it copies the list each time. See the following links for further details on AppendTo
:
https://mathematica.stackexchange.com/a/72625/86543
and point 3 and 5 in this answer:
https://mathematica.stackexchange.com/a/29351/86543
See also the following for a way to reproduce and enhance Reap/Sow:
https://mathematica.stackexchange.com/a/244033/86543
EvaluationMonitor
or StepMonitor
Nothing much to say other than check out the documentation but I am guilty of not using this to check why FindRoot
or Plot
is not converging or is slow.
Debugging
I use Echo
usually but if one needs to extract a lot of intermediate parts in a code and check how they relate to each other using another code, then copy pasting Echo outputs would be overly complicated.
Also, Reap
and Sow
could be helpful to check what Map
, MapAt
, MapAll
, SubsetMap
is working on especially if one included a level specification. That said, I prefer taking a small example and using Framed
Finding specific terms using functions that take a function as an argument
For example one may have wrote a code that acts only on specific terms using a function argument. A quick way to extract those specific terms is to use Reap
and Sow
.
Arbitrary depth and position categorization
One can use Reap/Sow with tags in combination with MapAt
, MapAll
,MapBlock
, MapIndexed
, ArrayReduce
etc to generalize Select
and Gather
to different depths and positions.
Example 1:
Gather sub-expressions of an expression by LeafCount:
Reap[MapAll[Sow[#, LeafCount[#]] &,
Integrate[1/(1 + Tan[x]^20), x]]][[2]] // Map[DeleteDuplicates]
Example 2:
Gather and select columns of a matrix depending on whether the sum of elements of the column is prime:
(
Reap[
ArrayReduce[
Sow[{#,PrimeQ@Total@#}
,
PrimeQ[Total@#]
]&
,
EchoFunction[MatrixForm]@
Array[RandomInteger[40]&,{3,4}]
,
1
]
][[2]]
//Map[MatrixForm,#,{2,Infinity}]&
)
The matrix:
$$ \left( \begin{array}{cccc} 13 & 13 & 25 & 28 \\ 21 & 26 & 7 & 28 \\ 9 & 35 & 21 & 4 \\ \end{array} \right) $$
The gathered columns:
$$\left( \begin{array}{cc} \{\{13,21,9\},\text{True}\} & \{\{25,7,21\},\text{True}\} \\ \{\{13,26,35\},\text{False}\} & \{\{28,28,4\},\text{False}\} \\ \end{array} \right)$$
If we want to select only the column where the sum of elements is prime than we can add an extra argument True at the end in the Reap
command.
I should also mention SelectEquivalents from this answer:
https://stackoverflow.com/a/6245166
but I am not sure how to use it in practice.
What else ?