0
$\begingroup$

How to avoid recursion in the following example?

Clear[MyRule];
Clear[MyHead1];

MyRule1 = MyHead1[x_MyHead2] | MyHead1[x_MyHead3] -> x;

MyHead1[x_] := Replace[MyHead1[x], MyRule1];

MyHead1[a]

MyHead1[MyHead2[b]]

How to make first rule in example below treated by Replace as not applicable?

In[17]:= ComplexRule1 = a -> Block[{},
    12
    ];

In[18]:= ComplexRule2 = a -> Block[{},
    13
    ];

In[19]:= Replace[a, {ComplexRule1, ComplexRule2}]

Out[19]= 12
$\endgroup$
6
  • $\begingroup$ You're asking a rapid-fire series of questions about pattern matching. I am assuming this is all part of a particular application. What is it? $\endgroup$
    – Mr.Wizard
    Commented Jan 19, 2013 at 10:56
  • $\begingroup$ I want to implement custom algebra with custom heads, transformations and simplifications. I am surprised Mathematica is not well suitable for this. $\endgroup$
    – Suzan Cioc
    Commented Jan 19, 2013 at 11:03
  • $\begingroup$ The main problem is "preprocessing". If user enters some expression with some heads, it should be automatically transformed into expressions with same heads, but simplified and normalized. This causes recursions for me. Conditions work bad here because they can require complex computations. $\endgroup$
    – Suzan Cioc
    Commented Jan 19, 2013 at 11:15
  • $\begingroup$ @kguler it's ok $\endgroup$
    – Suzan Cioc
    Commented Jan 19, 2013 at 11:20
  • $\begingroup$ "I am surprised Mathematica is not well suitable for this." — usually when someone says this, it's more often the case that they haven't thought through their problem well enough or are unfamiliar with Mathematica. I don't know which one it is :) $\endgroup$
    – rm -rf
    Commented Jan 19, 2013 at 17:17

1 Answer 1

5
$\begingroup$

You're mixing DownValues rules made with SetDelayed (:=) and replacement rules. Without seeing your application I cannot tell why. If you provide more information about your application a different approach may be recommended.

I see two problems with your code right off the bat. First:

MyHead1[x_] := Replace[MyHead1[x], MyRule1];

Here you made a definition that evaluates to itself in an unheld form. This causes infinite recursion.

Second, by defining:

MyRule1 = MyHead1[x_MyHead2] | MyHead1[x_MyHead3] :> x;  (* note use of :> to localize x *)

MyHead1[x_] := "anything"

MyRule1 evaluates to "anything" | "anything" :> x as soon as it is accessed.


The second problem might be corrected with HoldPattern:

MyRule1 = HoldPattern[MyHead1[x_MyHead2] | MyHead1[x_MyHead3]] :> x;

The first is more complicated. I still suppose that you may want instead to write this to avoid the recursion in the first place, but alternatively you could work within Hold:

ClearAll[MyHead1]

MyHead1[x_] := Replace[Hold[MyHead1[x]], MyRule1, {1}];  (* note Levelspec *)

Or you could use the Villegas-Gayley method:

ClearAll[MyHead1]

MyHead1[x_] /; ! TrueQ[insideMyHead1] :=
 Block[{insideMyHead1 = True},
  Replace[MyHead1[x], MyRule1]
 ]

I suspect instead of all this you may be looking for the functionality of UpSet, UpSetDelayed, TagSet, etc. which make UpValues rules. Again, with a more complete problem specification I may be able to recommend something better.


Lastly, the title of your question makes me think that perhaps you would find value in this special use of Condition:

lhs := Module[{vars}, rhs /; test] allows local variables to be shared between test and rhs. You can use the same construction with Block and With.

$\endgroup$
8
  • $\begingroup$ By MyRule1 = MyHead1[x_MyHead2] | MyHead1[x_MyHead3] -> x I meant a rule, which applies to expression with head 2 or 3 and gives x in the case. Isn't it correct? $\endgroup$
    – Suzan Cioc
    Commented Jan 19, 2013 at 11:08
  • $\begingroup$ @Suzan I added some more information to my answer. I hope that you will find it useful. I especially recommend that you read about UpSet and TagSet. Without a better sense of what you're really trying to do I cannot be more specific I'm afraid. $\endgroup$
    – Mr.Wizard
    Commented Jan 19, 2013 at 11:18
  • $\begingroup$ @Mr.Wizard I have troubles understanding a significance of "allows local variables to be shared between test and rhs.", not in this topic context but in general. What is so great about that. Obviously rhs and test will share variables since both of them all in the same Module, aren't they? Why don't I think alike documentation creators and so often have troubles understanding the meaning of their words? :) $\endgroup$
    – Kuba
    Commented Aug 5, 2016 at 7:11
  • $\begingroup$ p.s. shouldn't it be considered half/magical if this Module/Condition syntax allows to return unevaluated f[arg] and is not reachable by UpValues so easily? $\endgroup$
    – Kuba
    Commented Aug 5, 2016 at 7:16
  • $\begingroup$ @Kuba I cannot tell you what the documentation creators were thinking, but I agree what is a strange way to put things. I think I would have understood it better if they had said that the condition test applies to the entire lhs := rhs definition. Regarding the second comment I did mention RuleCondition in my self-answer which is the mechanism by which this works. I am still trying to figure out what counts as "magic" however. $\endgroup$
    – Mr.Wizard
    Commented Aug 5, 2016 at 7:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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