wolfram-mathematica – 从规则和/转换有什么好处 到大型应用程序中的OptionsPattern []和OptionValue?

老习惯很难,我意识到我一直在使用opts___Rule模式匹配,并且像这样的/ {opts} /。在我正在开发的非常大的包中的选项[myfunction]。 Sal Manango的“Mathematica Cookbook”提醒我,这样做的后6版方式是选择:OptionsPattern []和OptionValue [thisoption]。该软件包需要版本8,但是我从来没有改变过我多年来编写这种代码的方式。

是否值得重构所有这些从我的pre-version-6的方式做的事情?有表现还是其他好处?

问候

维尔比亚

编辑:摘要

回答这个问题有很多好处,所以感谢你们(当然还有一个)。总而言之,是的,我应该重构使用OptionsPattern和OptionValue。 (注意:OptionsPattern不是我以前的OptionPattern!)有很多原因为什么:

这是一个更快的触摸(@Sasha)
>它更好地处理函数,其中参数必须在HoldForm(@Leonid)中
> OptionsPattern会自动检查您是否将有效的选项传递给该函数(如果传递给另一个函数(@Leonid),则仍然需要FilterRules)
>它更好地处理RuleDelayed(:>)(@rcollyer)
>它处理嵌套的规则列表,而不使用Flatten(@Andrew)
>使用OptionValue / @ list分配多个本地变量,而不是对someoptions /进行多次调用有点简单。 {opts} /。选项[thisfunction](在@rcollyer和我之间的评论中提出)

编辑:7月25日我最初以为是一次使用/。如果您故意从另一个函数中提取默认选项,而不是实际调用的语法,语法可能仍然有意义。事实证明,这是通过使用OptionsPattern []的形式来处理的,其中包含一个头列表,例如:OptionsPattern [{myLineGraph,DateListPlot,myDateTicks,GraphNotesGrid}](参见documentation中的“更多信息”部分) 。我最近刚才这样做。

虽然几个答案强调了旧的和新的使用选择方式的不同方面,但我想再提一些意见。更新的构造OptionValue – OptionsPattern提供比OptionQ更多的安全性,因为OptionValue检查全局选项的列表,以确保传递的选项对该函数已知。较旧的OptionQ似乎更容易理解,因为它仅基于标准模式匹配,并且不与任何全局属性直接相关。您是否希望由这些结构提供的额外安全性取决于您,但我的猜测是,大多数人觉得有用,特别是对于较大的项目。

这些类型检查真正有用的一个原因是通常选项作为参数通过函数以链式方式传递,过滤等,因此没有这种检查,一些模式匹配错误将非常难以捕获,因为它们将会造成他们从其起源地“遥远”的危害。

在核心语言方面,OptionValue – OptionsPattern结构是模式匹配器的补充,也许是其所有功能中最“神奇”的。只要有人愿意将备选方案视为一种特殊的规则条件,那就不是语义上的必要条件。此外,OptionValue将模式匹配连接到Options [symbol] – 一个全局属性。那么,如果一个人坚持语言纯度,那么在opts ___中的规则呢?OptionQ看起来更容易理解 – 除了标准的规则替换语义以外,它不需要任何东西来理解这一点:

f[a_, b_, opts___?OptionQ] := Print[someOption/.Flatten[{opts}]/.Options[f]]

(我提醒说,OptionQ谓词是专门设计用于识别旧版本的Mathematica中的选项),而这一点:

f[a_, b_, opts:OptionsPattern[]] := Print[OptionValue[someOption]]

看起来很神奇当您使用Trace并看到OptionValue的简短形式评估为更长的形式时,它变得更清晰,但它自动确定封闭函数名称的事实仍然非常显着。

OptionsPattern作为模式语言的一部分还有一些后果。一个是@Sasha讨论的速度改进。然而,速度问题往往被过度强调(这不能减损他的意见),我期望这对于具有选项的功能尤其如此,因为这些功能往往是更高层次的功能,平凡的身体,大部分的计算时间将被花费。

另一个相当有趣的区别是当需要将选项传递给一个保存其参数的函数时。请考虑以下示例:

ClearAll[f, ff, fff, a, b, c, d];
Options[f] = Options[ff] = {a -> 0, c -> 0};
SetAttributes[{f, ff}, HoldAll];
f[x_, y_, opts___?OptionQ] :=
   {{"Parameters:", {HoldForm[x], HoldForm[y]}}, {" options: ", {opts}}};
ff[x_, y_, opts : OptionsPattern[]] :=
   {{"Parameters:", {HoldForm[x], HoldForm[y]}}, {" options: ", {opts}}};

还行吧:

In[199]:= f[Print["*"],Print["**"],a->b,c->d]
Out[199]= {{Parameters:,{Print[*],Print[**]}},{ options: ,{a->b,c->d}}}

但是这里我们基于OptionQ的函数泄漏评估作为模式匹配过程的一部分:

In[200]:= f[Print["*"],Print["**"],Print["***"],a->b,c->d]
During evaluation of In[200]:= ***
Out[200]= f[Print[*],Print[**],Print[***],a->b,c->d]

这不是一回事。会发生什么是模式匹配器,建立一个匹配或不匹配的事实,必须评估第三个打印作为OptionQ的评估的一部分,因为OptionQ不包含参数。为了避免评估泄漏,需要使用Function [opt,OptionQ [Unevaluated [opt]],HoldAll]代替OptionQ。使用OptionsPattern,我们没有这个问题,因为匹配的事实可以纯粹在语法上建立:

In[201]:= ff[Print["*"],Print["**"],a->b,c->d]
Out[201]= {{Parameters:,{Print[*],Print[**]}},{ options: ,{a->b,c->d}}}

In[202]:= ff[Print["*"],Print["**"],Print["***"],a->b,c->d]
Out[202]= ff[Print[*],Print[**],Print[***],a->b,c->d]

所以总结一下:我认为选择一种方法是另一种方法,主要是一种味道 – 每种都可以有效地使用,每种都可以被滥用。我更倾向于使用更新的方式,因为它提供了更多的安全性,但是我不排除那里有一些角落的情况,当它会让你感到惊讶 – 而旧的方法在语义上更容易理解。这与C-C比较类似(如果这是适当的):自动化和(可能)安全性与简单性和纯度。我的两美分

http://stackoverflow.com/questions/6617511/what-are-the-benefits-of-switching-from-rule-and-to-optionspattern-and-opti

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:wolfram-mathematica – 从规则和/转换有什么好处 到大型应用程序中的OptionsPattern []和OptionValue?