# Is Package development (via InitializationCells) compatible with creating new Notations (via MakeExpressions)?

Can new (lower-level) notations be readily used within package code?

There are a few notational additions that might improve my code base but I'm not sure if these will end up being more trouble than they are worth.

For example, take a first step in an attempt to implement a more “natural” and “efficient” struct; Using MakeExpression

MakeExpression[RowBox[{lhs___, x__, "\[CenterDot]", y__, rhs___}],StandardForm] :=
MakeExpression[RowBox[{lhs, RowBox[{x, "[", y, "]"}], rhs}],StandardForm];


yields a more OO-like notation

In[2]:= obj."field1"."field2"

Out[2]:= obj["field1"]["field2"]

[Here the . is mimicking Mma's \[CenterDot] -SE won't let newbies post images)]

In any (frontend) package development however, placing obj."field1"."field2" within an initialization cell causes this exact form to be placed in the corresponding .m file. It is this form that is subsequently loaded in by Get i.e. without any of the frontend parsing provided by the MakeExpression definition.

Hence the intended notation does not take effect in packages (instead CenterDot in CenterDot[obj,"field1","field2"] becomes unintentionally defined but a priori I want to avoid overloading CenterDot for efficiency/inheritance/encapsulation reasons).

One hack is to forcibly activate the frontend's parser while loading in packages by invisibly opening up the .m file and evaluating all initialization cells - something along the lines of:

ParsingGet[pathTomFile_] := With[{nb = NotebookOpen[pathTomFile, Visible -> False]},
FrontEndTokenExecute[nb, "EvaluateInitialization"];
NotebookClose@nb]


This then creates such messiness as having to explicitly integrate with Get's package name arguments, multi-argument BeginPackage calls, "stub symbols" and avoiding developmental surprises such as obj."field1"."field2" not reflecting package updates in single frontend tests such as (ParsingGet[mfilepath]; obj."field1"."field2") (the kernel will grab obj."field1"."field2" and not let go).

I’m a bit wary of going down a path that seems to quickly set off a series of cascading hacks but on the other hand I’m wondering if I’ve missed something (an InitializionCell-like option value?) or if anyone has extensively used such notational (or perhaps more accurately language) changes in package development?

One might expect they should be able to play nicely together since a whole package has been devoted to these lower-level notations in Mma (Jason Harris’s Notation package) and anyone going down this more involved notational route would surely want to harness them in their own packages at some point?

-
Hi Ronald, welcome to Mathematica@SE! Hope you like it here and enjoy answering questions too. When you get the ability to post images (which will be pretty soon) you may want to use this Mathematica image uploader. – Sjoerd C. de Vries Sep 10 '12 at 21:44
Thanks Sjoerd. Yes good to aim for a balance between the give and take. – Ronald Monson Sep 11 '12 at 21:46

## 2 Answers

"these will end up being more trouble than they are worth." - to my mind, this is a very accurate assessment of the situation.

As far as syntax is concerned, you will face multiple obstacles, starting from package and front-end parser differences you outlined (which makes the use of e.g. Notation package in packages quite non-trivial if not problematic), and ending with the limitations of the Notation package itself. If you need a pre-processor to change some of the Mathematica syntax, the general solution would require a full Mathematica parser with modifiable grammar, something like preprocessors in some functional languages (camlp4 in Ocaml for example). Everything else (including the Notation package) will have lots of limitations.

What is worse, is that you seem to be willing to add some OO features, and even if you succeed with the syntax, you will run into the problems of semantics. And these are, I believe, unsolvable without adding a certain amount of native OO support to Mathematica. There were a number of discussions regarding OO in Mathematica, here are some links:

Struct-equivalent-in-mathematica

Struct-data-type-in-mathematica

Object-oriented-mathematica-programming

Question-on-setting-up-a-struct-in-mathematica-safely

Mathematica-oo-system-or-alternatives

which you may want to check out.

EDIT

To be a bit more constructive and illustrate what can be involved in making Notation work in packages, here is a link to a Mathgroup thread where I described one possible way to use it.

-
"these will end up being more trouble than they are worth." - to my mind, this is a very accurate assessment of the situation.-- Yes this is what I suspect in which case it might be worth pointing out in any posts that use MakeExpression i.e. there is distinction here between Notation (for end-users of a package) and Language (for package authors). – Ronald Monson Sep 10 '12 at 21:42
@RonaldMonson I added a link to the thread discussing the use of Notation package in packages. – Leonid Shifrin Sep 10 '12 at 21:49
Yes I had looked at the OO posts but had considered some of the semantics and language design issues but I'm not totally convinced that the issues identified (including the mma's immutability you've discussed) are not somewhat manageable. And yes this would be far from a trivial exercise but I really want this capability :) oh well maybe some native support is around the corner? – Ronald Monson Sep 10 '12 at 21:56
@RonaldMonson The biggest problems are to my mind performance and garbage - collection. If you plan to use OO for the parts of your code where you can live with truly horrible performance, then you may as well use some of the existing attempts to integrate OO into mma. You may want to check out Objectica - it is a commercial project which seems fairly complete. I wonder how its author has solved those problems I outlined though. Now, I ended up simply linking to Java when I need massive OO functionality, and implementing that in Java - since Java has full-fledged OO, I don't waste any time. – Leonid Shifrin Sep 10 '12 at 22:00
@RonaldMonson You may want to check out my Java reloader which automates some steps for such development. I was also toying with an idea of adding some OO layer to mma based on Java (so that Java classes are generated, compiled and linked back behind the scenes), but JLink symbolic overhead kills this for many interesting cases (cost of call-backs to Mathematica is huge). In any case, I plan to look at it further if/as time permits. I agree that the native support would be very nice. – Leonid Shifrin Sep 10 '12 at 22:04

Ignoring Leonid's arguments on whether OO is a good idea, or not, I would like to suggest something a bit different. Instead of using MakeExpression, set a DownValue on CenterDot directly:

a_ \[CenterDot] b_ := a[b]
a_ \[CenterDot]b_\[CenterDot]c__ := a[b]\[CenterDot]c


where the second definition makes \[CenterDot] left associative allowing you to string long expressions together. For example,

f\[CenterDot]q
f\[CenterDot]q\[CenterDot]r\[CenterDot]s
(*
f[q]
f[q][r][s]
*)


As this uses a built-in operator that does not have any associated definition, it should work just fine in your packages.

-
What you suggest with CenterDot is in effect what happens now when the package is loaded in the normal way. The problem with this is you lose encapsulation and efficiency. In effect with ongoing use you are massively overloading CenterDot which may lead to efficiency issues while encapsulation-wise you lose the ability to removing or save an object (including all its attributes/methods etc) with a simple call. I think the best bet for now is just to use the "functional" form e.g. obj["field1"]=val etc. – Ronald Monson Sep 11 '12 at 21:37
I don't think Leonid was talking about the merits of OO per se (he can speak for himself but my impression it is that within mma he thinks it would be a good idea) but was agreeing that using notation changes in packages will ultimately be problematic and indeed this seems to be the take-home message of the post - "don't go there". – Ronald Monson Sep 11 '12 at 21:41
Having said this, it's worth bearing in mind that this is the current situation; I imagine it really wouldn't take too much to ensure that NotebookSave contains an option (default?) that includes custom-made parsing rules (given it already uses native parsing rules) so maybe this will change in the future. – Ronald Monson Sep 11 '12 at 21:42
@RonaldMonson you said, you are massively overloading CenterDot which is incorrect. Only two additional definitions are created. This change does not directly affect any other object. And, I do not see how this is substantially different than using MakeExpression. It must be interpreted at some point which might necessitate some slow down. But, you are correct, you cannot limit what objects are affected, with either method, which would potentially cause encapsulation problems. – rcollyer Sep 11 '12 at 22:25
A new DownValue for CenterDot will be created every time a new object is created thereby progressively overloading it (even if other objects are unaffected). But yes perhaps the efficiency implications are not as great as implied by the term massively overloading. I think the encapsulation limitation however, remains as reason alone to avoid such usage. – Ronald Monson Sep 11 '12 at 22:59