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