MathGroup Archive 1999

[Date Index] [Thread Index] [Author Index]

Search the Archive

Tricky Symbolizations with the Notation Package (Was Subscripts, Doh!!!)

>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,
>      Symbolize[ Subscript[x_, _Integer]
>might do it more generally.

O.k. here are the functions to do this.

<< Utilities`Notation`

unparsedNumericQ  @  boxes___ :=
   ReleaseHold @
     Hold[NumericQ] @
       Hold[Unevaluated] @ ToExpression[boxes, StandardForm, Hold]

       x_Symbol] := \((Symbolize[
           SubscriptBox[ToString\ @\ x,
             TagBox[RowBox[List["\<i_\>", "\<?\>", "\<unparsedNumericQ\>"]],
       x\_\(i_?IntegerQ\) := ToExpression\ @\ MakeBoxes[\ x\_i])\)\)


\!\(\[Mu]\_1 // Head\)


\!\(\[Mu]\_t // Head\)


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.

\!\(\(symbolizeAllSymbolsBySubscriptedInteger[] := \((Symbolize[
               TagBox[RowBox\ @\ {"\<_\>", "\<?\>", "\<unparsedSymbolQ\>"},
               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;\)\)



 From In[12]:=

\!\(a\_4 = 5\)



 From In[14]:=

\!\(Table[y\_j, {j, 1, 5}]\)

\!\({y\_1, y\_2, y\_3, y\_4, y\_5}\)

Head /@ %

{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 


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 

Hopefully this clarifies things a bit. The documentation goes into 
these topics in more detail. See the section on complex patterns.

Cheers,  Jason

  • Prev by Date: Re: Solve and Trig functions
  • Next by Date: Re: Pattern example
  • Previous by thread: Re: Simple edit ...
  • Next by thread: Control Function With NDsolve