Tricky Symbolizations with the Notation Package (Was Subscripts, Doh!!!)
- To: mathgroup at smc.vnet.net
- Subject: [mg19308] Tricky Symbolizations with the Notation Package (Was Subscripts, Doh!!!)
- From: Jason Harris <j.harris at phys.canterbury.ac.nz>
- Date: Sat, 14 Aug 1999 23:42:44 -0400
- Sender: owner-wri-mathgroup at wolfram.com
>Jason Harris wrote: > >>> >>>(iii) Ideally, one would be able to >>> >>> Symbolize[ Subscript[x, _Integer] ] >>> >>> and then be able to work with >>> >>> Table[x_i, {i, 1, 4}] >>> >>> where each of x_1, x_2, x_3 etc are treated as symbols. <Code that does the above> >Neat. Can you make this work for Greek symbols too, >say mu_1, mu_2 etc, rather than just m_1, m_2, m_3 ? > >[ Actually, I had better not advocate such things, or > a lot of my code will cease to work ! heh heh ] Yep. Really easily. >>Of course, this is all possible programmatically so one can >>easily define a function to automate this. > > >I think it would be valuable if you could add such features to >the next version of Symbolize, in an easily accessible manner. >For instance: > > Symbolize[ Subscript[x, _Integer] > >switches the above on, for just symbol x, >whilst: > > Symbolize[ Subscript[x_, _Integer] > >might do it more generally. O.k. here are the functions to do this. In[1]:= << Utilities`Notation` In[2]:= unparsedNumericQ @ boxes___ := ReleaseHold @ Hold[NumericQ] @ Hold[Unevaluated] @ ToExpression[boxes, StandardForm, Hold] In[3]:= \!\(symbolizeBySubscriptedInteger[ x_Symbol] := \((Symbolize[ NotationBoxTag[ SubscriptBox[ToString\ @\ x, TagBox[RowBox[List["\<i_\>", "\<?\>", "\<unparsedNumericQ\>"]], NotationPatternTag]]]]; x\_\(i_?IntegerQ\) := ToExpression\ @\ MakeBoxes[\ x\_i])\)\) In[4]:= symbolizeBySubscriptedInteger[\[Mu]] In[5]:= \!\(\[Mu]\_1 // Head\) Out[5]= Symbol In[6]:= \!\(\[Mu]\_t // Head\) Out[6]= Subscript Although easy, instead of parsing 'anything sub integer' to a symbol, it would probably be better to parse 'symbol sub integer' to a symbol. Thus \!\(TraditionalForm\`\((1 + a)\)\_3\) would not be parsed to a symbol but \!\(TraditionalForm\`\[Mu]\_3\) would. This is easily achieved by the following. In[7]:= \!\(\(symbolizeAllSymbolsBySubscriptedInteger[] := \((Symbolize[ NotationBoxTag[ SubscriptBox[ TagBox[RowBox\ @\ {"\<_\>", "\<?\>", "\<unparsedSymbolQ\>"}, NotationPatternTag], TagBox[RowBox\ @\ {"\<i_\>", "\<?\>", "\<unparsedNumericQ\>"}, NotationPatternTag]]]]; \((symb_?SymbolQ)\)\_\(i_?IntegerQ\) := ToExpression\ @\ MakeBoxes[\ symb\_i])\);\)\[IndentingNewLine] \(unparsedSymbolQ\ \ @\ \ boxes___\ := \ \[IndentingNewLine]ReleaseHold\ @\ \ \(Hold[SymbolQ]\ @\ \(Hold[Unevaluated]\ @\ ToExpression[boxes, StandardForm, Hold]\)\);\)\[IndentingNewLine] \(SymbolQ\ @\ _Symbol = True;\)\[IndentingNewLine] \(SymbolQ\ @\ ___\ = \ False;\)\) In[11]:= symbolizeAllSymbolsBySubscriptedInteger[] In[12]:= \!\(\(?a\_4\)\) From In[12]:= "Global`a\[UnderBracket]Subscript\[UnderBracket]4" In[13]:= \!\(a\_4 = 5\) Out[13]= 5 In[14]:= \!\(\(?g\_5\)\) From In[14]:= "Global`g\[UnderBracket]Subscript\[UnderBracket]5" In[15]:= \!\(Table[y\_j, {j, 1, 5}]\) Out[15]= \!\({y\_1, y\_2, y\_3, y\_4, y\_5}\) In[16]:= Head /@ % Out[16]= {Symbol, Symbol, Symbol, Symbol, Symbol} Setting up the really simple form like you ask is problematic for a couple of reasons. The following is an extremely brief and fairly technical explanation of why this is very hard, and in all likelihood won't be done. It is easy enough to do what you originally asked. However, generalizations of it would be very difficult. It would be exceedingly tricky to try to second guess what the user wants. The space here does not really allow me to go into the intricacies of why the design was chosen as it was. (Read the documentation for more details). The real problem is the distinction between parsing and evaluation. When one creates a pattern like _Integer, one is normally assuming evaluation... Whereas with parsing there is very rarely any evaluation. (This is fundamental to the parsing process in Mathematica.) Thus we run into problems. For instance Hold[2+2] will not match Hold[_Integer]. So assume we are trying to parse patterns of the form 'm sub _Integer'. If we then parse "m" sub "2+2" the system will think ohh <held> 2+2 is not an integer, so I'll parse this to Subscript[m,Plus[2,2]] which promptly evaluates to Subscript[m,4]. which did intuitively match the original m sub _Integer. Thus in the end some trickiness is required. (In this case we have to set up an evaluation rule for Subscript[m,_Integer]. ) This is a very specific case of the general problem of evaluation in parsing. We cannot have both literal and semantic things at the same time. (The terms I use here are "shades of grey" and should serve only as an approximation to the truth....) The same is true in Mathematica since it has the functions Verbatim and HoldPattern. That is, we can either match literal structures, or we can have our patterns evaluate, but we can't have both at the same time. The analog is true in parsing. We cannot have the same "structure" being a notation and a pattern at the same time. In the Notation package, it would be possible to have all "patterns" interpreted as patterns instead of literal notations. However, sometimes we don't want a pattern to be taken as a pattern, for example, if we are defining notations involving patterns. For instance, we can fairly easily create a pattern notation that will match the negative of a testing function. i.e. <simple pattern> ? sup ! <test func>. This would match things for which <test func> was not true. (Again see the documentation on how to do this.) E.g. \!\(f[expr_\(?\^! \)IntgerQ] := blah\) So at times we need to have patterns being interpreted as notations. Thus we have a choice. By default, in the Notation package, are "patterns" really patterns or notations? The choice is made much easier since, it is a very difficult task to determine the extent of a pattern in an unparsed box structure. (Conceivably I could have given this a go... but it would not be trivial. Moreover there are other reasons why we don't want this.) Thus I chose to take everything as a literally given unless otherwise stated. The only exception to this was for _, __, and ___. Even this leads to problems... For, instance it is not easily possible to create a notation for complex conjugation... since the overscripted underscore is treated as a simple pattern in the following notation-like statement. \!\(Notation[z_\&_\[DoubleLongLeftRightArrow]Conjugate[z_]]\) I could as the designer try and second guess what particular trickiness is required by the user. However, it is better to set up a fairly general and robust set of primitives whereby the user can create with (not too much trouble) what he /she desires. As we see from the forgoing it was fairly easy to set up the symbolizations required. Hopefully this clarifies things a bit. The documentation goes into these topics in more detail. See the section on complex patterns. Cheers, Jason