94 views

Skip to first unread message

Jan 10, 2011, 2:39:00 AM1/10/11

to

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.

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?

Jan 11, 2011, 12:33:25 AM1/11/11

to

This is not really that complicated. From the user's viewpoint, you can

define a package where

you put loadWithNotations function, and just load it before anything

else, perhaps by auto-initialization.

As for the requirement to wrap calls to InfixNotation inside packages like

this,

define a package where

you put loadWithNotations function, and just load it before anything

else, perhaps by auto-initialization.

As for the requirement to wrap calls to InfixNotation inside packages like

this,

BeginPackage["Global`",{"Notation`","NotationTest`"}]

InfixNotation[ParsedBoxWrapper["\[Element]"],myElement];

EndPackage[],

this does not seem to be a big deal either, and can be further automated if

needed. The only other thing

the user has to do is to wrap the calls to Needs into loadWithNotations,

which doesn't look like too much

work for me.

As for whether this is going to work in later versions, I think it should,

because it uses rather fundamental mechanisms which are not very likely to

change (including Notation`'s attachment to MakeBoxes/MakeExpression).The

code for loadWithNotations is not ideal (for instance, the way it deals with

possible Aborts, exceptions, or prior definitions attached to SetDelayed),

but it also can be improved. So, let me put it this way: I'd surely use it

myself for my purposes, but I'd hesitate to package it for other people's

use, mainly because of manipulations with SetDelayed.

Regarding other ways of doing it: there are several stages of code

processing, each of which could be used to try getting what you want. If you

only wanted to use this notation when defining a function but not when it is

used, you could as well register your functions with some other function,

and then post-process their DownValues after they were given, replacing

\[Element] by something else. But since you also want to use this syntax

when you call, I can only think of 2 options: parse-time redefinitions (this

is what Notation` does, and I doubt you can find much better solution, at

least conceptually, given that you will also have to use it from the

FrontEnd), or run-time redefinitions.

For the latter, I'd consider UpValues. They could solve a subset of your use

cases, like this for instance:

In[2]:= sum /: sum[a_ \[Element] b_List, expr_] := Sum[expr, {a, b}]

In[3]:= sum[i \[Element] {1, 2, 3}, i]

Out[3]= 6

Another advantage of them is that they are attached to your symbols (sum

etc), not to \[Element], and therefore, unlikely to break other functions

using \[Element]. Here you also don't have to worry about dispatching

myElement to either MemberQ or Element, as you would in the Notation`-based

approach .They (UpValues) are more limited, however, due to the depth-1 rule

(you can not attach them to a symbol which is deeper in an expression).

Regards,

Leonid

On Mon, Jan 10, 2011 at 11:01 PM, Yaroslav Bulatov <yaros...@gmail.com>wrote:

> Wow, that looks complicated....is it likely to work in future versions?

>

> At the core, I basically want

> 1. Have \[Element] work like MemberQ for lists.

> 2. Define functions that use f[a_\[Element] b_] syntax

> 3. Be able to import this functionality without breaking behavior or

> functions like Reduce that use "Element" built-in

>

> Is there perhaps a way to do this without Notation package?

>

>

>

> On Mon, Jan 10, 2011 at 8:54 AM, Leonid Shifrin <lsh...@gmail.com> wrote:

> > 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 <yaros...@gmail.com

Jan 11, 2011, 12:32:08 AM1/11/11

to

Jan 11, 2011, 12:32:42 AM1/11/11

to

Wow, that looks complicated....is it likely to work in future versions?

At the core, I basically want

1. Have \[Element] work like MemberQ for lists.

2. Define functions that use f[a_\[Element] b_] syntax

3. Be able to import this functionality without breaking behavior or

functions like Reduce that use "Element" built-in

Is there perhaps a way to do this without Notation package?

On Mon, Jan 10, 2011 at 8:54 AM, Leonid Shifrin <lsh...@gmail.com> wrote:

> 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==

>> sum[a_ \[Element] list_, expr_] :== ...

Jan 11, 2011, 7:21:48 PM1/11/11

to

As an intermediate, try using an initialization cell for the notations

in a notebook, instead of building a package.

in a notebook, instead of building a package.

Chris

Yaroslav Bulatov a =E9crit :

Reply all

Reply to author

Forward

0 new messages

Search

Clear search

Close search

Google apps

Main menu