Shotgun thoughts:
You don't need the
Hold
/ReleaseHold
pair;Unevaluated
will do:Unevaluated[f] /. rules
You can use direct destructuring to extract
extvar
:curvature[f_, range : {var_, __}] :=
By extracting
var
as above you canBlock
it directly, simplifying everything.You can leave the
Table
variable out of the mainBlock
as it is already localized.res /. {z_} :> z
can replace the lineIf[Length[res] == 1, res = res[[1]]]; res
In fact
res
can be eliminated and the rule applied to theTable
You can pre-evaluate your
1/Sqrt[Total[D[fn,var]^2]]
expression; this should be faster, and also eliminates the need for the replacement inside theTable
Putting it together I would write:
SetAttributes[curvature, HoldAll];
curvature[f_, range : {var_, __}] :=
Block[{var},
Module[{fn},
fn = If[ListQ[f], f, {var, f}];
fn = 1/Sqrt[Total[D[fn, var]^2]];
Table[fn, range] /. {z_} :> z
]
]
You will notice red highlighting of var
signifying a possible conflict; this is not a problem and is in fact exactly what I desire: the sharing of var
between the function, the Block
, and the Table
.
My answer originally had fn
in the Block
declaration. This is bad because conceivably fn
could appear in the function expression and this would conflict. I have moved it to a Module
now.
An alternative is to do without that symbol entirely by writing the lines of code as Functions:
curvature[f_, range : {var_, __}] :=
Block[{var},
Table[#, range] /. {z_} :> z &[
1/Sqrt[Total[D[#, var]^2]] &[
If[ListQ[f], f, {var, f}]
]
]
]