Named patterns in Except

It seems that f[Except[0, a_], Except[0, a_]] isn't considered doubled argument while this

f[a : Except[0], a : Except[0]] is. So the former isn't considered special case and is overwritten by your next definition.

I can't explain properly but seems to be expected.

ClearAll[f];
f[a_, a_] := 0  (*or f[a : Except[0], a : Except[0]] if f[0,0] should give f[0,0]*)
f[a : Except[0], b : Except[0]] := {a, b}



f[1, 2]
f[0, 1]
f[0, 0]
f[1, 1]
{1,2}
f[0,1]
0
0

Another way to get two definitions is to only use Except on the first argument for the case where the arguments are identical.

Clear[f]

f[Except[0, a_], a_] := 0

f[Except[0, a_], Except[0, b_]] := (a - b) Log[a - b]

Annoyingly it doesn't matter the order for the definitions it comes out like this:

DownValues@f
(* {HoldPattern[f[Except[0, a_], Except[0, b_]]] :> (a - b) Log[a - b], 
 HoldPattern[f[Except[0, a_], a_]] :> 0} *)

So in order to get the right behaviour you have to do

DownValues[f] = Reverse@DownValues@f
(* {HoldPattern[f[Except[0, a_], a_]] :> 0, 
 HoldPattern[f[Except[0, a_], Except[0, b_]]] :> (a - b) Log[a - b]} *)

Now

f[3, 1]
f[3,0]
f[2,2]
f[0,0]

gives

2 Log[2]
f[3,0]
0
f[0,0]