Wolfram mathematica 从规则和/转换的好处是什么。在大型应用程序中选择OptionPattern[]和OptionValue?
旧习惯很难改掉,我意识到我一直在使用Wolfram mathematica 从规则和/转换的好处是什么。在大型应用程序中选择OptionPattern[]和OptionValue?,wolfram-mathematica,mathematica-8,Wolfram Mathematica,Mathematica 8,旧习惯很难改掉,我意识到我一直在使用opts\uuuu规则模式匹配和类似thispoption/的结构。{opts}/。选项[myfunction]在我目前正在开发的非常大的软件包中。Sal Manango的“Mathematica Cookbook”提醒我,第6版后的实现方法是opts:options模式[]和option值[thispoption]。无论如何,这个软件包需要版本8,但多年来我从未改变过编写这种代码的方式 是否值得从我6版之前的做法中重构所有这些?是否有绩效或其他好处 问候 韦
opts\uuuu规则
模式匹配和类似thispoption/的结构。{opts}/。选项[myfunction]
在我目前正在开发的非常大的软件包中。Sal Manango的“Mathematica Cookbook”提醒我,第6版后的实现方法是opts:options模式[]
和option值[thispoption]
。无论如何,这个软件包需要版本8,但多年来我从未改变过编写这种代码的方式
是否值得从我6版之前的做法中重构所有这些?是否有绩效或其他好处
问候
韦比娅
编辑:摘要
在回答这个问题时提出了很多好的观点,所以谢谢大家(当然还有一点)。总之,是的,我应该重构以使用OptionsPattern
和OptionValue
。(注意:OptionsPattern
不是我以前使用的OptionsPattern
),原因有很多:
HoldForm
(@Leonid)中的函数options模式
会自动检查您是否正在向该函数传递有效的选项(FilterRules
如果您要传递到另一个函数(@Leonid))则仍然需要RuleDelayed
(:>
)的能力要好得多(@rcollyer)flant
(@Andrew)OptionValue/@list
分配多个局部变量比多次调用someoptions/{opts}/.Options[thisfunction]
要容易一些(在@rcollyer和我之间的评论中出现)编辑:7月25日我最初认为使用
/。
语法的一次可能仍然有意义,那就是如果您有意从另一个函数中提取默认选项,而不是实际调用的选项。结果证明,这是通过使用OptionsPattern[]的形式来处理的
中有一个标题列表,例如:选项模式[{myLineGraph,DateListPlot,myDateTicks,GraphNotesGrid}]
(请参阅中的“更多信息”部分)。我最近才解决了这个问题。依赖模式匹配器似乎比使用patternetest
产生更快的执行速度,因为后者需要调用求值器。无论如何,我的计时表明可以实现一些加速,但我认为它们并没有那么关键,不会促使重新分解
In[7]:= f[x__, opts : OptionsPattern[NIntegrate]] := {x,
OptionValue[WorkingPrecision]}
In[8]:= f2[x__, opts___?OptionQ] := {x,
WorkingPrecision /. {opts} /. Options[NIntegrate]}
In[9]:= AbsoluteTiming[Do[f[1, 2, PrecisionGoal -> 17], {10^6}];]
Out[9]= {5.0885088, Null}
In[10]:= AbsoluteTiming[Do[f2[1, 2, PrecisionGoal -> 17], {10^6}];]
Out[10]= {8.0908090, Null}
In[11]:= f[1, 2, PrecisionGoal -> 17]
Out[11]= {1, 2, MachinePrecision}
In[12]:= f2[1, 2, PrecisionGoal -> 17]
Out[12]= {1, 2, MachinePrecision}
一个鲜为人知(但经常有用)的事实是,允许选项出现在嵌套列表中:
In[1]:= MatchQ[{{a -> b}, c -> d}, OptionsPattern[]]
Out[1]= True
选项处理功能,如了解以下内容:
In[2]:= FilterRules[{{PlotRange -> 3}, PlotStyle -> Blue,
MaxIterations -> 5}, Options[Plot]]
Out[2]= {PlotRange -> 3, PlotStyle -> RGBColor[0, 0, 1]}
考虑到:
In[3]:= OptionValue[{{a -> b}, c -> d}, a]
Out[3]= b
但当然没有考虑到这一点:
In[4]:= a /. {{a -> b}, c -> d}
During evaluation of In[4]:= ReplaceAll::rmix: Elements of {{a->b},c->d} are a mixture of lists and nonlists. >>
Out[4]= a /. {{a -> b}, c -> d}
因此,如果使用,可能还应该使用OptionValue来确保可以使用用户传入的选项集
另一方面,如果使用ReplaceAll(/),出于同样的原因,您应该坚持使用opts\uuuuu规则
请注意,选择规则
在某些情况下也有点过于宽容:
无效选项:
In[5]:= MatchQ[Unevaluated[Rule[a]], OptionsPattern[]]
Out[5]= False
但是\u规则允许它通过:
In[6]:= MatchQ[Unevaluated[Rule[a]], ___Rule]
Out[6]= True
更新:正如rcollyer所指出的,\uuuu规则
的另一个更严重的问题是它遗漏了指定的选项。您可以解决它(请参阅rcollyer的答案),但这是使用OptionValue的另一个很好的理由。您的代码本身有一个微妙但可修复的缺陷。模式opts\uuuuu规则
将与表单a:>b
的选项不匹配,因此如果您需要使用它,您必须更新代码。立即解决的方法是将opts\uu规则
替换为opts:(uuuuu Rule | uuuuuuruledelayed)
比OptionsPattern[]
需要更多的输入。但是,对于我们这些懒惰的人来说,OptionValue[…]
比ReplaceAll
的缩写形式需要更多的输入。不过,我认为它有助于更清晰地阅读代码
我发现选项pattern[]
和OptionValue
更容易阅读,也更容易理解正在做的事情。较旧的形式选择了uuuuuuuuuuuu…
和ReplaceAll
在第一次通读时就更难理解。除此之外,我会继续更新你的代码。虽然有几个答案强调了dif在使用选项的新旧方法的不同方面,我想做一些额外的观察。较新的构造OptionValue
-OptionsPattern
比OptionQ
提供更多的安全性,因为OptionValue
检查全局选项列表,以确保函数知道传递的选项但是,较旧的选项q
似乎更容易理解,因为它仅基于标准模式匹配,与任何全局属性都没有直接关系。您是否希望这些构造提供这种额外的安全性取决于您,但我猜大多数人会发现它很有用,尤其是对于更大的pr项目
这些类型检查非常有用的一个原因是,函数通常会以链式方式将选项作为参数传递、过滤等,因此如果没有这些检查,一些模式匹配错误将很难捕获,因为它们将在远离原点的地方造成危害
<> P>在核心语言方面,<代码> opthValue<代码> OptionsPattern > <代码>构造是模式匹配器的一个附加部分,可能是其所有特征中最“神奇”的一个。它不需要语义上的,只要一个人愿意考虑选项作为规格。
f[a_, b_, opts___?OptionQ] := Print[someOption/.Flatten[{opts}]/.Options[f]]
f[a_, b_, opts:OptionsPattern[]] := Print[OptionValue[someOption]]
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}}}
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]
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]