我想重载 Mathematica 的 Set 函数 (=),这对我来说太棘手了(请参阅下面的代码示例)。我成功重载了其他函数(例如代码示例中的 Reverse)。有什么建议么?
In[17]:= ClearAll[struct];
In[18]:= var1=struct[{1,2}]
Out[18]= struct[{1,2}]
In[19]:= Reverse@var1
Out[19]= struct[{1,2}]
In[20]:= Head[var1]
Out[20]= struct
In[21]:= struct/:Reverse[stuff_struct]:=struct[Reverse@stuff[[1]]]
In[22]:= Reverse@var1
Out[22]= struct[{2,1}]
In[23]:= struct/:Set[stuff_struct,rhs_]:=Set[struct[[1]],rhs]
In[24]:= var1="Success!"
Out[24]= Success!
In[25]:= var1
Out[25]= Success!
In[26]:= Head[var1]
Out[26]= String
In[27]:= ??struct
Global`struct
Reverse[stuff_struct]^:=struct[Reverse[stuff[[1]]]]
(stuff_struct=rhs_)^:=struct[[1]]=rhs
我不认为你想要的可以用UpValues
(唉),因为符号(标签)必须不超过一级才能定义工作。此外,您想要的语义在 Mathematica 中有些不寻常,因为大多数 Mathematica 表达式都是不可变的(不是 L 值),并且它们的部分不能被赋值。我相信这段代码会做与你想要的类似的事情:
Unprotect[Set];
Set[var_Symbol, rhs_] /;
MatchQ[Hold[var] /. OwnValues[var], Hold[_struct]] := Set[var[[1]], rhs];
Protect[Set];
例如:
In[33]:= var1 = struct[{1, 2}]
Out[33]= struct[{1, 2}]
In[34]:= var1 = "Success!"
Out[34]= "Success!"
In[35]:= var1
Out[35]= struct["Success!"]
但一般情况下,添加DownValues
诸如此类的重要命令Set
不建议这样做,因为这可能会以微妙的方式损坏系统。
EDIT
稍微扩展一下您的尝试失败的原因:Mathematica 使用参数保持机制实现流程控制和赋值运算符(Hold*
- 属性,描述here)。特别是,这种机制允许它模仿赋值所需的按引用传递语义。但是,当你分配给var1
, Set
不知道里面存储了什么var1
已经,因为它只有符号var1
,而不是它的值。图案_struct
不匹配,因为即使变量已经存储了一些struct
, Set
只有变量名。为了匹配成功,里面的变量Set
必须评估其价值。但是,该值是不可变的,您不能分配给它。我建议的代码测试变量是否具有以下形式的指定值struct[something]
,如果是,则修改第一部分(Part
命令是一个例外,它可以修改 L 值表达式的部分(前提是这些部分已经存在)。
您可以阅读有关以下主题的更多信息Hold*
- 例如很多地方的属性和相关问题here and here
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)