9

Sometimes because of conditionals, you cannot guarantee that Sow will be called at least once.

Reap[Sow[1]][[2,1]] results in {1}, which is perfect if one was going to discard the end value anyway, because only the list of sown values has value.

Reap[Null][[2, 1]] raises exception

"Part::partw: Part 1 of {} does not exist."

I use this code

ClearAll[reapList]
reapList::usage="gracefully collect all Sow expressions into list";
SetAttributes[reapList,HoldAll]
reapList[r__]:=Flatten[Reap[r,{_}][[2]],2]
(* unit tests follow *)
reapList[Sow[15]]
   {15}
reapList[Sow[{}]]
   {{}}
reapList[Sow[{16,17}];Sow[18];Print["hello"];Sow[{19,20}];21]
    hello
   {{16,17},18,{19,20}}
reapList[Null]
   {}
reapList[Sow[Null]; Sow[{Null}]]
   {Null,{Null}}
reapList[For[i = 95, i <= 100, i++, If[PrimeQ[i*2 - 1], Sow[i]]]]
   {96, 97, 99, 100}
reapList[For[i = 101, i <= 105, i++, If[PrimeQ[i*2 - 1], Sow[i]]]]
   {}

but there might be a better way than use of pattern {_} and Flatten[ ... ,2] that is so much shorter not much value in creating helper function.

Also, not clear to me how to generalize the "reapList" helper function for use with tags.

Manuel --Moe-- G
  • 1,057
  • 1
  • 8
  • 16

4 Answers4

9

Edit: I accidentally used Identity when I meant Sequence, but on reflection I believe Join @@ is better.

My two standard methods are Apply: (reference Formatting text through pattern matching and Quick multiple selections from a list)

Join @@ Reap[Sow[1]][[2]]
Join @@ Reap[Null][[2]]
Join @@ Reap[Sow /@ {1, 2, {}}][[2]]
{1}

{}

{1, 2, {}}

And ReplaceAll: (reference How to remove redundant {} from a nested list of lists?)

Reap[Sow[1]][[2]]             /. {x_List} :> x
Reap[Null][[2]]               /. {x_List} :> x
Reap[Sow /@ {1, 2, {}}][[2]]  /. {x_List} :> x
{1}

{}

{1, 2, {}}

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
5

In Mathematica v10.1 there's undocumented GeneralUtilities`ReapList function. It accepts two arguments: expression and a tag.

Using it on adapted test suite from OP:

Needs["GeneralUtilities`"]
ClearAll[tag]
ReapList[Sow[15, tag], tag]
(* {15} *)
ReapList[Sow[{}, tag], tag]
(* {{}} *)
ReapList[
    Sow[{16, 17}, tag]; Sow[18, tag]; Print["hello"]; Sow[{19, 20}, tag]; 21,
    tag
]
(* hello *)
(* {{16, 17}, 18, {19, 20}} *)
ReapList[Null, tag]
(* {} *)
ReapList[Sow[Null, tag]; Sow[{Null}, tag], tag]
(* {Null, {Null}} *)
ReapList[For[i = 95, i <= 100, i++, If[PrimeQ[i*2 - 1], Sow[i, tag]]], tag]
(* {96, 97, 99, 100} *)
ReapList[For[i = 101, i <= 105, i++, If[PrimeQ[i*2 - 1], Sow[i, tag]]], tag]
(* {} *)
jkuczm
  • 15,078
  • 2
  • 53
  • 84
2

@Kuba is correct

Flatten[Reap[r][[2]], 1]

is a good substitute for Reap[r][[2,1]] when cannot guarantee at least one Sow

the line above should be substituted with

reapList[r_] := Flatten[Reap[r][[2]], 1]

because the __ is unnecessary as well

Manuel --Moe-- G
  • 1,057
  • 1
  • 8
  • 16
1

Perhaps cleaner to construct your expression in a way that guarantees at least one Sow[] call.

  Table[Rest@First@Last@Reap[Sow[Null]; If[i != 2, Sow[i]]], {i, 3}]

{{1}, {}, {3}}

george2079
  • 38,913
  • 1
  • 43
  • 110