gpt4 book ai didi

wolfram-mathematica - 从 Rule 和/切换有什么好处。在大型应用程序中使用 OptionsPattern[] 和 OptionValue?

转载 作者:行者123 更新时间:2023-12-03 11:10:18 25 4
gpt4 key购买 nike

旧习惯难改,我意识到我一直在使用opts___Rule模式匹配和结构,如 thisoption /. {opts} /. Options[myfunction]在我目前正在开发的非常大的包中。 Sal Manango 的“Mathematica Cookbook”提醒我,版本 6 后的方法是 opts:OptionsPattern[]OptionValue[thisoption] .无论如何,该软件包都需要版本 8,但多年来我从未改变过编写此类代码的方式。

是否值得从我的版本 6 之前的做事方式中重构所有这些?有性能或其他好处吗?

问候

马鞭草

编辑:摘要

在回答这个问题时提出了很多好的观点,所以谢谢你们(当然还有一个)。总而言之,是的,我应该重构以使用 OptionsPatternOptionValue . (注意:OptionsPattern 不是 OptionPattern,因为我以前有过!)有很多原因:

  • 这是一个更快的触摸(@Sasha)
  • 它更好地处理参数必须在 HoldForm 中的函数(@Leonid)
  • OptionsPattern自动检查您是否将有效选项传递给该函数(如果您传递给其他函数 (@Leonid) FilterRules 仍然需要
  • )
  • 它处理 RuleDelayed ( :> ) 好多了 (@rcollyer)
  • 它处理嵌套的规则列表而不使用 Flatten (@Andrew)
  • 使用 OptionValue /@ list 分配多个局部变量要容易一些而不是多次调用 someoptions /. {opts} /. Options[thisfunction] (出现在@rcollyer 和我之间的评论中)

  • 编辑:7 月 25 日 我一开始以为是曾经使用过 /.如果您有意从另一个函数中提取默认选项,而不是实际调用的那个,则语法可能仍然有意义。事实证明,这是通过使用 OptionsPattern[] 的形式来处理的。里面有一个头像列表,例如: OptionsPattern[{myLineGraph, DateListPlot, myDateTicks, GraphNotesGrid}] (请参阅 documentation 中的“更多信息”部分)。我最近才解决了这个问题。

    最佳答案

    虽然有几个答案强调了使用选项的新旧方式的不同方面,但我想再做一些额外的观察。较新的结构 OptionValue - OptionsPattern提供比 OptionQ 更高的安全性, 自 OptionValue检查全局选项列表以确保函数知道传递的选项。较旧的 OptionQ然而似乎更容易理解,因为它仅基于标准模式匹配并且与任何全局属性没有直接关系。您是否希望这些构造中的任何一个提供这种额外的安全性取决于您,但我的猜测是大多数人发现它很有用,尤其是对于较大的项目。

    这些类型检查真正有用的一个原因是,选项通常以类似链的方式、过滤等方式由函数作为参数传递,因此如果没有这样的检查,一些模式匹配错误将很难被发现,因为它们会在“远离”它们的起源地造成伤害。

    在核心语言方面,OptionValue - OptionsPattern构造是模式匹配器的补充,也许是其所有功能中最“神奇”的。语义上没有必要,只要人们愿意将选项视为规则的一种特殊情况。此外,OptionValue将模式匹配连接到 Options[symbol] - 全局属性(property)。所以,如果坚持语言纯洁,规则如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 讨论的速度改进。然而,速度问题往往被过分强调(这并不是要减损他的观察),我希望对于带有选项的函数尤其如此,因为这些往往是更高级的函数,它们可能具有非微不足道的 body ,大部分计算时间都将花费在这里。

    另一个相当有趣的区别是当需要将选项传递给保存其参数的函数时。考虑以下示例:
    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]

    这并非完全微不足道。发生的事情是模式匹配器,要建立匹配或不匹配的事实,必须评估第三个 Print ,作为 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++ 比较(如果这是一个合适的比较):自动化和(可能)安全性与简单性和纯度。我的两分钱。

    关于wolfram-mathematica - 从 Rule 和/切换有什么好处。在大型应用程序中使用 OptionsPattern[] 和 OptionValue?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6617511/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com