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.

At times I'll find myself building a some interface component where I want to have some localized dynamic variables, and while testing I might realize that some bit of the code needs to change, which means I lose the current state of all the localized variables, some which might be bothersome to set once again. In such case my typical solution is something like:

DynamicModule[{
  persistant = 21,
  transient = 2},
      Column[{
          InputField[Dynamic[persistant]],
          InputField[Dynamic[transient]],
          Dynamic[persistant*transient],
      }],
  Deinitialization :> (saveVar = persistant),
  Initialization :> (FinishDynamic[]; If[ValueQ[saveVar], persistant = saveVar])
]

Which will retain the value of persistant even if I rerun the code. However if you have a bunch of variables that you want to retain it becomes bothersome to save each and everyoen and reload them, and what more you might want to save DownValues as well as OwnValues so I thought that I'd make a bit more general solution using DumpSave or Save to save definitions and load them in using Get:

Deinitialization :> (If[FileExistsQ["tempfile"], DeleteFile["tempfile"]];
       Save["tempfile", {persistant}]),
Initialization :> (FinishDynamic[]; If[FileExistsQ["tempfile"], get["tempfile"]])

But when trying this I've run into problems since the names that are saved are the local temporary names eg. FEpersistant$$161instead of justpersistant` which means the values aren't loaded back again correctly. So my question is whether theres either another way to achieve a similar result or if the naming problem can be resolved

share|improve this question
add comment

1 Answer 1

up vote 2 down vote accepted

This can be done by reading the saved symbol and copying it to the new one

Below I define copySymbol that copies the definition of a symbol to another and making sure that the FE context is not excluded.

saveSymbol Saves a given symbol in $TemporaryDirectory, for instance FE'abc$123 is saved as MMAsave_abc_FE'abc$123 (read ' as `)

readSymbol takes a name and a destination symbol, and Gets the corresponding definition and copies it to the destination symbol, with some trickery to avoid evaluation of OwnValues along the way. By looking at the last part of the filename it knows which symbol to copy.

removeSymbol takes a name as argument and removes everything in $TemporaryDirectory that begins with "MMAsave_"<>name<>"_" to help remove all old definitions.

ClearAll[copySymbol, saveSymbol, readSymbol];
Attributes[copySymbol] = HoldAll;
copySymbol[old_ /; Head[old] =!= Hold, new_] := (
  Language`ExtendedFullDefinition[new] = 
   Language`ExtendedFullDefinition[old, "ExcludedContexts" -> 
      DeleteCases[
       OptionValue[Language`ExtendedFullDefinition, "ExcludedContexts"],
       "FE"]] /. HoldPattern[old] :> new)

Attributes[saveSymbol] = {HoldFirst};
SavePrefix = FileNameJoin@{$TemporaryDirectory, "MMAsave_"};
    saveSymbol[sym_] := With[
      {name = StringReplace[SymbolName[Unevaluated[sym]], 
         name_ ~~ "$" ~~ ___ :> name]},
  Save[SavePrefix <> name <> "_" <> Context[sym] <> 
       SymbolName[Unevaluated[sym]], sym]]

Attributes[readSymbol] = {HoldAll};
readSymbol[name_String, dest_Symbol] := Block[{
   file = First@FileNames[SavePrefix <> name <> "_*"],symname},
  symname = StringReplace[file, 
    SavePrefix ~~ name ~~ "_" ~~ symname_ :> symname];
  Get[file];
  With[{old = ToExpression[symname, InputForm, Hold]},
   copySymbol[old, dest] /. 
    HoldPattern[copySymbol[Hold[a_], b_]] :> copySymbol[a, b]
   ]]

removeSymbol[name_String] := DeleteFile@FileNames[SavePrefix <> name <> "_*"];
savedSymbolQ[name_] := Length[FileNames[SavePrefix <> name <> "_*"]] != 0

It can be used as follows:

DynamicModule[{persistent = 21, transient = 2}, 
 Column[{InputField[Dynamic[persistent]], 
   InputField[Dynamic[transient]], Dynamic[persistent*transient]}],
 Deinitialization :> (removeSymbol["persistent"]; saveSymbol[persistent]), 
 Initialization :> (FinishDynamic[]; 
   If[savedSymbolQ["persistent"], readSymbol["persistent", persistent]])]
share|improve this answer
add comment

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.