4
$\begingroup$

While checking out the different pattern replacement methods in this question, I have a query regarding the basic difference between the following two replacements:

 expr = a x^3 + b x y - c x^7 y^2;
 expr /. {x^m_Integer :> x^Mod[m, 2]}
 expr /. {x^m_?Integer :> x^Mod[m, 2]}

The first replacement works as expected, but the second replacement does not do anything. What is happening in the second one. Also, another code to effect the desired replacement is

expr /. {x^_?EvenQ -> 1, x^_?OddQ -> x}

which contains "?" after an underscore.

Any help to solve this confusion will be appreciated.

$\endgroup$

closed as off-topic by Michael E2, m_goldberg, AccidentalFourierTransform, Carl Lange, MarcoB May 12 at 16:47

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "This question arises due to a simple mistake such as a trivial syntax error, incorrect capitalization, spelling mistake, or other typographical error and is unlikely to help any future visitors, or else it is easily found in the documentation." – Michael E2, m_goldberg, AccidentalFourierTransform, Carl Lange, MarcoB
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    $\begingroup$ you can use expr /. {x^m_?IntegerQ :> x^Mod[m, 2]} $\endgroup$ – kglr May 12 at 10:01
  • $\begingroup$ see tutorial/PuttingConstraintsOnPatterns $\endgroup$ – kglr May 12 at 10:11
  • $\begingroup$ @kglr Thanks for the solution and the link. Could you kindly illustrate the difference between _Integer and _?IntegerQ ? Another one is "_Integer?" mentioned in the following link discussing partly my doubts. mathematica.stackexchange.com/questions/9356/… $\endgroup$ – Mark Robinson May 12 at 10:25
  • 2
    $\begingroup$ If you use the _?func pattern then func can be any function at all. Any function you can think of. _head is a shorthand for the pattern head[___]. A pattern that doesn't involve arbitrary black box functions can be optimized in ways that it couldn't if it had to evaluate arbitrary functions on each possible match. Don't use _?func unless you have to. $\endgroup$ – C. E. May 12 at 10:51
  • $\begingroup$ m_?Integer is incorrect. Did you mean IntegerQ? $\endgroup$ – Szabolcs May 12 at 11:05
13
$\begingroup$

See PatternTest.

x_?test matches if test[x] is True. It is equivalent to x_ /; test[x] (see Condition).

x_symbol matches if Head[x] is symbol.

m_?Integer makes no sense because Integer is not a function that returns True or False. m_?IntegerQ is valid and works. See Integer and IntegerQ.

_Integer and _?IntegerQ are very similar, but there are some important differences:

_Integer is faster than _?IntegerQ:

list = Developer`FromPackedArray@RandomInteger[1000, 1000000];

fun1[_Integer] := "x";
fun2[_?IntegerQ] := "x";

fun1 /@ list; // Timing
(* {0.23702, Null} *)

fun2 /@ list; // Timing
(* {0.376331, Null} *)

But _Integer also matches expressions which are not really integers, such as Integer["abc"].

The same applies to other, similarly named functions as well.

_?GraphQ and _Graph are not the same. _?AssociationQ and _Association are not the same. This is because there are expressions with the head Association that are not atomic associations.

expr = Association[123]
(* Association[123] *)

MatchQ[expr, _Association]
(* True *)

MatchQ[expr, _?AssociationQ]
(* False *)

In these cases, one usually needs the pattern _?AssociationQ. Then the expression will work with functions like Lookup, KeyTake, etc.

There is even use for _Association?AssociationQ. This pattern is faster to reject non-associations than _?AssociationQ, but it is otherwise functionally equivalent.

$\endgroup$
  • $\begingroup$ Are _?EvenQ and _Even equivalent? The code expr /. {x^_Even -> 1, x^_Odd -> x} does not work. $\endgroup$ – Mark Robinson May 12 at 14:12
  • 4
    $\begingroup$ @MarkRobinson I don't follow your thinking ... as I said, _Even matches expressions with the head Even. That symbol has no built-in meaning. Why would you even try to use it? Why do you think it has any connection to EvenQ? If something was not clear in my explanation, please ask. $\endgroup$ – Szabolcs May 12 at 14:30
  • $\begingroup$ It might be worth noting that _Integer and _?IntegerQ are not fully equivalent - e.g. for Integer["a"], only the former matches. While this is admittedly a rather contrived example, I encountered this issue a few times with Symbol[…] (I was using _Symbol to get all symbols in the expression, which failed due to the above) $\endgroup$ – Lukas Lang May 12 at 17:21
  • $\begingroup$ @LukasLang Thanks! You're right, it's the same situation as with Association. $\endgroup$ – Szabolcs May 12 at 17:26
  • $\begingroup$ @Szabolcs Thanks for the clearly explained and to the point answer and illustrating the equivalence with condition. I now understand it to a good extent. $\endgroup$ – Mark Robinson May 13 at 4:21

Not the answer you're looking for? Browse other questions tagged or ask your own question.