A simple question:
MatchQ[f[a], f[x_]]
(* True *)
MatchQ[D[a], D[x_]]
(* True *)
MatchQ[Dt[a], Dt[x_]]
(* False *)
Why doesn't the last test succeed? Is this a bug or am I doing something wrong? (Mathematica 10.2 on Mac.)
The symbol MatchQ
does not have an Hold*
attribute,
Attributes[MatchQ]
(* {Protected} *)
so its arguments are evaluated before the internal definition of MatchQ
fires. This means that the pattern-matcher is called only after the evaluation of the arguments. (See for instance the standard evaluation sequence in this tutorial.)
First situation
MatchQ[f[a], f[x_]]
(* True *)
The evaluation of each argument returns the argument itself, so you are effectively asking for a match between the typed expression.
Second situation
MatchQ[D[a], D[x_]]
(* True *)
The arguments are evaluated to what they contain, so you are asking for a match between a
and x_
, which returns True
.
Last situation
MatchQ[Dt[a], Dt[x_]]
(* False *)
While the argument Dt[a]
remains unchanged, the argument Dt[x_]
gets evaluated to:
Dt[x] Derivative[1, 0][Pattern][x, _]
which then results in False
once the pattern-matcher is called.
The fact that Dt[x_]
evaluates to this output can be understood by seeing the symbol Pattern
as an inert head in the evaluation sequence. You would obtain an output with the same structure by evaluating for instance Dt[f[x, 1]]
.
This is what happens: a) x_
is represented internally as Pattern[x, Blank[]]
, and b) Dt
takes the total derivative of this expression of head Pattern
with respect to all variables, namely with respect to all expressions at level 1 or deeper that are AtomQ
and have head Symbol
,
Level[Pattern[x, Blank[]], {1}]
(* {x, _} *)
AtomQ /@ %
(* {True, False} *)
Head /@ %%
(* {Symbol, Blank} *)
Level[Pattern[x, Blank[]], {2}]
(* {} *)
so here only with respect to x
.
Solution
To avoid the evaluation of the second argument, you can wrap it into HoldPattern
:
MatchQ[Dt[a], HoldPattern[Dt[x_]]]
(* True *)
Trace[]
or especially WReach's traceView functions can help show a user where his or her assumptions about evaluation diverge from reality.
$\endgroup$
Commented
Sep 10, 2016 at 18:44
D[a]
evaluates toa
andDt[a]
does not evaluate? $\endgroup$MatchQ
, the second argument is not held; it is evaluated (see the output ofTrace
). Thus,Dt[x_]
is evaluated, creating this weird expression:Dt[x]*Derivative[1, 0][Pattern][x, _]
. (Dt
tries to take the derivative of thePattern
function) Of courseDt[a]
looks nothing similar to this, soMatchQ
returnsFalse
. I believe this is unintended (perhapsMatchQ
should haveHoldRest
attribute). $\endgroup$