1
$\begingroup$

I have an operator that is flat and orderless that I want to evaluate only after the expression has been entirely flattened. Essentially, I want an expression of the form f[f[x,x],x] to only evaluate when it is in the form f[x,x,x]. I can accomplish this in limited cases,

ClearAll[f]
SetAttributes[f,{Orderless,Flat,HoldAll}]
f[x__] := Length[{x}]
f[x, x, f[x, x, f[x, x], x]]

which evaluates correctly to 7.

However, I am stumped when I try to apply this to more complicated cases such as using UpValues. If, for instance, I want x x x to evaluate as f[x,x,x], which is 3, I can try

ClearAll[f]
SetAttributes[f, {Orderless, Flat, HoldAll}]
x /: y__ x := f[x, y];
x  x  x 

which does evaluate to f[x,x,x] as I want. However,

ClearAll[f]
SetAttributes[f, {Orderless, Flat, HoldAll}]
f[x__] := Length[{x}]
x /: y__ x := f[x, y];
x  x  x 

evaluates to 2. Is there a way to produce the desired behavior?

Is there any way to obtain the desired behavior?

Edit: I have found the solution to the problem thanks to jjc385, I forgot to clear up values associated with x. I used something like

ClearAll[f]
SetAttributes[f, {Orderless, Flat, HoldAll}]
f[x__] := Length[{x}]
x /: y_ x := f[x, y];
x  x  x 

before which does indeed evaluate to 2, and never cleared x before trying the version I posted.

$\endgroup$
  • 1
    $\begingroup$ What $Version are you using? For me (11.3.0 for Microsoft Windows (64-bit) (March 7, 2018)), your last line evaluates to 3. $\endgroup$ – jjc385 Oct 25 '18 at 4:51
  • $\begingroup$ @jjc385 Thank you, I found the error. I had an up value associated with x that I did not know about, thanks to typos in my original code. Clearing x produces the desired response. $\endgroup$ – steven Oct 25 '18 at 17:03