Why If does not work instead of /; when searching condition in a list

I am trying to define a commutator. The way I am working this out is the following. I have a list with integers. I want to put the biggest on the right commuting them. For example, if I have a list like {1,1,1,-4,-3}, then I want to commute the three 1's to the right of the negative number.

I have a recursive function that does the job but I have issues with it since I overcharged this function's definition and the way Mathematica interprets it is not totally clear to me. Therefore, I want to go with an If,else condition. The first recursive function I have is the following

C3[a___, h2_, {n1___, m_, n_, n4___}, b___] := C3[a, h2, {n1, n, m, n4}, b] + (m - n) C3[a, h2, {n1, n + m, n4}, b] +
If[m + n == 0, c (m^3 - m)/12 C3[a, h2, {n1, n4}, b], 0] /; m > n;


This function works indeed as expected, and we have

  In[6]:= C3[1, {}, 1, {1, 1, 1, -4, -3}, 1, {}] // FullSimplify

Out[6]= 48 (3 C3[1, {}, 1, {-4}, 1, {}] +    5 (C3[1, {}, 1, {-3, -1}, 1, {}] + C3[1, {}, 1, {-2, -2}, 1, {}]))


Now I don't understand why an equivalent thing with an If does not work. If I use the function

C3p[a___, h2_, {n1___, m_, n_, n4___}, b___] := If[m > n,C3p[a, h2, {n1, n, m, n4},  b] + (m - n) C3p[a, h2, {n1, n + m, n4}, b] +  If[m + n == 0, c (m^3 - m)/12 C3p[a, h2, {n1, n4}, b], 0], 0]


This one does not enter in the condition and we obtain

In[8]:= C3p[1, {}, 1, {1, 1, 1, -4, -3}, 1, {}]

Out[9]= 0


This function does not even produce an output and never enters the condition. I am also interested in the rapidity of execution since in the end, this function may be called a huge number of time. Any help would be much appreciated.

In full generality, what I am trying to achive is the following. In a recursive manner, I have this six functions, but I am almost sure that Mathematica is confused since their call is somewhat similar. C3 is a function that take six arguments of the form C3[h1_,{n1___},h2_,{n2___},h3_,{n3___}], three integers and three lists of integers. My code yields the correct result but become incredibly slow. Basically, I am searching a clever way to write

C3[a___, h3_, {n___, m_}] := 0 /; m > 0;
C3[a___, h2_, {n___, m_}, b___] := 0 /; m > 0;
C3[h_, {n___, m_}, a___] := 0 /; m > 0;
C3[a___, h3_, {n1___, m_, n_, n4___}] := C3[a, h3, {n1, n, m, n4}] + (m - n)     C3[a, h3, {n1, n + m, n4}] +
If[m + n == 0, 24 (m^3 - m)/12 C3[a, h3, {n1, n4}], 0] /; m > n;
C3[a___, h2_, {n1___, m_, n_, n4___}, b___] :=
C3[a, h2, {n1, n, m, n4}, b] + (m - n) C3[a, h2, {n1, n + m, n4}, b] +
If[m + n == 0, c (m^3 - m)/12 C3[a, h2, {n1, n4}, b], 0] /; m > n;
C3[h_, {n1___, m_, n_, n4___}, a___] := C3[h, {n1, n, m, n4}, a] + (m - n) C3[h, {n1, n + m, n4}, a] +
If[m + n == 0, 24 (m^3 - m)/12 C3[h, {n1, n4}, a], 0] /; m > n;


so that mathematica is not confused and know exactly how to commute the thing until the desired order is reached.

• The reason that the If version doesn't work, apart from having C3 on the right-hand side rather than C3p (which is required for it to be recursive), sit that it evaluates (for your list) m == 1 and n==1 first (i.e. the first elements in the list), and since 1 >1 is False, it spits out 0 and doesn't call itself. Unfortunately I don't have time to test further. Commented Mar 10, 2017 at 22:40
• Thanks for the explanation. I edited the typo, I indeed meant C3p. Commented Mar 10, 2017 at 23:06
• "This function does not even produce an output and never enters the condition." What does this mean? Can you provide example inputs and outputs? Perhaps are you bothered that some outputs are wrapped in If? This is because in replacing Condition with If as you did, the pattern on the left hand side of SetDelayed is more general -- it's possible that the pattern will match when m>n evaluates to neither true nor false, unlike when you used Condition. Commented Mar 11, 2017 at 11:05
• Thank you for your comment. I edited the question with an input and output for the given list. Hope this helps Commented Mar 11, 2017 at 11:20
• @Ezareth Note that commenters are usually not notified unless you tag them with (@username). An exception is the original poster, who is always notified. Commented Mar 11, 2017 at 19:33

General Issue

The problem is there's a huge difference between SetDelayed with Condition versus SetDelayed with If.

Consider

LHS := RHS /; test


versus

LHS := If[ test, RHS, somethingElse ]


If test evaluates to true, the output will be the same. However, if test evaluates to anything other than true, the output will be different.

In the first case, with Condition, the transformation will not be applied, and LHS will return unevaluated.

In the second case, with If, the transformation rule will always be applied to any pattern matching LHS, whether or not test is true. If test evaluates to false, somethingElse is returned. If test evaluates to anything other than true or false (e.g., a < b for a and b undefined), a partially evaluated If statement is returned.

General examples

fooCond[m_, n_] /; m < n := bar[m, n]

fooIf[m_, n_] := If[m < n, bar[m, n], somethingElse[m, n] ]


When the test m < n evaluates to true, the output is the same:

fooCond[1, 2]


bar[1, 2]

fooIf[1, 2]


bar[1, 2]

When the test m < n evaluates to false:

fooCond[2, 1]


fooCond[2, 1]

fooIf[2, 1]


somethingElse[2, 1]

When the test m < n' evaluates to anything other than true or false:

fooCond[a, b]


fooCond[a, b]

fooIf[a, b]


If[a < b, bar[a, b], somethingElse[a, b] ]

OP's Issue

After evaluating the first two lines of your code

C3[1, {}, 1, { -4, -3}, 1, {}]


returns unevaluated, while

C3p[1, {}, 1, {-4, -3}, 1, {}]


returns zero. This falls into the second category above: the test evaluates to false.

One possible fix

C3[a___, h2_, {n1___, m_, n_, n4___}, b___] := 0 /; !( m > n )

Then the output will be the same as long as the test m > n evaluates to true or false. These are still not completely equivalent, but they will be if m and n` are real numbers.