We can replace something, in all definitions associated with a symbol, using function like this:
ClearAll[replaceExtendedDefinition]
SetAttributes[replaceExtendedDefinition, HoldFirst]
replaceExtendedDefinition[sym_, rules_] :=
Replace[
Language`ExtendedDefinition[sym]
,
(rule:Rule | RuleDelayed)[lhs_, rhs_] :>
With[
{eval =
With[
{heldRhs =
Replace[HoldComplete[rhs], rules, {1, Infinity}]}
,
Function[Null, rule[lhs, #], HoldAllComplete] @@ heldRhs
]}
,
eval /; True
]
,
{4, 5}
]
We can easily use it for all symbols from given context:
Scan[
(Language`ExtendedDefinition[#] =
replaceExtendedDefinition[#, HoldPattern@explicitvalue -> explicitvalue])&
,
Names["Test`*"]
]
Now we have:
??testFunction
(* - *)
(* testFunction[] := {123, {1, 1, 1}, Hold[{1, 1, 1}]} *)
replaceExtendedDefinition
in current form replaces all occurrences of replaced expressions on right hand side of definitions including those in local scopes, which may not be desirable. Its advantage is that it can replace more complicated expressions, not only symbols.
Version using Szabolcs's With
trick. It avoids replacements of symbols in local scopes, but does not allow replacements of more complicated expressions.
ClearAll[extendedDefinitionWithReplacement]
SetAttributes[extendedDefinitionWithReplacement, HoldAll]
extendedDefinitionWithReplacement[vars : {(_Set | _SetDelayed) ..}, sym_] :=
ReplacePart[
Unevaluated @ With[vars, Null],
{2} -> Language`ExtendedDefinition[sym]
]
Test symbol with all possible ...Values
:
ClearAll[test, var]
test::usage = "test is a test symbol.";
SetAttributes[test, Listable];
Format[test] = "TEST" <> ToString[var];
test[var][var_] := var;
test[var_] := var;
test[1, var] := Module[{var}, var];
f[test] ^= var;
N[test] = var;
Default[test] = var;
test = var;
Its extended definition:
Language`ExtendedDefinition[test]
(* Language`DefinitionList[TESTvar -> {
OwnValues -> HoldPattern[TESTvar] :> var,
SubValues -> {HoldPattern[TESTvar[var][var_]] : >var},
UpValues -> {HoldPattern[f[TESTvar]]->var},
DownValues -> {
HoldPattern[TESTvar[1, var]] :> Module[{var},var],
HoldPattern[TESTvar[var_]] :> var},
NValues -> {HoldPattern[N[TESTvar, {MachinePrecision, MachinePrecision}]] -> var},
FormatValues -> {
HoldPattern[TESTvar] :> "TEST" <> ToString[var],
HoldPattern[MakeBoxes[TESTvar, FormatType_]] :> Format["TEST" <> ToString[var], FormatType]},
DefaultValues -> {HoldPattern[Default[TESTvar]] -> var},
Messages->{HoldPattern[TESTvar::usage] -> test is a test symbol.},
Attributes->{Listable}
}] *)
And definition with replacement:
extendedDefinitionWithReplacement[{var = value}, test]
(* Language`DefinitionList[TESTvar -> {
OwnValues -> HoldPattern[TESTvar] :> value,
SubValues -> {HoldPattern[TESTvar[value][var_]] :> var},
UpValues -> {HoldPattern[f[TESTvar]] -> value},
DownValues -> {
HoldPattern[TESTvar[1, value]] :> Module[{var}, var],
HoldPattern[TESTvar[var_]] :> var
},
NValues -> {HoldPattern[N[TESTvar, {MachinePrecision, MachinePrecision}]] -> value},
FormatValues -> {
HoldPattern[TESTvar] :> "TEST" <> ToString[value],
HoldPattern[MakeBoxes[TESTvar, FormatType$_]] :> Format["TEST" <> ToString[value], FormatType$]},
DefaultValues -> {HoldPattern[Default[TESTvar]] -> value},
Messages -> {HoldPattern[TESTvar::usage] -> test is a test symbol.},
Attributes->{Listable}
}] *)
TemplateExpression
could be made to do what you require? $\endgroup$explicitvalue
in the private part of the package. We need to reference it in the public part, e.g. addexplicitvalue::usage = "..."
before the private part. $\endgroup$Test`explicitvalue = {1, 1, 1}
beforeGet@path
. $\endgroup$testFunction
as written is defined to useTest`Private`explicitvalue
(I'm thinking defensively). $\endgroup$