16
$\begingroup$

How can I implement persistent storage for packages/applications? For example, how can my package have settings which persist across sessions?


I have implemented this more than once in the past. This question is to share our solutions and keep them for future reference. This the kind of application where reliability is paramount because it is often used in packages that may be distributed to many people.

Things to pay attention to:

  • Compatibility with different Mathematica versions. This is a typical requirement for packages. Solutions must be compatible with 10.0 and all later versions. Earlier version compatibility is even better, but I'm not asking for it because associations are too convenient ...

  • Persistent storage is useful for package settings. Solutions presented here shouldn't stand in the way of changing the settings format in future versions of the package (adding or removing settings, changing the format, etc.)

  • Corrupted storage files must be handled gracefully.

  • Given that this is meant to be included in other packages, simple and short solutions are preferred.

  • Anything else I didn't think of?

$\endgroup$
11
  • $\begingroup$ What about Resourceobject? $\endgroup$
    – rcollyer
    Commented Nov 6, 2016 at 15:32
  • $\begingroup$ Could you expand on what you might use this persistent storage for? $\endgroup$
    – Chris K
    Commented Nov 6, 2016 at 16:13
  • $\begingroup$ @ChrisK The main uses case I have in mind are persistent settings. E.g. MaTeX must store the location of the pdflatex executable permanently, so I use some persistent storage for this. MATLink also need to remember if it should try to use a 32-bit or 64-bit MATLAB. Another possible use case is caching certain information. I'm primarily interested in use cases where the data that needs to be stored is small. $\endgroup$
    – Szabolcs
    Commented Nov 6, 2016 at 17:46
  • 1
    $\begingroup$ What about CurrentValue[$FrontEnd, {TaggingRules, "MaTeX", "pdflatexpath"}] = ..., this is what I am doing (unles I missed the point) $\endgroup$
    – Kuba
    Commented Nov 7, 2016 at 1:58
  • 1
    $\begingroup$ @masterxilo OK, I'll post a solution myself, and I hope others will share theirs then. I won't be able to do it until tonight though. I prefer the file in $UserBaseDirectory/ApplicationData/PackageName, not in the package directory itself. The package directory may get removed when the package is updated. $\endgroup$
    – Szabolcs
    Commented Nov 9, 2016 at 7:53

1 Answer 1

7
$\begingroup$

As stated in comments above, it does not meet all your requirements. Nevertheless I find it extremely useful and applicable in many situations.

That is to use CurrentValue[$FrontEnd, {TaggingRules, "MyApp", "setting1"}] to reference your package settings.

Advantages:

  • no additional files

    Mathematica will automatically store them in init.m file. You don't even need to check whether your package is installed, which is very, very useful when it has a complex installation/autoload/updating scheme.

  • it is part of Mathematica setup, could it be more compatible?

    Tagging rules are there since V4 or something (not sure if this works there but should be no problem in V7, the earliest version I worked with)

  • it supports $FrontEndSession inheritance (see FrontEnd options)

    so you don't need to worry about switching off something that was enabled temporarily

  • automatically translates to nested rules:

    CurrentValue[$FrontEnd, {TaggingRules, "MyApp", "param1"}] = True

    translates to: {..., "MyApp" -> {"param1" -> True}}

    with syntax that feels like using Associations

  • hard to corrupt that setup since it is done automatically

  • for missing entries there is an undocumented 3rd argument of CurrentValue

    It sets that value if you try to reference a missing key:

    CurrentValue[$FrontEnd, {TaggingRules}]
    

    {..., "MyApp" -> {"param1" -> True}}

    CurrentValue[
      $FrontEnd, {TaggingRules, "MyApp", "param2"}, "defaultparam2"
    ] === "defaultparam2"
    

    True

    CurrentValue[$FrontEnd, {TaggingRules}]
    

    {..., "MyApp" -> {"param1" -> True, "param2" -> "defaultparam2"}}

Issues:

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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