gpt4 book ai didi

wolfram-mathematica - 指定选项的设置

转载 作者:行者123 更新时间:2023-12-04 07:58:26 24 4
gpt4 key购买 nike

您如何明确说明选项的有效设置?以这个例子为例

Options[myFunc] = {opt1 -> "SomeString"};
myFunc[OptionsPattern[]] := Print[OptionValue[opt1]];
myFunc打印选项的值。如果我们评估 myFunc[opt1 -> {1, 2}]然后打印 {1, 2} .这个函数基本上会打印任何你设置为 opt1 的东西。 .我的问题是,如何确保我的函数只接受给定数量的 opt1 值? .我们可以从简单的东西开始,比如 StringInteger .

为了更好地了解我们在给 opt1 的错误值时所期望的行为我们可以看看当我们为 PlotRange 提供错误值时会发生什么。在函数 Plot .

enter image description here

在图片中给出的示例中,我故意给 PlotRange 提供了错误的值。选项并给我一条消息,指定该特定选项的正确值类型。好像是 PlotRange最终采用其默认值,因此返回 Graphics目的。

在这个简单的例子中,我们想要得到的是这样的:
myFunc::sometag : Value of option opt1 -> `1` is not a string or integer.

如何做到这一点?

最佳答案

一个简单的解决方案

这是一个简单的方法:

In[304]:= ClearAll[myFunc];
Options[myFunc] = {opt1 -> "SomeString"};
myFunc::badopt = "Value of option opt1 -> `1` is not a string or integer.";
myFunc[OptionsPattern[]] :=
With[{val = OptionValue[opt1]},
With[{error = ! MatchQ[val, _String | _Integer]},
If[error, Message[myFunc::badopt , val]];
(Print[val] /; ! error)]];

例如:
In[308]:= myFunc[opt1 -> 1]

During evaluation of In[308]:= 1

In[309]:= myFunc[opt1 -> {1, 2}]

During evaluation of In[309]:= myFunc::badopt:
Value of option opt1 -> {1,2} is not a string or integer.

Out[309]= myFunc[opt1 -> {1, 2}]

使用自定义赋值运算符使其通用

我们可以使用 OptionValue在函数内部使用单个参数作为选项名称,以排除错误检查的乏味。这可以通过使用 mma 元编程工具来实现。这是自定义赋值运算符的代码:
ClearAll[def, OptionSpecs];
SetAttributes[def, HoldAll];
def[f_[args___] :> body_,OptionSpecs[optionSpecs : {(_ -> {_, Fail :> _}) ..}]] :=
f[args] :=
Module[{error = False},
Scan[
With[{optptrn = First[# /. optionSpecs], optval = OptionValue[#]},
If[! MatchQ[optval, optptrn ],
error = True;
Return[(Fail /. Last[# /. optionSpecs])[optval]]]] &,
optionSpecs[[All, 1]]
];
body /; ! error];

它所做的是将函数定义作为规则 f_[args___]:>body_ ,并且
在检测到传递的选项之一中的错误时执行的可接受选项设置和操作的规范。然后我们在执行主体之前注入(inject)错误测试代码( Scan)。一旦发现第一个设置不合适的选项,错误标志就会设置为 True , 以及 Fail:>code_ 中指定的任何代码该选项的部分规范。期权规范模式 (_ -> {_, Fail :> _})应阅读 (optname_ -> {optpattern_, Fail :> onerror_}) , 其中 optname是选项名称, optpattern是选项值必须匹配的模式, onerror是检测到错误时执行的任意代码。请注意,我们使用 RuleDelayedFail:>onerror_ ,以防止过早评估该代码。注意 b.t.w。该 OptionSpecs添加 wrapper 只是为了便于阅读 - 它是一个完全空闲的符号,没有附加任何规则。

以下是使用此自定义赋值运算符定义的函数示例:
ClearAll[myFunc1];
Options[myFunc1] = {opt1 -> "SomeString", opt2 -> 0};
myFunc1::badopt1 = "Value of option opt1 -> `1` is not a string or integer.";
myFunc1::badopt2 = "Value of option opt2 -> `1` is not an integer.";
def[myFunc1[OptionsPattern[]] :>
Print[{OptionValue[opt1], OptionValue[opt2]}],
OptionSpecs[{
opt1 -> {_Integer | _String,
Fail :> ((Message[myFunc1::badopt1, #]; Return[$Failed]) &)},
opt2 -> {_Integer,
Fail :> ((Message[myFunc1::badopt2, #]; Return[$Failed]) &)}}
]];

以下是使用示例:
In[473]:= myFunc1[]
During evaluation of In[473]:= {SomeString,0}

In[474]:= myFunc1[opt2-> 10]
During evaluation of In[474]:= {SomeString,10}

In[475]:= myFunc1[opt2-> 10,opt1-> "other"]
During evaluation of In[475]:= {other,10}

In[476]:= myFunc1[opt2-> 1/2]
During evaluation of In[476]:= myFunc1::badopt2:
Value of option opt2 -> 1/2 is not an integer.

Out[476]= $Failed

In[477]:= myFunc1[opt2-> 15,opt1->1/2]
During evaluation of In[477]:= myFunc1::badopt1:
Value of option opt1 -> 1/2 is not a string or integer.

Out[477]= $Failed

自动向已定义的函数添加选项检查

您可能还对我编写的用于测试通过选项的包感兴趣: CheckOptions , 可用 here .包装内附有说明其用途的笔记本。它解析你的函数的定义并创建额外的定义来检查选项。当前的缺点(除了可能并不总是合适的新定义的生成)是它仅涵盖通过 OptionQ 定义选项的旧方法。谓词(我还没有更新它以涵盖 OptionValue - OptionsPattern 。我将在这里复制随附笔记本的一部分以说明它是如何工作的:

考虑一个模型函数:
In[276]:= ClearAll[f];
f[x_, opts___?OptionQ]:= x^2;
f[x_, y_, opts___?OptionQ] := x + y;
f[x_, y_, z_] := x*y*z;

假设我们要在选项 FontSize 时返回错误消息。传递给我们的函数:
In[280]:= 
f::badopt="Inappropriate option";
test[f,heldopts_Hold,heldArgs_Hold]:=(FontSize/.Flatten[List@@heldopts])=!=FontSize;
rhsF[f,__]:=(Message[f::badopt];$Failed);

我们添加选项 - 检查定义:
In[283]:= AddOptionsCheck[f,test,rhsF]
Out[283]= {HoldPattern[f[x_,opts___?OptionQ]/;test[f,Hold[opts],Hold[x,opts]]]:>
rhsF[f,Hold[opts],Hold[x,opts]],
HoldPattern[f[x_,y_,opts___?OptionQ]/;test[f,Hold[opts],Hold[x,y,opts]]]:>
rhsF[f,Hold[opts],Hold[x,y,opts]],
HoldPattern[f[x_,opts___?OptionQ]]:>x^2,
HoldPattern[f[x_,y_,opts___?OptionQ]]:>x+y,
HoldPattern[f[x_,y_,z_]]:>x y z}

如您所见,一旦我们调用 AddOptionsCheck ,它会生成新的定义。它接受函数名、测试函数和失败时执行的函数。测试函数接受主函数名称、传递给它的选项(包裹在 Hold 中)和传递给它的非选项参数(也包裹在 Hold 中)。从生成的定义中,您可以看到它的作用。

我们现在检查各种输入:
In[284]:= f[3]
Out[284]= 9

In[285]:= f[3,FontWeight->Bold]
Out[285]= 9

In[286]:= f[3,FontWeight->Bold,FontSize->5]
During evaluation of In[286]:= f::badopt: Inappropriate option
Out[286]= $Failed

In[289]:= f[a,b]
Out[289]= a+b

In[290]:= f[a,b,FontWeight->Bold]
Out[290]= a+b

In[291]:= f[a,b,FontWeight->Bold,FontSize->5]
During evaluation of In[291]:= f::badopt: Inappropriate option
Out[291]= $Failed

In[292]:= OptionIsChecked[f,test]
Out[292]= True

请注意,测试函数可以测试涉及函数名称、传递参数和传递选项的任意条件。我还有一个包裹, PackageOptionChecks ,在同一页面上可用,它具有更简单的语法来专门测试 r.h.s.选项,也可以应用于整个包。它的使用的一个实际例子是另一个包, PackageSymbolsDependencies ,其函数选项受 PackageOptionChecks 的“保护” .另外, PackageOptionChecks可应用于 Global' 中的函数上下文也是如此,没有必要有一个包。

当前实现的另一个限制是我们不能返回未评估的函数。请在包装随附的笔记本中查看更详细的讨论。如果对此有足够的兴趣,我会考虑更新包以消除我提到的一些限制。

关于wolfram-mathematica - 指定选项的设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6587833/

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