When Cases
searches an expression, it assumes by default Heads -> False
. This means that expression heads are not searched for matches. With Heads -> True
, heads are searched.
By means of the visualization helper function frameMatches
(defined at the bottom of this post), we can explore the implications of this option.
First, let's look at the full form of the expression in question:
expr // FullForm
Now, let's highlight all of the subexpressions (i.e. anything that matches _
), but ignoring heads:
frameMatches[expr, _, Infinity, Heads -> False]
This is the full set of possible matches for an unrestricted pattern. Note that Derivative[1]
, Derivative[2]
, Derivative[1][y]
, Derivative[2][y]
and the other heads are not in this set -- even though the expressions that contain them are. So it is no surprise that it we try to match the pattern Derivative[_]
we come up empty:
frameMatches[expr, Derivative[_], Infinity, Heads -> False]
Cases[expr, Derivative[_], Infinity, Heads -> False]
(* {} *)
Now, let's include heads when matching. Again, with the unrestricted pattern _
:
frameMatches[expr, _, Infinity, Heads -> True]
This time around, Derivative[1]
and Derivative[2]
are included in the search. And the search even descends into the heads of those expressions, to include Derivative
.
This is why we now get the results we want using the desired pattern:
frameMatches[expr, Derivative[_], Infinity, Heads -> True]
Cases[expr, Derivative[_], Infinity, Heads -> True]
(* {Derivative[1], Derivative[2]} *)
Matching Heads with Heads -> False
Incidentally, the option Heads -> True is not the only way to match heads within an expression. We can write explicit patterns that will extract the heads from matched non-head parts. For example:
Cases[expr, (d : Derivative[_])[_][_] :> d, Infinity]
(* {Derivative[1], Derivative[2]} *)
Is All This Documented?
Yes, but as usual it is terse. The documentation for Heads
says:
Heads
is an option for functions which use level specifications that specifies whether heads of expressions should be included.
Heads->True
treats heads just like other elements of expressions for the purpose of levels.
Heads->False
never includes heads as part of any level of an expression.
frameMatches
caveat: this function works for the examples at hand, but is not intended to be fully general
frameMatches[expr_, patt_, args___] :=
Replace[expr // FullForm, e:patt :> Framed[e], args] // expandFrames
expandFrames[e_] :=
MakeBoxes[e] //
Replace[#, RowBox[{"Framed", "[", x_, "]"}] :> FrameBox[x], Infinity]& //
Replace[RowBox[{FrameBox["FullForm", ___],"[", x_, "]"}] :> x] //
RawBoxes
y''[x] // FullForm
givesDerivative[2][y][x]
. ThatDerivative
term is in theHead
. You'll could get away withHeads->False
here by doingDerivative[n_][_][__]
, but note that this may not work in general. $\endgroup$Head->True
just makesCases
also return the Head in the result. So I would have expected something like{Derivative,1,2}
to be returned. $\endgroup$Heads->True
makes it (try to) match theHead
too. The docs were just noting that since it was matching the_Symbol
, it was going to return theHead
. $\endgroup$