Re: ParsedBoxWrapper's in packages
- To: mathgroup at smc.vnet.net
- Subject: [mg115426] Re: ParsedBoxWrapper's in packages
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Tue, 11 Jan 2011 00:32:01 -0500 (EST)
Hi Yaroslav, I could offer some chain of hacks, which, while not perfect, seem to do it. First, an example package: BeginPackage["NotationTest`"] mySum; myElement; plus; Begin["`Private`"]; BeginPackage["Global`",{"Notation`","NotationTest`"}] InfixNotation[ParsedBoxWrapper["\[Element]"],myElement]; EndPackage[] mySum[a_ \[Element] list_,expr_]:=plus[a,expr]; End[] EndPackage[] Note that we wrap the calls to InfixNotation into BeginPackage and EndPackage in some special way. The next ingredient is a pretty dirty hack, for which I will probably be flamed: SetAttributes[loadWithNotations, HoldAll]; loadWithNotations[code_] := Module[{oldSDdefs = DownValues[SetDelayed], temp, result}, Needs["Notation`"]; Unprotect[SetDelayed]; def : _SetDelayed /; (temp; True) := With[{dv = DownValues[SetDelayed]}, Unprotect[SetDelayed]; Clear[SetDelayed]; ReleaseHold@MakeExpression[MakeBoxes[def], StandardForm]; DownValues[SetDelayed] = dv; Protect[SetDelayed]]; Protect[SetDelayed]; AbortProtect[Catch[Catch[result = code, _]]]; Unprotect[SetDelayed]; DownValues[SetDelayed] = oldSDdefs; Protect[SetDelayed]; result] You must define this function in the Global` context before you load the packages. Now, assuming that you placed your package where Mathematica can find it (or appended its directory tp $Path), here is how you use it: loadWithNotations[ Needs["NotationTest`"]; ] Let us now check the resulting definition: In[5]:= DownValues[mySum]//FullForm Out[5]//FullForm= List[RuleDelayed[HoldPattern[mySum[myElement[Pattern[NotationTest`Private`a,Blank[]], Pattern[NotationTest`Private`list,Blank[]]],Pattern[NotationTest`Private`expr,Blank[]]]], plus[NotationTest`Private`a,NotationTest`Private`expr]]] You can load several packages inside loadWithNotations. In each of these packages, you must isolate your calls to InfixNotation, as I did it here. Note that this will only work for definitions (with SetDelayed). Now, how does this work. It took me some time to figure this out. The problem is that Notation sticks to MakeBoxes/MakeExpression, which it redefines. But normally, when we read in packages (unlike when we enter expressions in interactive FrontEnd sessions), they are parsed by some different means, so MakeExpression is not invoked. So, what I did here was to force the code to undergo MakeBoxes->MakeExpression transition during the time SetDelayed executes, thereby forcing it to trigger the mechanisms of Notation. We need ReleaseHold because Notation`'s version of MakeBoxes wraps the result in HoldComplete, while we want it to execute. The reason why we need to wrap things in BeginPackage / EndPackage with Global` is that Notation` checks the $ContextPath for what is referred there as initializationContext variable, which must be on the $ContextPath. I can not say anything about the limitations of this approach, but it seems to work in simple cases. I haven't used Notation` package ever before, so it could be that I missed something important. Hope this helps. Regards, Leonid On Mon, Jan 10, 2011 at 10:39 AM, Yaroslav Bulatov <yaroslavvb at gmail.com>wrote: > I'm trying to turn my notebooks into stand-alone packages and I'm > running into problems with Notation package. In particular, I'm using > Notation package and InfixNotation, and when I save notebook as a > package, I get "ParsedBoxWrapper"'s and definitions using infix > notation fail to match, for example. > > InfixNotation[ParsedBoxWrapper["\[Element]"], MyElement] > sum[a_ \[Element] list_, expr_] := ... > sum[a_\[Element] {1,2,3},a] > > This fails to match when in .m file, but works fine in .nb file. My > question is -- how should I package "sum" so that it matches correctly > both in packages and in notebooks? > >