5

The following is a minor variant of the function uniqueTuples as given by Simon Woods in this answer.

g[lists___List] := Module[{f},
  f[___, x_, x_,___] := Sequence[];
  f[x___] := (f[x]=Sequence[];{x});
  Attributes[f]={Orderless};
  Flatten[Outer[f, lists], Length[{lists}]-1]]

data=RandomInteger[40, {6,11}];
Length[g @@ data] // Timing
(* {6.177640,388897} *)

In the definition of g we have a local variable f, which is used as a function and for which a lot of DownValues could be created. This function is not removed when the Module is evaluated:

Names["f$*"]
(* {f$,f$342} *)

Length[DownValues[f$342]]
(* 388899 *)

I am using version 10.0.2 on Windows (32-bit). Indeed, this bug made Mathematica crash due to lack of memory when I used this function a number of times with larger arguments.

Fred Simons
  • 10,181
  • 18
  • 49

1 Answers1

7
g[lists___List] := Module[{f}, f[___, x_, x_, ___] := Sequence[];
  f[x___] := (f[x] = Sequence[]; {x});
  Attributes[f] = {Orderless, Temporary};
  Flatten[Outer[f, lists], Length[{lists}] - 1]]

To address the comments let me put it another way: If you overwrite the attributes of course they are going to be 'lost'

Look at this:

g[lists___List] := Module[{f}, f[___, x_, x_, ___] := Sequence[];
  f[x___] := (f[x] = Sequence[]; {x});
  Print[Attributes[f]];
  Attributes[f] = {Orderless};
  Print[Attributes[f]];
  Flatten[Outer[f, lists], Length[{lists}] - 1]]
user21
  • 39,710
  • 8
  • 110
  • 167
  • 2
    Thank you very much. This is a nice and useful workaround, but adding the attribute Temporary to a local variable of a Module should be superfluous. – Fred Simons Jan 20 '15 at 10:21
  • 1
    Ah, I see. It is not a bug in Mathematica, but a subtle error of mine. The solution is to use SetAttributes[f, Orderless]; instead of defining Attributes[f]={Orderless};. Many thanks again. – Fred Simons Jan 20 '15 at 12:13