Wolfram mathematica Mathematica:OptionValue是如何实现的?

Wolfram mathematica Mathematica:OptionValue是如何实现的?,wolfram-mathematica,Wolfram Mathematica,内置的实现包含了一些魔力,因此 OptionValue[name]等同于 OptionValue[f,name],其中f是 左侧的头部 转换规则,其中 出现选项值[名称] 是否有人知道如何实现类似的选项,即实现一个autoOptions[],该选项将解析为出现autoOptions[]的转换规则左侧的符号定义的选项? 为了清楚起见,我正在寻找的是一种 Options[foo]={bar->1}; foo[OptionsPattern[]]:=autoOptions[] foo[] 输出{

内置的实现包含了一些魔力,因此

OptionValue[name]
等同于
OptionValue[f,name]
,其中
f
是 左侧的头部 转换规则,其中 出现选项值[名称]

是否有人知道如何实现类似的
选项
,即实现一个
autoOptions[]
,该选项将解析为出现
autoOptions[]
的转换规则左侧的符号定义的选项? 为了清楚起见,我正在寻找的是一种

Options[foo]={bar->1};
foo[OptionsPattern[]]:=autoOptions[]
foo[]
输出
{bar->1}


最终的目标是执行类似于中请求的操作,而不必更改定义的RHS以外的任何内容。

这里是一个简单、非常示意的版本:

Module[{tried},
  Unprotect[SetDelayed];    
  SetDelayed[f_[args___, optpt : OptionsPattern[]], rhs_] /; 
    !FreeQ[Unevaluated[rhs], autoOptions[]] :=
     Block[{tried = True},
       f[args, optpt] :=  
         Block[{autoOptions}, autoOptions[] = Options[f]; rhs]] /; ! TrueQ[tried];
  Protect[SetDelayed];]
您的用法:

In[8]:= Options[foo] = {bar -> 1};
foo[OptionsPattern[]] := autoOptions[]
foo[]

Out[10]= {bar -> 1}

请注意,当显式选项也被传递时,这将不起作用-考虑它们需要更多的工作,而且这通常不是一个好的实践,因为我重载了
SetDelayed
-但是您要求它,并且您得到了它

请给出一个伪代码示例,说明您的期望。也许我遗漏了什么,但为什么您不能在RHS上使用
Options[symbol]
,我可以而且我确实做到了——这更像是一件好奇的事情:)另外,我还看到了一些可怕的错误,它们来自于复制代码和忘记更改这种类型的结构中的符号。谢谢Leonid。摆弄SetDelayed也是我能想到的唯一方法(尽管您的实现比我想象的要好得多),我同意这不符合良好实践的要求。尽管如此,这种模式是足够具体的,我可能会考虑……“JaNUS I实际上使用了类似的模式与代码> StEdTrime几次,而我个人并不是狂热地反对这一点。在我看来,真正重要的是,这些东西完全局限于您的用途,并且是孤立的。如果它是您自己的代码,则您始终可以自由定义自定义赋值运算符,而无需更改
SetDelayed
。当您想要对某些其他代码(例如,正在加载的包)中的定义进行一些运行时修改或检查时,通常需要使用后者,而这些代码您没有直接访问权限,或者您不想直接访问或修改。@Leonid。是的,我同意。也许中缀符号中的自定义
SetDelayed
,比如
~def~
可以在不太难看的情况下工作。这甚至可以通过减少对
尝试过的
技巧的需要来进一步简化您的实现。尽管如此,我还是忍不住想知道
OptionValue
是否真的由
SetDelayed
@Janus处理
OptionsPattern-OptionValue
中包含了一些魔力,这是毫无疑问的。虽然这些很方便,但我对它们的感觉却很复杂。较旧的
OptionQ
谓词仅使用标准语言构造(规则),并且易于理解-知道参数是如何传递的以及模式是如何工作的,就足以知道选项是如何工作的。而
选项值
选项模式
则不然。我希望它们更透明,在顶级mma中实现。@Janus但由于修改
SetDelayed
似乎是唯一明确的方法,我理解在系统级将其连接起来更安全,因为
SetDelayed
太重要和根本,不能显式处理它。这是否是通过实际修改
SetDelayed
的内置规则(code)实现的,这是一个很好的问题,我也想知道答案。