Basics
To get it out of the way, for the specific example given you could use Unevaluated
:
Cases[Unevaluated[1 + 3], _, {-1}]
{1, 3}
To actually be able to modify a System function I recommend Internal`InheritedBlock
:
SetAttributes[cases, HoldAll]
cases[args___] :=
Internal`InheritedBlock[{Cases},
SetAttributes[Cases, HoldFirst];
Cases[args]
]
cases[1 + 3, _, {-1}]
{1, 3}
This does not make additional definitions convenient however. I am working on that.
Experimental construct
I think this may be useful. The idea is to have to associate cases
with Cases
only once, then be able to work with cases
as desired. It is limited to DownValues
and Attributes
for now as I cannot think of a clean way to extend it to SubValues
, UpValues
, etc. That can probably be done with Stack
but I am not as comfortable with that method as Leonid is so I shall leave it to a last resort.
SetAttributes[{clone, parent}, HoldAll]
clone[from_, to_] := Scan[(#[to] = #[from];) &, {DownValues, Attributes}]
parent[lhs_ -> rhs_] := (
clone[lhs, rhs];
Unprotect[rhs];
x_rhs :=
Internal`InheritedBlock[{rhs = lhs},
Unprotect[lhs];
clone[rhs, lhs];
x
]
)
Call it before definitions are made to cases
:
parent[Cases -> cases];
Then add definitions to cases
as desired:
SetAttributes[cases, HoldFirst] (* test of Attributes *)
cases[a_, b_, "foo"] := cases[2^a, b, {-1}] (* test of DownValues *)
Result:
cases[1 + 3, _, "foo"]
{2, 1, 3}