I have some code that uses a list of replacement rules to inject values (physical constants for different materials) into a more complicated expression. This is convenient since I can tweak the values in my rule list independently from the code and they appear in the code as familiar greek letters for the values until substitution.
This all works fine in the normal context of a notebook, but when I move the code to a package the symbols in my expression are in the package context and the are not replaced by applying ReplaceAll
with a list of symbols created in the default Global` context.
Is there a simple way to get around this problem without resorting to tedious incorporation of a long list of named options, or explicitly passing the constants in the function code, or using order dependent lists of unlabeled data?
Can this be fixed by applying a pure function to the replacement rule lists? Something that rewrites the symbol contexts just before calling ReplaceAll
for the substitution? It should transform something like this
{Global`x->1.0, Global`y->2.*^10, Global`z->0.123}
into something like this:
{MyContext`x->1.0, MyContext`y->2.*^10, MyContext`z->0.123}
with the intention of making substitutions in a call to the packaged code in a way that is transparent to the user who simply inputs a list built in a regular notebook.
Does anyone have a better arrangement for this use case?
Here's a short example of what I mean:
BeginPackage["foo`"]
Unprotect @@ Names["foo`*"];
ClearAll @@ Names["foo`*"];
f::usage = "sol=f[x,plist]"
Begin["`Private`"]
f[x_, plist_] := x + y + z /. plist;
End[]
Protect @@ Names["foo`*"];
EndPackage[]
paramList = {y -> 1, z -> 2};
sol = foo`f[x, paramList]
which gives
(*x + foo`Private`y + foo`Private`z*)
while the desired ouput would be
(*3 + x*)
y
andz
in your example are in package context while they
andz
you are passing are from global context. I suggest writing this as I showed below, otherwise, you'll have to do hacks and other such things to fix things. So better do things right from the start (my 2 cents ofcourse) $\endgroup$paramList = {y -> 1, z -> 2} mySymbols = {x, y, z}; sol = f[mySymbols, paramList]
You only have to type the list once and then use it. This is for me the clean solution, other than making a wrong API, then try to figure what hacks to do to fix things afterwords. But this is just how I would do it. If you wait more, may be you'll have better suggestions how to handle this. good luck. $\endgroup$