Evaluate[Map[p, Range[0, 3]]] = {a, b, c, d}
补充一下关于自定义数据类型的问题。严格来讲mma是没有这个功能的,但是可以做到类似的效果,比如这样
In[5]:= myList[a_List] := myListObj[a];
x_myListObj[i_] := x[[1, i + 1]];
a = myList[{1, 2, 3, 4}];
a[0]
Out[8]= 1
这几行就完成了一个基本的自定义,定义了一个叫做myList的类,通过myListObj来实现自定义数组下标。
下标的读取解决了,接下来是下标的赋值,也就是说当运行a[0]=3时需要改变a,这其实是最困难的一步。但好在stackexchange上已经有了相关讨论,直接照搬其解决方案并作小幅修改即可
(附原帖链接:http://mathematica.stackexchange.com/questions/1162/alternative-to-overloading-set)
ClearAll[withCustomSetLex];
SetAttributes[withCustomSetLex, HoldAll];
withCustomSetLex[code_] :=
Unevaluated[code] /.
HoldPattern[Set[a_Symbol[i_], value_]] /; Head[a] == myListObj :>
Set[a, ReplacePart[a, {1, i + 1} -> value]]
这样在withCustomSetLex中进行的赋值就可以达到目的了
接下来还希望myList支持尽可能多的运算,如加减乘除、点乘等。最开始我打算用/:把计算中需要用到的运算全部重载,后来想到其实可以直接在计算中把myListObj化为List处理,因为myListObj和List只有在[]运算符和Set时才有区别,其他时候完全一样,因此只需在withCustomSetLex最后加上一句myListObj->Identity即可。
为了方便计算,将withCustomSetLex放入$Pre,这样就可以正常的操作myListObj了。
附完整代码与例子如下:
(*定义部分*)
ClearAll[myList, myListObj];
myList[a_List] := myListObj[a];
x_myListObj[i_Integer] := x[[1, i + 1]];
ClearAll[withCustomSetLex];
SetAttributes[withCustomSetLex, HoldAll];
withCustomSetLex[code_] :=
Unevaluated[code] /.
HoldPattern[Set[a_Symbol[i_], value_]] /; Head[a] == myListObj :>
(Set[a, ReplacePart[a, {1, i + 1} -> value]]; value) /.
myListObj -> Identity;
$Pre = withCustomSetLex;
然后进行一些测试
可见大部分运算都可以进行
但也有一些会失败的例子,如Length、Total、{3,4,5,6}/b等等,用的时候还是需要多加小心