8

I just learned about Mr. Wizard's very efficient code here.

list=RandomChoice[{True,False},10^6];
AbsoluteTiming[l2=Developer`ToPackedArray@With[{True=1,False=0},Evaluate@list];]
(*{0.066533,Null}*)

Compare that to Boole.

AbsoluteTiming[l3=Boole[list];]
l2===l3
(*{0.262770,Null}*)
(* True *)

It seems we can make a faster Boole. I tried to use the code above to do that, but it doesn't work.

boole[list_]:=Developer`ToPackedArray@With[{True=1,False=0},Evaluate@list];
list={True,True,False,True,False};
boole[list]
(*{True,True,False,True,False}*)

Why doesn't boole above work, and how can it be fixed?

Chris K
  • 20,207
  • 3
  • 39
  • 74
Ted Ersek
  • 7,124
  • 19
  • 41
  • I suggest making the question explicit in the title (you're using an existing implementation and it doesn't work, rather than asking for possible implementations) -- – user202729 Oct 28 '18 at 15:07

2 Answers2

9

The problem is the automatic module variable renaming that happens with With. You can use TracePrint to see this:

TracePrint[boole[list], _With]

With[{True\$=1,False\$=0},{True,True,False,True,False}]

{True, True, False, True, False}

One idea to circumvent this renaming is to use a pure function:

Clear[boole]
boole = Function[Developer`ToPackedArray @ With[{True = 1, False = 0}, #]];

Then:

boole[list]

{1, 1, 0, 1, 0}

Carl Woll
  • 130,679
  • 6
  • 243
  • 355
8

See Using With to scope over pure functions, then try:

boole[list_] := With @@ Hold[{True = 1, False = 0}, list] // Developer`ToPackedArray
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371