In this question, there is a beautiful method to copy a symbol. However, i'm not able to use it as an addon to my package. So the main question is
How to rename/copy a function defined in a package by loading one of its sub packages ?
I'll try to explain that in an minimal example
Let's say I have a package A`
BeginPackage["A`"]
f::usage = "My function";
Begin["Private`"];
f[x_] := x^2;
End[]
EndPackage[];
Due to the fact, that f
was earlier named g
and I would like my old notebooks still to work (and though I can rewrite my package functions, I would like to have a kind of legacy package (okay I could also just copy my Package and load the old or the new one - despite debugging twice that works)), so I define something like
BeginPackage["A`Sub`"]
SetAttributes[copy,HoldFirst];
new_~copy~org_:=With[{prop={Attributes,UpValues,OwnValues,DownValues,SubValues,NValues,FormatValues,Messages,Options}},ClearAll@new;
Set[#@new,#@org/.HoldPattern@org:>new]&~Scan~prop;]
(* Start copying*)
g~copy~A`f;
EndPackage[];
(using the great idea of the copy from above). Here I'll use A`f
to avoid shadowing problems (and put this Sub.m
in the subdirectory A/
of the A.m
).
But if I now try to use that, say in a notebook (ATest.nb
inside the same directory as A.m
)
$Path = Join[$Path, {NotebookDirectory[]}];
Needs["A`"];
Of course f
works as intended, but loading
Needs["A`Sub`"];
does not make g
available as a copy of f
(and does neither report any error). Though, executing the cells of Sub.m
directly one by one does. Of course, i don't want to specify g::usage
because that should be obtained by copying from f. I think it might depend on the context, but I can't see why and how.
What am I missing here?
Update
As Albert pointed out, rm -rf s solution below should be extended using a Private`
area for the copy
function. Then the sub package providing the old names looks like the following
BeginPackage["A`Sub`",{"A`"}];
Begin["Private`"];
SetAttributes[copy,HoldFirst];
new_~copy~org_:=
With[{prop={Attributes,UpValues,OwnValues,DownValues,SubValues,NValues,FormatValues,Messages,Options}},
ClearAll@new;
Set[#@new,#@org/.HoldPattern@org:>new]&~Scan~prop;
];
(* Start copying*)
A`Sub`g~copy~A`f;
End[]
EndPackage[];
Then the right operand of copy (the original f
) needs the context A`
and the left one, g
(in order not to be private) the context A`Sub`
(due to the fact that ::usage
should also be copied from f
.
A`Sub`
does not know aboutA`
, so you should loadNeeds["A`"]
immediately afterBeginPackage["A`Sub`"]
. I haven't run your code, but can you try the above and see if it works (use a fresh kernel, etc.). If it does, I'll post it as an answer. $\endgroup$BeginPackage["A`Sub`",{"A`"}]
(and learned about the double ticks), it works. Though my eyes hurt, that the subpackage has to load it's parent; but I'll have to get used to that I think. Works fine :) $\endgroup$Begin
andEnd
: as it is written now, you'll also exportcopy
,prop
,new
andorg
along withg
... $\endgroup$