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.

I am trying to use Sow/Reap to replace Append in my code. The problem is that I need to define the tags within my code, but doing so doesn't reap the desired results. A simplified version of my code is

Clear[tag];
Reap[tag = {a,b}; Sow[1, a];Sow[2,b];, tag]

However, if I define my tag outside of Reap, then it works

Clear[tag];
tag = {a,b};
Reap[Sow[1, a];Sow[2,b];, tag]

Any ideas as to how I can define tags within my code?

share|improve this question
    
In short, the reason is the HoldFirst attribute of Reap. This attribute is necessary for Reap to be influence the evaluation of its first argument. –  Szabolcs Jun 4 '12 at 15:59
    
@Szabolcs I think what is basically asked here is whether or not Reap can work with filtering tags which are only known when the code inside Reap is running. In such formulation, it makes perfect sense, but alas the answer is no. But one can always filter after the fact, and with a similar run-time performance (but possibly at the expense of memory use). –  Leonid Shifrin Jun 4 '12 at 19:20
add comment

migrated from stackoverflow.com Jun 4 '12 at 17:18

This question came from our site for professional and enthusiast programmers.

1 Answer

up vote 6 down vote accepted

Reap does not work that way: when you provide a list of tags for Reap only these tags are "watched for" and collected. This allows for much better memory management than collecting for all tags and discarding at the end.

In essence it works something like this for declared tags 1, 2, 3:

{one, two, three} = {{},{},{}};

sow[x_, 1] := (one   = {one, x};   x)
sow[x_, 2] := (two   = {two, x};   x)
sow[x_, 3] := (three = {three, x}; x)
sow[x_, _] := x

SeedRandom[1]
Do[sow[i, RandomInteger[10^6]], {i, 10^7}]

Flatten /@ {one, two, three}

MaxMemoryUsed[]
{{30003, 1238414, 1529333, 3074569, 3401105, 4162839, 4715096, 5855206, 5971795, 6984287},
 {238730, 652982, 946353, 1821955, 2018277, 2065726, 4483637,
  4591412, 4733380, 4920935, 5283043, 5816356, 8272260, 8409277},
 {2793919, 2803799, 3784289, 5018439, 6380588, 8799862, 9301537}}

15034792

You can see that advance knowledge of the tags is needed to set this up. Compare to the memory requirements of this:

SeedRandom[1]

Cases[
 {#[[All, 1]], #[[1, 2]]} & /@
   Table[{i, RandomInteger[10^6]}, {i, 10^7}] ~GatherBy~ Last,
 {_, 1 | 2 | 3},
 {1}
]

MaxMemoryUsed[]
{{{30003, 1238414, 1529333, 3074569, 3401105, 4162839, 4715096, 
   5855206, 5971795, 6984287}, 1},
 {{238730, 652982, 946353, 1821955, 2018277, 2065726, 4483637, 
   4591412, 4733380, 4920935, 5283043, 5816356, 8272260, 8409277}, 2},
 {{2793919, 2803799, 3784289, 5018439, 6380588, 8799862, 9301537}, 3}}

605960144

If you wish to replace Append with something more efficient, consider using linked lists as I did in the sow example above, or the Internal`Bag class of functions.

share|improve this answer
add comment

Your Answer

 
discard

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.