有没有办法强迫Mathematica独立于未订阅的对应方处理下标变量?进一步来说。说,我有以下定义:
Subscript[b, 1] = {{1, 2}}
Subscript[b, 2] = {{3, 4}}
b = Join[Subscript[b, 1], Subscript[b, 2]]
现在我使用
Subscript[b, 1]
Mathematica将用
代替它Subscript[{{1, 2}, {3, 4}},1]
当我希望这些是三个独立的值时,更改b不会影响下标[b,..]。有可能吗?
答案 0 :(得分:13)
在对前一个SO问题的回答中,Mathematica Notation and syntax mods,telefunkenvf14提到他是
希望使用Notations强制MMA 将下标变量视为符号
这就是这个问题的基本内容。
WReach指出Notation package只需使用Symbolize
即可完成此操作
Needs["Notation`"];
Symbolize[ParsedBoxWrapper[SubscriptBox["_", "_"]]]
在(如Daniel的回答中)不要过于担心上面的Box
结构,因为您可以使用Notation
调色板更简单地输入这些内容。
检查一切是否正常工作:
In[3]:= Subscript[a, b]//Head
a = 1
Subscript[a, b]
Out[3]= Symbol
Out[4]= 1
Out[5]= Subscript[a, b]
和
In[6]:= Subscript[b, 1] = {{1, 2}}
Subscript[b, 2] = {{3, 4}}
b = Join[Subscript[b, 1], Subscript[b, 2]]
Out[6]= {{1, 2}}
Out[7]= {{3, 4}}
Out[8]= {{1, 2}, {3, 4}}
注意:以上所有代码均为copied as Input Text,因此排版SubscriptBox
已转换为输入形式Subscript
。但是,Symbolize
在框级别工作,因此需要将测试转换回其二维形式。为此,请使用Cell
菜单或convert it to standard form Ctrl-Shift-N
选择代码(或单元格)和shortcut。具有上述所有代码的笔记本应该是这样的
答案 1 :(得分:2)
如果您不想使用Notation
包(请参阅Daniel's和my答案),但想要复制Symbolize
的行为,那么它会获得有点棘手。
在我阅读SO answer之后,我开始这么做了,但遇到了麻烦而放弃了。我将这里的代码作为社区维基,以便其他人可以尝试完成它!
首先,您要拦截输入的下标框结构,并将其解释为“唯一”符号。以下代码
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
转换为实际框才能使代码生效。通过转换为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. >>
答案 2 :(得分:2)
以下是我过去用来执行此操作的一些代码。它也适合你:
SubscriptToProxySymbol[_] = Null;
MakeExpression[SubscriptBox[a_, b_], StandardForm] :=
Module[{proxy, boxes = SubscriptBox[a, b]},
proxy = SubscriptToProxySymbol[boxes];
If[proxy === Null, proxy = ToString[Unique[ProxySymbol]];
SubscriptToProxySymbol[boxes] = proxy;
With[{n = Symbol[proxy]}, MakeBoxes[n, StandardForm] := boxes];];
MakeExpression[RowBox[{proxy}], StandardForm]]
有了这个,像
这样的定义f[Subscript[a, b] : _] := Sin[Subscript[a, b]]
内部存储如下:
In[11]:= InputForm@DownValues[f]
Out[11]//InputForm=
{HoldPattern[f[ProxySymbol$99_]] :> Sin[ProxySymbol$99]}
但它们显示为下标。
从快速看,我认为这可能是西蒙的目标。
如果您的应用程序允许,您可能希望考虑采用类似Mathematica的命名约定,例如FullyDescriptiveCamelCase变量名称而不是下标变量。它最终将使您的代码更具可移植性,并最终成为第二种性质。
答案 3 :(得分:1)
符号为b
,而非Subscript[b, _]
。
定义时:
Subscript[b, 1] = {{1, 2}}
就像定义任何函数f的下限值。喜欢这样做:
f[b, 2] = {{1, 2}}
所以,你正在做的是
f[b, 1] = {{1, 2}}
f[b, 2] = {{3, 4}}
b = Join[f[b, 1], f[b, 2]]
当然,这会给符号b赋值。
现在
f[b, 1]
->f[{{1, 2}, {3, 4}}, 1]
正如所料。
所以,我想简短的回答是否定的。至少不是一种直截了当的方式。
修改强>
虽然上述情况属实(我相信),但我并不知道Notation包有办法绕过默认行为。其他答案包含详细信息。
答案 4 :(得分:1)
可以使用同名包中的Notation。
不要介意下面的代码,你不要弄清楚RowBox的结构。只需使用调色板模板并在左侧键入Subscript [b,j_],然后在右侧键入bb [j_]。所以“实际”变量现在是bb [1]等,你可以安全地分配给b。Needs["Notation`"]
Notation[ParsedBoxWrapper[
RowBox[{"Subscript", "[",
RowBox[{"b", ",", "j_"}], "]"}]] \[DoubleLongRightArrow]
ParsedBoxWrapper[
RowBox[{"bb", "[", "j_", "]"}]]]
Subscript[b, 1] = {{1, 2}}
Subscript[b, 2] = {{3, 4}}
b = Join[Subscript[b, 1], Subscript[b, 2]]
Out [3] = {{1,2}}
Out [4] = {{3,4}}
Out [5] = {{1,2},{3,4}}
Subscript[b, 1]
Out [6] = {{1,2}}
你可能会得到更准确的回复,这是我第一次使用Notation软件包。
Daniel Lichtblau Wolfram Research
答案 5 :(得分:0)
我通过将各种回复粘贴到Mathematica笔记本中来详细研究下标变量的线程(并使用版本7和8进行了尝试)。但是,我发现在某些情况下,作为Subscript[a,b]
的下标变量的显式表示并未给出这些答案中包含的正确答案。但是,当我明确使用下标(a_b)的2d符号时,答案是预期的。可能是因为将下标符号粘贴到电子邮件中时,它们被表示为
Subscript[a,b]
。 (当然,我应该补充说,对于每个人的贡献,我开始使用Mathematica新鲜 - 使用Quit[ ]
后)。