我正在尝试定义一个接收矩阵的函数,当它的尺寸未作为输入提供时,在可选参数d
这不起作用但是给你一个想法(options参数需要是常量):
Options[DimM] = {d -> Dimensions[A]};
DimM[A_?MatrixQ, OptionsPattern[]] := OptionValue@d;
实际上,简单的方法是输入一个不可能的值,并在函数def中输入if条件,如
Options[DimM] = {d -> 0};
DimM[A_?MatrixQ, OptionsPattern[]] :=If[OptionValue@d==0,Dimensions[A],OptionValue@d]
如何最有效地完成这项工作?
答案 0 :(得分:9)
对于您的原始配方,@ WReach给出了一个很好的答案。但是,重新考虑一下您的设计可能有意义:请注意,在任何情况下{/ 1}} 都有(依赖于输入参数)值。可选参数的设计完全符合 - 可选。在您的情况下,默认参数似乎更合适。您可以使用d
进行设置,类似于@WReach建议的内容:
Automatic
要在代码中的多个位置使用此功能,您需要引入辅助变量或常量(使用dimMAuto[a_?MatrixQ, d_: Automatic] :=
If[d === Automatic, Dimensions[a], d];
或With
)来存储此值。作为替代方案,您还可以使用以下代码:
Module
的优点是您可以在函数体中的任何位置使用相同的原始参数Module[{dims},
dimM[a_?MatrixQ, d_: dims] :=
Block[{dims = Dimensions[a]},
d]
]
。这里发生的事情非常重要:d
用于生成唯一符号,然后将其作为Module
的默认值给出,并用于动态计算维度。请注意,d
本地化不是符号Block
,而是dims
生成的唯一符号dims$77542
。 Module
和Module
的这种组合使这项技术完全安全。使用示例:
Block
我认为In[1466]:= dimM[IdentityMatrix[3],{1,1}]
Out[1466]= {1,1}
In[1467]:= dimM[IdentityMatrix[3]]
Out[1467]= {3,3}
和Module
的这种组合是一种有趣的技术,可能会找到其他用途。从本质上讲,它是动态范围的一个版本,通过词法范围(或更准确地说,它在Mathematica中的模仿)变得安全 - 因为动态范围的主要危险之一是动态本地化符号与同名的无意碰撞。
在不相关的事情上 - 最好不要用大写字母开始你的变量和函数,因为它们可能会与系统符号发生碰撞。
答案 1 :(得分:5)
这并不是对“简单方法”的改进,但对于许多内置的Mathematica函数,符号Automatic
被用作“不可能的值”。例如:
Options[DimM] = {d -> Automatic};
DimM[A_?MatrixQ, OptionsPattern[]] := OptionValue[d] /. Automatic->Dimensions[A]
DimM[RandomInteger[10, {2, 2}]]
(* {2, 2} *)
DimM[RandomInteger[10, {2, 2}], d -> {5, 5}]
(* {5, 5} *)