pha*_*234 3 wolfram-mathematica
我想重载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
Run Code Online (Sandbox Code Playgroud)
我不认为你想要的是什么UpValues(唉),因为符号(标签)必须不比第一级深,才能使定义工作.此外,您想要的语义在Mathematica中有点不寻常,因为大多数Mathematica表达式是不可变的(不是L值),并且它们的部分不能被赋值.我相信这段代码会做你想做的事情:
Unprotect[Set];
Set[var_Symbol, rhs_] /;
MatchQ[Hold[var] /. OwnValues[var], Hold[_struct]] := Set[var[[1]], rhs];
Protect[Set];
Run Code Online (Sandbox Code Playgroud)
例如:
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!"]
Run Code Online (Sandbox Code Playgroud)
但通常情况下,不建议添加DownValues此类重要命令,Set因为这可能会以微妙的方式破坏系统.
编辑
扩展了尝试失败的原因:Mathematica使用参数保持机制(Hold*- 属性,这里描述)实现流控制和赋值运算符.该机制允许它特别模仿分配所需的传递引用语义.但是,当你分配时var1,Set不知道var1已经存储了什么,因为它只有符号var1,而不是它的值.模式_struct不匹配,因为即使变量已经存储了一些struct,也Set只有变量名.为了使匹配成功,内部变量Set必须评估其值.但是,该值是不可变的,您无法分配给它.我建议的代码测试变量是否具有表单的赋值struct[something],如果是,则修改第一部分(该Part命令是一个例外,它可以修改L值表达式的部分,前提是这些部分已经存在) .
您可以Hold*在许多地方阅读有关- 属性和相关问题的主题的更多信息,例如此处和此处