The following is an attempt for making a general purpose function for this task:
ClearAll[allowNonSymbol]
SetAttributes[allowNonSymbol, HoldAll]
allowNonSymbol[func : (h : Set | SetDelayed)[lhs_, rhs_]] :=
With[{blank = Verbatim[#][___] & /@ (Blank | BlankSequence | BlankNullSequence)},
Module[{newFunc, independentVar}, {newFunc, {independentVar}} =
Reap[Hold@func /.
var_ (holder : blank) :> RuleCondition[Sow@var; Pattern[var, holder]] /.
var_ Verbatim[PatternTest][holder : blank, test_] :>
RuleCondition[Sow@var; PatternTest[Pattern[var, holder], test]] // Quiet, _,
Union[#2] &];
With[{rule = # -> Unique[] & /@ independentVar}, newFunc /. rule // ReleaseHold]]]
allowNonSymbol[func : Function[independentVar_, rhs__]] :=
With[{rule = # -> Unique[] & /@ Flatten@{independentVar}},
Hold[func] /. rule // ReleaseHold]
#Usage
Clear[f, relativez]
allowNonSymbol[f[z[bar] _] := z[bar]^2];
allowNonSymbol[relativez[z_, z[bar] _] := z/z[bar]];
f[3]
(* 9 *)
relativez[2, 3]
(* 2/3 *)
allowNonSymbol
can be used on pure function:
sin = allowNonSymbol@Function[b[1], Sin@b[1]];
Sin[2.]
(* 0.909297 *)
It can handle BlankSequence[]
(__
) and BlankNullSequence[]
(___
):
allowNonSymbol[times[argu[n] __] := Times[argu[n]]]
times[2, 3, 5]
(* 30 *)
allowNonSymbol[join[lst_, ele[i] ___] := Join[lst, ele[i]]]
join[{3}]
(* {3} *)
It can also handle _h
and PatternTest
:
Clear[f, g]
allowNonSymbol[f[a[2] _Integer] := 2 a[2]]
f[2]
(* 4 *)
f[2.]
(* f[2.] *)
allowNonSymbol[g[a[1] _?NumericQ] := a[1]]
g[3]
Clear[a]; g[a]
(* g[a] *)
#Known issue
Patterns like
a[1]:{_Integer}
can't be used, and it seems to be impossible to overcome the issue, because Mathematica notebook simpliy can't parse the expression:a[1] : {_Integer}
- Patterns like
Pattern[a[1], {_Integer}]
isn't supported yet.