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've noticed a behaviour of Reap that I don't quite understand yet. Suppose I want to Sow several values during a computation.

sowstuff := (Do[Sow[i, tag1], {i, 5}]; Do[Sow[i^2, tag2], {i, 5}])

If I Reap this, I get one list of values per tag.

Reap[sowstuff] // Last
-> {{1, 2, 3, 4, 5}, {1, 4, 9, 16, 25}}

TreeForm of plain Reap

If I specify the tags i want to use explicitly, each of these lists gets wrapped in an additional list:

Reap[sowstuff, {tag1, tag2}] // Last
-> {{{1, 2, 3, 4, 5}}, {{1, 4, 9, 16, 25}}}

TreeForm of Reap with explicit tags

I believe I understand how Reap in general works. What puzzles me is the purpose of this additional wrapping. After reading the documentation of Reap and Sow, I have not yet seen a situation in which this list contains more than one element.

So my questions are:

  • Is there a reason for the introduction of another list?
  • Can this list have more than one element or is it always safe to just run Map[First,%] to remove it?
share|improve this question
    
Interesting. Up to this point, I had not found the second argument of Reap useful; I will have to re-evaluate my opinion. –  rcollyer Aug 22 at 18:09

2 Answers 2

up vote 4 down vote accepted

Yes, it is possible to generate sublists with more than one element. For example:

Last @ Reap[
  Sow[1,a]; Sow[2,a]
; Sow[3,b]; Sow[4,b]
; Sow[5,c]; Sow[6,c]
; Sow[7,d]; Sow[8,d]
, {a|b, c|d}
]

(* {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}} *)

The documentation explains that this happens because "Expressions sown using [...] different tags are given in different lists." It also states that we specify a list of patterns, the results for each pattern is returned in a separate list. This explains the extra levels of list structure.


Rant

enter at your own risk :)

Personally, I find Reap to be over-general. It irritates me that the shape of the result is different when no values are sown, e.g.

Reap[Sow[1]] // Last
(* {{1}} *)

But:

Reap[Null] // Last
(* {} *)

For me, building a single list of results is the common case. I'm usually not interested in value of the expression either -- just the list being built. So, most of the time my Reap expressions look something like this:

Reap[(*... some code ... *)][[2]] /. {r_} :> r

I'm not fond of that boilerplate.

Alternative?

I am not advocating the removal of Reap -- it has valuable uses cases, say, classifying terms in algebraic expressions. Rather, I would welcome the addition of another function that handles the common case of building up a single list procedurally. Just as FirstCase provides a convenient notation for a very common use of Cases. Perhaps something along these lines:

SetAttributes[reapList, HoldAll]
reapList[{sow_}, body_] :=
  Module[{bag, sow}
  , bag = Internal`Bag[]
  ; sow[v_] := Internal`StuffBag[bag, v]
  ; body
  ; Internal`BagPart[bag, All]
  ]

reapList[{sow}
, Scan[If[OddQ[#], sow[#]]&, Range[10]]
]
(* {1, 3, 5, 6, 9} *)

reapList[{sow}
, Scan[If[# > 100, sow[#]]&, Range[10]]
]
(* {} *)

reapList is notationally convenient when building up a single list. It also is safer to use in library code where the dynamic extent established by Reap could extend into user code causing user calls to Sow to wreak havoc with the library function.

share|improve this answer
    
Nice. Competing answers. :) –  rcollyer Aug 22 at 18:18
    
@rcollyer I confess that my answer is mostly motivated by the need to vent about Reap :D –  WReach Aug 22 at 18:32
    
It turns out my primary use of Reap was superseded by GroupBy, the Association thing not withstanding. –  rcollyer Aug 22 at 18:38
    
I these kinds of suggestions are exactly what @TaliesinBeynon was hoping for –  Rojo Aug 23 at 20:27
    
Thanks. This was exactly the explanation I was looking for. I simply didn't think of trying patterns which match more than one tag. One more case which explains the necessity of the additional wrapping just came to my mind: For a pattern which doesn't match, Reap produces an empty list - a place holder. This would not be possible without the additional level of wrapping. –  arnd Aug 25 at 8:32

The form of Reap your using is

Reap[expr, p:{pat1, pat2, ...}]

where each pattern generates a separate list in the answer. For instance, from the docs,

Reap[
 Sow[1, RandomInteger[{-9, 9}, 100]], 
 {_?Negative, _?NonNegative}, 
 #1 -> Total[#2] &
] // Last
(* {
 {-1 -> 4, -3 -> 5, -2 -> 5, -9 -> 6, -4 -> 4, -7 -> 3, -8 -> 3, -5 ->8, -6 -> 1}, 
 {1 -> 7, 0 -> 7, 6 -> 6, 4 -> 7, 8 -> 9, 9 -> 2, 7 -> 12, 2 -> 3, 5 -> 2, 3 -> 6}
} 
*)

So, each pattern is applied to the entire list, and the results for each are returned in a separate sub-list. In you case, you first have the pattern tag1, which only matches one thing, so it is put into a sub-list. The same thing happens for the second pattern, tag2, giving your nested result. In essence, this is what is going on:

Reap[sowstuff, #][[2]]& /@ {tag1, tag2}
(* {{{1, 2, 3, 4, 5}}, {{1, 4, 9, 16, 25}}} *)

To "fix" this, you merge the two patterns:

Reap[sowstuff, (tag1 | tag2), Rule] // Last
(* {tag1 -> {1, 2, 3, 4, 5}, tag2 -> {1, 4, 9, 16, 25}} *)

where Rule was included to emphasize the difference.

share|improve this answer

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.