zhenyuzeng
(Zhenyu Zeng)
February 18, 2022, 10:14am
1
Hello,
In Mathematica, 0 is an integer. So why can we write these codes:
evenodd[n_Integer] := If[EvenQ[n], Black, White]; evenodd[0] = Red
As 0 is an integer, the second half code is weird. The first part of codes includes 0.
How should I understand it?
sghuisman
(Sander Huisman)
February 18, 2022, 10:34am
2
This can be very tricky actually, the patterns of evenodd are sorted from very specific to least specific:
ClearAll[evenodd]
evenodd[n_Integer] := If[EvenQ[n], Black, White];
evenodd[0] := Red
DownValues[evenodd]
Any call to evenodd will be matched in the order of DownValues as far as I know.
zhenyuzeng
(Zhenyu Zeng)
February 18, 2022, 10:58am
3
0 is even too. So there is no chance to match.
evenodd[0]
In fact, it will be matched. So how understand it?
sghuisman
(Sander Huisman)
February 18, 2022, 11:01am
4
The call evenodd[0] matches both evenoff[0] and evenodd[n_Integer]. What happens on the right hand side of the definitions is not considered in the matching. But since these both match, the most-specific will be matched first (in the order of DownValues).
eric3
(Eric Rimbey)
February 18, 2022, 5:09pm
5
Try this experiment:
Clear[evenodd];
evenodd[n_Integer] := Brown;
evenodd[n_Integer?Positive] := Orange
evenodd[n_Integer?EvenQ] := Magenta;
evenodd[n_Integer /; Divisible[n, 4]] := Blue;
evenodd[0] := Red;
evenodd /@ Range[-5, 5]
Notice how Blue never shows up, and Magenta never shows up on the positive side. Why? To understand, look at the DownValues:
DownValues@evenodd
which gives you
{HoldPattern[evenodd[0]] :> Red, HoldPattern[evenodd[n_Integer?Positive]] :> Orange, HoldPattern[evenodd[n_Integer?EvenQ]] :> Magenta, HoldPattern[evenodd[n_Integer /; Divisible[n, 4]]] :> Blue, HoldPattern[evenodd[n_Integer]] :> Brown}
Notice that Mathematica automatically re-ordered the definitions from most specific to most general. But it couldn’t distinguish between the conditional rules, so it left them in the order in which they were evaluated.
Try the experiment again after re-ordering the conditional rules.
Clear[evenodd];
evenodd[n_Integer] := Brown;
evenodd[n_Integer?EvenQ] := Magenta;
evenodd[n_Integer?Positive] := Orange
evenodd[n_Integer /; Divisible[n, 4]] := Blue;
evenodd[0] := Red;
evenodd /@ Range[-5, 5]
All of this indicates that care should be taken when trying to define conditional rewrite rules.
Side note, this also shows that you could replace your definition using If with one using a Condition or a PatternTest.
hansmilton
(Hans Milton)
February 18, 2022, 6:01pm
6
I might be missing something. But:
Practical use of your code works as expected. What is the actual problem?
evenodd[n_Integer] := If[EvenQ[n], Black, White]
evenodd[0] := Red
Table[evenodd[i], {i, -3, 3}]