Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I would like to know how can I completely copy one Symbol to another. When I say copy, a refer to UpValues, DownValues, FormatValues.. and so on.

I created this function to do that, but I don't know if it's a good practice.

SetAttributes[copy,HoldFirst];
copy[new_Symbol,org_Symbol]:=Module[{},
    ClearAll@new;
    UpValues@new=UpValues@org/.org:> new;
    DownValues@new=DownValues@org/.org:> new;
    FormatValues@new=FormatValues@org/.org:> new;
    SetAttributes[new,Attributes[org]];
]

So I can copy some symbol b into a using a~copy~b.

There is a simpler way to do that? Or this approach is ok?


Update

Thanks for all comments. This is the evolution of the function above:

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;
]
share|improve this question
    
Do you have a good use case for this? Or is it just theoretical? –  Szabolcs Feb 21 '13 at 3:01
2  
There's some clone function of Leonid around, that does basically this. Don't forget Options, NValues, OwnValues, SubValues, Defaults. And make it HoldAll –  Rojo Feb 21 '13 at 3:01
1  
Also, you can't trust this for built-ins, some of which seem to have "hidden" values, or for ReadProtected and Locked symbols, or for symbols that are recognized as special by other functions –  Rojo Feb 21 '13 at 3:02
    
There's a subtlety: if org refers to org in its definition, will new keep referring to org or to new? –  Szabolcs Feb 21 '13 at 3:03
    
In other words, I wouldn't trust this too much unless you know the function you are cloning. And I don't know a better way to copy a symbol –  Rojo Feb 21 '13 at 3:04

2 Answers 2

up vote 27 down vote accepted

This is a simplification of your solution:

Language`ExtendedFullDefinition[new] = 
 Language`ExtendedFullDefinition[old] /. HoldPattern[old] :> new

I believe Language`ExtendedFullDefinition is used in transferring definitions between the main kernel and subkernels. Also note the HoldPattern on the LHS of the rule which ensures that OwnValues will work.


One thing to think about is: what should happen if old refers back to itself? Should new keep referring to old, or to itself? This solution, like yours, replaces the old in the definition as well.

share|improve this answer
    
Nice! I didn't know you could assign to that +1 –  Rojo Feb 21 '13 at 3:09
    
@Rojo I learned about it from Oleksandr. I'm not sure if anything can go wrong with this ... check the Options. As I said, it's meant to be used for transferring definitions to subkernels, and for some contexts this should be prevented. –  Szabolcs Feb 21 '13 at 3:12
    
Wow, much more simpler!! Tks! I have to think about the "old to itsef" question. I Don't know yet the best to my case. +1 –  Murta Feb 21 '13 at 3:14
    
Damn... I just came here to write this! Of course, I learned this from you, so it's right that you got to post it :) –  rm -rf Feb 21 '13 at 3:15
1  
@Akater Language`ExtendedFullDefinition has an ExcludedContexts option. Check if it's what's blocking the context of the package you want to use. –  Szabolcs May 27 at 13:07

Adding to Szabolcs's answer, it's better to use ExtendedDefinition instead of ExtendedFullDefinition.

In situation in which old symbol (the one that we want to copy), depends on anotherSymbol and anotherSymbol has old symbol somewhere in it's ...Values e.g.:

ClearAll[new, old, anotherSymbol]
old = anotherSymbol
anotherSymbol[] := 2 old

Full definition of old includes definition of anotherSymbol:

Language`ExtendedFullDefinition[old]
(* Language`DefinitionList[
    old -> {
        OwnValues -> HoldPattern[old] :> anotherSymbol, SubValues -> {},
        UpValues -> {}, DownValues -> {}, NValues -> {}, FormatValues -> {},
        DefaultValues -> {}, Messages -> {}, Attributes -> {}
    },
    anotherSymbol -> {
        OwnValues -> {}, SubValues -> {}, UpValues -> {},
        DownValues -> {HoldPattern[anotherSymbol[]] :> 2 old},
        NValues -> {}, FormatValues -> {}, DefaultValues -> {},
        Messages -> {}, Attributes -> {}
    }
] *)

Assignment using ExtendedFullDefinition:

Language`ExtendedFullDefinition[new] =
    Language`ExtendedFullDefinition[old] /. HoldPattern[old] :> new
(* Language`DefinitionList[
    new -> {
        OwnValues -> HoldPattern[new] :> anotherSymbol, SubValues -> {},
        UpValues -> {}, DownValues -> {}, NValues -> {}, FormatValues -> {},
        DefaultValues -> {}, Messages -> {}, Attributes -> {}
    },
    anotherSymbol -> {
        OwnValues -> {}, SubValues -> {}, UpValues -> {},
        DownValues -> {HoldPattern[anotherSymbol[]] :> 2 new},
        NValues -> {}, FormatValues -> {}, DefaultValues -> {},
        Messages -> {}, Attributes -> {}
    }
] *)

has a side effect. As we can see above, rule HoldPattern[old] :> new changes not only possible self references of old, discussed in Szabolcs's answer, but also references to old in definition of anotherSymbol.

By evaluating above assignment we have changed definition of anotherSymbol:

?? anotherSymbol
(* Global`anotherSymbol
anotherSymbol[]:=2 new *)

Language`ExtendedDefinition, in contrast to "Full" variant, returns and assigns only definition of symbol passed to it as argument.

ClearAll[new, old, anotherSymbol]
old = anotherSymbol
anotherSymbol[] := 2 old

Language`ExtendedDefinition[old]
(* Language`DefinitionList[
    old -> {
        OwnValues -> HoldPattern[old] :> anotherSymbol, SubValues -> {},
        UpValues -> {}, DownValues -> {}, NValues -> {}, FormatValues -> {},
        DefaultValues -> {}, Messages -> {}, Attributes -> {}
    }
] *)

Assignment to ExtendedDefinition:

Language`ExtendedDefinition[new] = 
    Language`ExtendedDefinition[old] /. HoldPattern[old] :> new
(* Language`DefinitionList[
    new -> {
        OwnValues -> HoldPattern[new] :> anotherSymbol, SubValues -> {},
        UpValues -> {}, DownValues -> {}, NValues -> {}, FormatValues -> {},
        DefaultValues -> {}, Messages -> {}, Attributes -> {}
    }
] *)

is free of side effect of ExtendedFullDefinition:

?? anotherSymbol
(* Global`anotherSymbol
anotherSymbol[]:=2 old *)

and of course correctly copies definition of old to new:

?? new
(* Global`new
new=anotherSymbol *)
share|improve this answer
    
Tks. Very interesting. +1 –  Murta Dec 11 at 22:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.