5
$\begingroup$

I have a large number of variables/functions with subscripts and use definitions with memoization to avoid recomputing them within a kernel session, but I cannot figure out how to export them all for long-term storage. (Ideally human-readable and in a way that also works when running the code from the command line without the Notebook interface).

I have symbolized the subscripted variables so I can use functions that only operate on symbols (in particular Save, Clear). Below is a minimum working example.

Creating and saving the variables as symbols works fine:


Get["Notation`"]
Symbolize[ParsedBoxWrapper[SubscriptBox["_", "_"]]]

a⎵Subscript⎵1 = 2    
a⎵Subscript⎵test = 3

Names[StringJoin[$Context, "*"]]

Information[a⎵Subscript⎵1, LongForm -> False]
Information[a⎵Subscript⎵test, LongForm -> False]

Information["a⎵Subscript⎵1", 
 LongForm -> False]
Information["a⎵Subscript⎵test", 
 LongForm -> False]

Save[ NotebookDirectory[] <> "test_symbolize_save.m", "`*"]

symbolized variables with subscripts before saving

But when I open a new notebook and load the saved file it loads neither the original variables with subscript (only the internal representation) nor the associated values (even though they are contained in the exported file):


Get["Notation`"]
Symbolize[ParsedBoxWrapper[SubscriptBox["_", "_"]]]

Get[StringJoin[NotebookDirectory[], "test_symbolize_save.m"]]; 

Names[StringJoin[$Context, "*"]]

Information[2, LongForm -> False]
Information[3, LongForm -> False]

Information["a⎵Subscript⎵1", LongForm -> False]
Information["a⎵Subscript⎵test", LongForm -> False]

symbolized variables with subscripts after loading

I entered the subscript via "Ctrl+_" for the first ? calls before exporting and after importing. The RawInputForm of those calls after importing probably points to the underlying issue, as the intended reference to the subscripted variable points to its stored value instead.

Content of the file exported with Save:


a⎵Subscript⎵1 = 2     
a⎵Subscript⎵test = 3

(I also tried DumpSave, and while that saved the variable/function name, it did not save the subscripts and associated values.)

My question: How can I easily and consistently create, export, and import variables/functions with subscripts, so the definitions and computed values are fully restored after import?

I don't have to use symbolize (in fact i never did before), but when I tried Save without symbolizing it did not actually export my variables/functions with subscripts.

$\endgroup$
  • 6
    $\begingroup$ I hate to say it, but I would recommend against using Notation and just stick to one dimensional symbols. There are so fewer headaches... $\endgroup$ – user6014 Oct 30 '18 at 23:57
  • 1
    $\begingroup$ The issue is that the Notation rules weren't saved via Save. How you get that to work I'm not entirely sure, but try exporting the OwnValues, DownValues, and FormatValues explicitly. That will work at minimum. $\endgroup$ – b3m2a1 Oct 31 '18 at 0:12
6
+50
$\begingroup$

You could just save global variables and Subscript:

Save[file, {"`*", "Subscript"}]

If you really want to use the Notation package, then the problem is that the functions that know how to convert back and forth between the symbolized and unsymbolized forms are not being saved. Here are your definitions:

Get["Notation`"]
Symbolize[ParsedBoxWrapper[SubscriptBox["_","_"]]]

Subscript[a, 1] = 2
Subscript[a, test] = 3

2

3

Here is how to save the needed symbols from the notation package:

Block[{NotationBoxTag, Notation`Private`createSymbolizeSingleInstance, 
       MakeExpression, $ContextPath},
SetAttributes[{$ContextPath},Protected];
    Save[
        FileNameJoin[{NotebookDirectory[], "test_symbolize_save.m"}],
        {"`*", NotationMakeBoxes, NotationMakeExpression}
    ]
]

(The above Block is not strictly necessary, but there is no need to save all of the definitions when you are going to reload the Notation package anyway)

Then quit the kernel, and reload:

Get["Notation`"]
Symbolize[ParsedBoxWrapper[SubscriptBox["_","_"]]]

Get[FileNameJoin[{NotebookDirectory[], "test_symbolize_save.m"}]];

Subscript[a, 1]
Subscript[a, test]

2

3

Here are the contents of the saved file:

Import[FileNameJoin[{NotebookDirectory[], "test_symbolize_save.m"}], "String"]
a⎵Subscript⎵1 = 2  
a⎵Subscript⎵test = 3
Attributes[Notation`NotationMakeBoxes] = {HoldAllComplete}

Notation`NotationMakeBoxes[HoldPattern[Notation`ParsedBoxWrapper][
      Notation`Private`boxes__], Notation`Private`anyForm_] := 
    TemplateBox[{Notation`Private`boxes}, "NotationTemplateTag"]

Notation`NotationMakeBoxes[a⎵Subscript⎵1, 
      StandardForm] /; MemberQ[$ContextPath, "Global`"] := 
    SubscriptBox["a", "1"]

Notation`NotationMakeBoxes[a⎵Subscript⎵test, 
      StandardForm] /; MemberQ[$ContextPath, "Global`"] := 
    SubscriptBox["a", "test"]

Notation`NotationMakeBoxes /: Notation`NotationMakeBoxes::usage = 
     "NotationMakeBoxes is a private version of MakeBoxes."

Notation`NotationMakeExpression[TagBox[Notation`Private`boxes_, 
      Notation`NotationBoxTag, Notation`Private`opts___], 
     Notation`Private`anyForm_] := HoldComplete[Notation`ParsedBoxWrapper[
      Notation`Private`boxes]]

Notation`NotationMakeExpression[TagBox[Notation`Private`boxes_, 
      "NotationTemplateTag", Notation`Private`opts___], 
     Notation`Private`anyForm_] := HoldComplete[Notation`ParsedBoxWrapper[
      Notation`Private`boxes]]

Notation`NotationMakeExpression[SubscriptBox["a", "1"], StandardForm] /; 
     MemberQ[$ContextPath, "Global`"] := HoldComplete[
     a⎵Subscript⎵1]

Notation`NotationMakeExpression[SubscriptBox["a", "test"], StandardForm] /; 
     MemberQ[$ContextPath, "Global`"] := HoldComplete[
     a⎵Subscript⎵test]

Notation`NotationMakeExpression[Notation`Private`matchedBoxes:
       SubscriptBox[_, _], StandardForm] /; MemberQ[$ContextPath, 
      "Global`"] := (Notation`Private`createSymbolizeSingleInstance[
      Notation`Private`matchedBoxes, "Global`"]; 
     MakeExpression[Notation`Private`matchedBoxes, StandardForm])

Notation`NotationMakeExpression /: Notation`NotationMakeExpression::usage = 
     "NotationMakeExpression is a private version of MakeExpression."
$\endgroup$
  • $\begingroup$ Is it possible to use DumpSave instead of Save? I tried Block[{NotationBoxTag, Notation`Private`createSymbolizeSingleInstance, MakeExpression, $ContextPath}, SetAttributes[{$ContextPath}, Protected]; DumpSave[FileNameJoin[{NotebookDirectory[], "test_symbolize_save.mx"}], {"Global`", NotationMakeBoxes, NotationMakeExpression}]] but it causes Syntax::sntxi: Incomplete expression; more input is needed . warning, which I don't quite understand. Tested in v11.2. BTW, v9 spits out ToExpression::esntx warning in addition. $\endgroup$ – xzczd Nov 11 '18 at 10:01
  • 1
    $\begingroup$ @xzczd If you want to use DumpSave, then there is no need to make the file readable. So, don't use Block, and it should work. $\endgroup$ – Carl Woll Nov 11 '18 at 19:56

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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