I am not an expert on scoping constructs... Replacement rules aren't very respectful of inner scoping constructs, of the expression in which they are replacing. They seem to be respectful however of the scoping constructs of the expression they are building.
So, for example
Hold[val /. x_ /; cond :> res] /. cond :> x
returns
Hold[val /. x_ /; x :> res]
but, like your example
{1, x>0, -x}/.{val_,cond_,res_}:>(val/. x_/;cond:>res)
returns
1/. x$_/;x>0:>-x
In any case, we need to avoid the rescoping. Many ways to do this, but one would be to simply prevent the replacer to see your x_ as a scoped variable when it does the replacing
Attributes[f] = {HoldRest};
f[val_, cond_, res_] := val /. Pattern @@ Hold[x, _] /; cond :> res
In place of Pattern @@ Hold[x, _] you can put anything that evaluates to x_ without having it explicitly. You coudl make your own function, write Pattern[x, Sequence[], _], Union@Pattern[x, _, _], Identity[Pattern][x, _], Evaluate[Pattern][x, _], Reverse[Pattern[_, x]], ToExpression["x_"], Pattern @@ (x _) (notice the space, could be a +). In those cases that don't hold its arguments, however, you would need to add an Unevaluated to avoid problems if x is defined
@WReach's good suggestions in the comments are based on this too, on hiding the x_ as a scoped variable when the replacement is done, by injecting them later
Edit
Things like Pattern[x, 1 _^1+0] or stuff like that with the same structure (head Pattern2 arguments, won't work because it recognises it as a pattern)
Ok, I said there are many ways, so I'll give another example... Another way to implement the above is to lexically scope your Pattern so it isn't a pattern but you can type it as such. It probably only makes sense if your rhs is big and the lhs is small, but it also has the advantage of working when the pattern is inside held constructs. By the way, I never saw this done so I reserve the right to be suggesting something stupid and abstruse. In any case, its instructive and you wanted to learn, hehe
Attributes[f] = {HoldRest};
With[{rp = Pattern}, Module[{Pattern},
f[rp[val, _], rp[cond, _], rp[res, _]] := Unevaluated@
(val /. x_ /; cond :> res)
/. Pattern :> rp]]
So, when you write your code, you can use x_ as you wish, because it will be interpreted as some Pattern$ASk that's not a scoping contruct. You use rp for those that you wish to become real patterns at definition time and _ those who you want to turn into patterns at execution time.
Another idea is, instead of hiding the scoping variable, hide the scoping constructs until runtime
Attributes[f] = {HoldRest};
With[{Condition = Hold[Condition], RuleDelayed = Hold[RuleDelayed],
ReplaceAll = Hold[ReplaceAll]},
SetDelayed @@
Hold[f[val_, cond_, res_], ReleaseHold[val /. x_ /; cond :> res]]
]
In order for the With to work you need to do something like that SetDelayed@@ because that's another scoping construct that With won't go into willingly. So, in this example, you see two layers of the trick.
flooks like an invitation for trouble. – Leonid Shifrin Mar 3 '12 at 17:54#still seems a more natural syntax to me, but perhaps I've overlooked something? – Mr.Wizard♦ Dec 21 '12 at 23:46