Function Repository Resource:

ReapAssociation

Source Notebook

Equivalent to Reap, but returns an association with tags as keys

Contributed by: Richard Hennigan (Wolfram Research)

ResourceFunction["ReapAssociation"][expr]

gives the value of expr together with all expressions to which Sow has been applied during its evaluation. Expressions sown using Sow[e] or Sow[e,tagi] with different tags are returned as lists in an association keyed by the tags.

ResourceFunction["ReapAssociation"][expr,patt]

reaps only expressions sown with tags that match patt.

ResourceFunction["ReapAssociation"][expr,{patt1,patt2,}]

puts expressions associated with each of the patti in a separate list.

ResourceFunction["ReapAssociation"][expr,patt,f]

has values f[tagi(ei,1,ei,2,...}] for each key tagi.

Details and Options

Sow and ResourceFunction["ReapAssociation"] provide a convenient way to accumulate a list of intermediate results in a computation.
ResourceFunction["ReapAssociation"] accumulates expressions in the order in which Sow is applied to them.
Expressions sown with a particular tag are collected by the innermost ResourceFunction["ReapAssociation"] whose pattern matches the tag.
Expressions sown with no tag are returned using the tag None.
The result of evaluating the expression is returned using the key "Result", and the sown values are in an association under the key "Sown".
ResourceFunction["ReapAssociation"][expr] is equivalent to ResourceFunction["ReapAssociation"][expr,_].
ResourceFunction["ReapAssociation"] has attribute HoldFirst.

Examples

Basic Examples (3) 

Evaluate a sequence of expressions, "reaping" ones that have been "sown":

In[1]:=
ResourceFunction["ReapAssociation"][Sow[a]; b; Sow[c]; Sow[d]; e]
Out[1]=

Compute a sum, "reaping" i^2 "sown" at each step:

In[2]:=
ResourceFunction["ReapAssociation"][Sum[Sow[i^2] + 1, {i, 10}]]
Out[2]=

Make a separate key for each tag being reaped:

In[3]:=
ResourceFunction["ReapAssociation"][Sow[1, x]; Sow[2, y]; Sow[3, {x, y}]]
Out[3]=
In[4]:=
ResourceFunction["ReapAssociation"][Table[Sow[i, OddQ[i]], {i, 10}]]
Out[4]=
In[5]:=
ResourceFunction["ReapAssociation"][
 Do[Sow[i, If[PrimeQ[i], "Prime", "Composite"]], {i, 2, 100}]]
Out[5]=

Scope (2) 

If nothing is sown, an empty association will be returned in the "Sown" key:

In[6]:=
ResourceFunction["ReapAssociation"][1 + 1]
Out[6]=

Count the number of instances of each integer, separating the negative:

In[7]:=
ResourceFunction["ReapAssociation"][
 Sow[1, RandomInteger[{-9, 9}, 100]], {_?Negative, _?NonNegative}, Total[#2] &]
Out[7]=

Generalizations & Extensions (1) 

Apply f to each distinct key and list of values:

In[8]:=
ResourceFunction["ReapAssociation"][Sow[1, {x, x}]; Sow[2, y]; Sow[3, x], _, f]
Out[8]=
In[9]:=
ResourceFunction["ReapAssociation"][Sow[1, x]; Sow[2, y]; Sow[3, x], _, Echo[#2, #1] &]
Out[9]=

Applications (2) 

Find the list of values sampled by Plot:

In[10]:=
ResourceFunction["ReapAssociation"][
 Plot[Sin[x], {x, 0, 10}, EvaluationMonitor :> Sow[x]], _, Short[#2, 5] &]
Out[10]=

Remove duplicates from a list, keeping the original order:

In[11]:=
unsortedUnion[x_] := Keys[Lookup[ResourceFunction["ReapAssociation"][Sow[1, x]], "Sown"]]
In[12]:=
unsortedUnion[{b, b, c, a, c, a, b, d}]
Out[12]=

This is like Union without the sorting:

In[13]:=
Union[{b, b, c, a, c, a, b, d}]
Out[13]=

Properties & Relations (4) 

If no expressions are sown, ReapAssociation returns an empty association of expressions it has reaped:

In[14]:=
ResourceFunction["ReapAssociation"][x]
Out[14]=

ReapAssociation collects expressions in exactly the order they are sown:

In[15]:=
ResourceFunction["ReapAssociation"][MapAll[Sow, (a + b) (c + x^2)];]
Out[15]=

The list associated with the first tag to be encountered will be the first key:

In[16]:=
ResourceFunction["ReapAssociation"][Sow[1, y]; Sow[2, x]; Sow[3, y]]
Out[16]=

When the order of tags is not known, ReapAssociation can make it easier to understand results compared to Reap:

In[17]:=
SeedRandom[1];
Reap[Table[Sow[i, RandomChoice[{"a", "b", "c"}]], {i, 20}]] // Last
Out[7]=
In[18]:=
SeedRandom[1];
ResourceFunction["ReapAssociation"][
  Table[Sow[i, RandomChoice[{"a", "b", "c"}]], {i, 20}]] // Last
Out[10]=

Neat Examples (1) 

Create an animation showing the full stack history of an evaluation:

In[19]:=
fib[0] := 1;
fib[1] := 1;
fib[n_] := fib[n - 2] + fib[n - 1];
In[20]:=
ListAnimate[
 DeleteDuplicates[
  ResourceFunction["ReapAssociation"][
    StackBegin[
     TraceScan[StackInhibit[Sow[Column[Rest[Stack[_]]], "fib"]] &, Table[fib[i], {i, 5}]]]][["Sown", "fib"]]]]
Out[20]=

Requirements

Wolfram Language 11.3 (March 2018) or above

Version History

  • 1.0.0 – 06 March 2019

Related Resources

License Information