Если вы не хотите использовать пакет Notation
(см. ответы Даниеля и мои ), но хотите скопировать поведение Symbolize
, тогда он получаетнемного сложно.
Я попытался сделать это после того, как прочитал ТАК * ответ , но столкнулся с проблемами и сдался.Я поставлю код здесь, как вики сообщества, чтобы другие люди могли попытаться закончить его!
Сначала вы хотите перехватить структуру введенного поля индекса и сделать его интерпретируемым как «уникальный» символ.Следующий код
MakeExpression[SubscriptBox[x_String, i_String], form_] :=
With[{name = StringJoin[{"$sUbsCript$", x, "$SPLIT$", i}]},
Hold[Symbol[name]]]
делает введенный x_i
символом "$sUbsCript$x$SPLIT$i"
.Не гарантированное уникальное имя символа ... но это было бы довольно необычное!Примечания:
1) что этот код не будет подбирать индексы, написанные в FullForm
.
2) это определение срабатывает только в том случае, если обе части индекса «простые» - без пробелов, скобок, операторов и т. Д....
Далее, поскольку это имя символа очень уродливо, вот что-то необязательное, чтобы сделать его лучше, когда его просят (это, вероятно, следует изменить)
Protect[$inSymbolName];
Unprotect[SymbolName];
SymbolName[symb_Symbol] :=
Block[{$inSymbolName = True, result, s},
result = If[StringMatchQ[s = SymbolName[symb], "$sUbsCript$" ~~ __],
StringJoin@StringSplit[StringDrop[s, 11], "$SPLIT$"],
s]] /; ! TrueQ[$inSymbolName]
Protect[SymbolName];
Наконец, мыхочу, чтобы этот индекс был хорошо распечатан.Обычно мы делаем это, используя определение MakeBoxes
- но мы не можем в этом случае, потому что Symbol
имеет атрибут Locked
: (
Вместо этого мы взломаем $PrePrint
, чтобы найтиэти безумно названные символы и записывают их обратно как подписки:
$PrePrint = (# /. s_Symbol :>
Block[{$inSymbolName = True},
If[StringMatchQ[SymbolName[s], "$sUbsCript$" ~~ __],
Subscript@@StringSplit[StringDrop[SymbolName[s], 11], "$SPLIT$"], s]]
)&;
Наконец, все, где все это рушится, - это если вы пытаетесь назначить что-то подписанному символу. Я еще не пытался обойти это!
Некоторые тесты - обратите внимание, что для работы кода вам нужно будет преобразовать Subscript
s в фактические поля. Сделайте это путем преобразования в StandardForm: Ctrl-Shift-N.
symbs = {x, yy, Subscript[a, 3], Subscript[long, name]};
In[10]:= Head/@symbs
Out[10]= {Symbol, Symbol, Symbol, Symbol}
In[11]:= SymbolName/@symbs
Out[11]= {x, yy, a3, longname}
In[12]:= Block[{$inSymbolName=True},SymbolName/@symbs]
Out[12]= {x, yy, $sUbsCript$a$SPLIT$3, $sUbsCript$long$SPLIT$name}
In[13]:= f[x_Symbol] := Characters[SymbolName[x]]
In[14]:= {f["acb"], f[abc], f[Subscript[xx, 2]]}
Out[14]= {f["acb"], {"a", "b", "c"}, {"x", "x", "2"}}
Он не работает с Set
или SetDelayed
, если они генерируют OwnValues
, и не работает с Information
In[15]:= Subscript[x, y] = 5
??Subscript[x, y]
During evaluation of In[4]:= Set::write: Tag Symbol in Symbol[$sUbsCript$x$SPLIT$y] is Protected. >>
Out[15]= 5
During evaluation of In[4]:= Information::nomatch: No symbol matching Symbol["$sUbsCript$x$SPLIT$y"] found. >>
Он работает с определениями, которые производят DownValues
In[17]:= Subscript[x, z][z_]:=z^2
In[18]:= Subscript[x, z][2]
Out[18]= 4
In[19]:= ?Subscript[x, z]
Information::nomatch: No symbol matching Symbol["$sUbsCript$x$SPLIT$z"] found. >>