4

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.`}]
Cases[d,#]&@@rule

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

ALEXANDER
  • 1,219
  • 8
  • 21
  • Why are you using HoldForm? It works fine without it. – Leonid Shifrin Apr 25 '14 at 18:17
  • 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. – ALEXANDER Apr 25 '14 at 18:24
  • 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. – ALEXANDER Apr 25 '14 at 18:29
  • 4
    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. – Leonid Shifrin Apr 25 '14 at 18:35
  • Works fine for me, just double-checked on a fresh kernel, copy-pasted from my comment. I tend to think this is a problem on your side. Just replace your definition of rule with mine, and try again. – Leonid Shifrin Apr 25 '14 at 18:47
  • Works great. However, when I look at the code with Trace I am not able to see what is going one. Could you show me how you are able to see the problem? – ALEXANDER Apr 25 '14 at 18:58
  • 2
    "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 – Leonid Shifrin Apr 25 '14 at 19:14

1 Answers1

5

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.

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368