Create rules based on data. I have a system that picks out on date,based on some rules. I then want to generate a new rule based on this date and apply the rule to a new dataset.

datePicked={{2008, 3, 21, 0, 0, 0.}}
rule=datePicked/. {t_, n_, o_, b___} :> HoldForm[{t, n, v_, b} /; v <= o];

d=DateRange[{2008, 2, 21, 0, 0, 0.`}, {2008, 3, 21, 0, 0, 0.`}]

Problem is that the rule I have made is not general, it has assigned the $ to v. How can I make it general?

  • $\begingroup$ Why are you using HoldForm? It works fine without it. $\endgroup$ Commented Apr 25, 2014 at 18:17
  • $\begingroup$ Because then i only get the value from datePicked. but I want to make a rule based on datePick the output should be {t,n,v_,b}/;v<=0, However it comes out as {t,n,v$_,b}/;v$<=0, which means that I cant apply that pattern because it is not general due to $ sign. $\endgroup$
    Commented Apr 25, 2014 at 18:24
  • $\begingroup$ As you can see the output is a pattern with a rule which is used in Cases, but since it is not general it does not work. I therefor want to make the output general by removing the $ signs each assigned to v. $\endgroup$
    Commented Apr 25, 2014 at 18:29
  • 4
    $\begingroup$ Ok, I see. What you really need is something like rule = datePicked /. {t_, n_, o_, b___} :> Identity[{t, n, v_, b} /; v <= o];, where Identity serves as an escaping mechanism, so that the condition is not interpreted as a part of the rule during rule application in the above code. The reason your pattern didn't work was not due to v to v$ renaming, but due to the presence of HoldForm in your pattern - the HoldForm head is not transparent for pattern-matching. As an alternative, you could use HoldPattern in place of HoldForm, but I like the solution with Identity better. $\endgroup$ Commented Apr 25, 2014 at 18:35
  • 2
    $\begingroup$ "how you are able to see the problem" - long experience :). Pattern-matching only shows in Trace when there are non-trivial calls to evaluator (via Condition or PatternTest). In this case, your entire pattern was wrapped in HoldForm, and the pattern-matcher was able to determine the fact of (non)match without testing the condition in the pattern. The problem of Condition being interpreted as a part of the rule rather than belonging to the answer (r.h.s.) only, is indeed rather subtle. This is a good question. If no one does this first, I will convert my comment into a proper answer $\endgroup$ Commented Apr 25, 2014 at 19:14

1 Answer 1


As Leonid explained in the comment, HoldForm is not transparent for the pattern matcher as opposed to HoldPattern:

MatchQ[#, HoldForm[_]] & /@ {a, HoldForm[a]}
MatchQ[#, HoldPattern[_]] & /@ {a, HoldForm[a]}
{False, True}

{True, True}

From the above you see that an expression will match the pattern HoldForm[_] only if its Head is HoldForm. HoldPattern is specially designed to be transparent for the pattern matcher, and so HoldPattern[_] is equivalent to _ for the pattern matcher.

Condition (/;) is interpreted as a part of rule only if it is placed on level 1 inside it:

FullForm[lhs :> rhs /; test]    

RuleDelayed[lhs, Condition[rhs, test]]

{1, 2} /. x_Integer :> f[x] /; OddQ[x]   

{f[1], 2}

Mathematica converts such structures to undocumented RuleCondition for the purposes of pattern matching:

Trace[1 /. x_ :> f[x] /; OddQ[x]] 
(*=>  {{x_:>x/;test,x_:>x/;test},1/. x_:>x/;test,{RuleCondition[$ConditionHold[$ConditionHold[1]],test],Fail},1} *)

If one wraps Condition with arbitrary head it is no more a part of the rule:

{1, 2} /. x_Integer :> f[x /; OddQ[x]]    

{f[1 /; OddQ[1]], f[2 /; OddQ[2]]}

The role of such head may serve Identity as Leonid suggests:

{1, 2} /. x_Integer :> Identity[x /; OddQ[x]]    

{1 /; OddQ[1], 2 /; OddQ[2]}

HoldPattern is also suitable but it is not necessary in your case.


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.