Wolfram mathematica 使用可选值定义函数,默认情况下,该值是mathematica中函数的另一个参数的函数

Wolfram mathematica 使用可选值定义函数,默认情况下,该值是mathematica中函数的另一个参数的函数,wolfram-mathematica,Wolfram Mathematica,我试图定义一个函数,它接受一个矩阵,当它的维数没有作为输入提供时,在可选参数d 这不起作用,但给了您一个想法(options参数需要是常量): 实际上,最简单的方法是输入一个不可能的值,并在函数def中输入if条件,如中所示 Options[DimM] = {d -> 0}; DimM[A_?MatrixQ, OptionsPattern[]] :=If[OptionValue@d==0,Dimensions[A],OptionValue@d] 如何才能最有效地完成此任务?这并不是对“简

我试图定义一个函数,它接受一个矩阵,当它的维数没有作为输入提供时,在可选参数
d

这不起作用,但给了您一个想法(options参数需要是常量):

实际上,最简单的方法是输入一个不可能的值,并在函数def中输入if条件,如中所示

Options[DimM] = {d -> 0};
DimM[A_?MatrixQ, OptionsPattern[]] :=If[OptionValue@d==0,Dimensions[A],OptionValue@d]

如何才能最有效地完成此任务?

这并不是对“简单方法”的真正改进,但对于许多内置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} *)

对于你最初的表述,@florach给出了一个很好的回答。然而,重新考虑一下您的设计可能是有意义的:请注意,在任何情况下,
d
都有一个值(取决于输入参数)。可选参数的设计正是为了实现这一点,即它是可选的。在您的情况下,默认参数似乎更合适。您可以使用
Automatic
进行设置,类似于@florach建议的设置:

dimMAuto[a_?MatrixQ, d_: Automatic] :=
     If[d === Automatic, Dimensions[a], d];
但是,要在代码中的多个位置使用此值,您需要引入辅助变量或常量(使用
模块
)来存储此值。此外,您还可以使用以下代码:

Module[{dims},
  dimM[a_?MatrixQ, d_: dims] :=
      Block[{dims = Dimensions[a]}, 
          d]
] 
它的优点是可以在函数体的任何地方使用相同的原始参数
d
。这里发生的事情非常重要:
模块
用于生成唯一的符号,然后作为
d
的默认值给出,并用于动态计算尺寸。请注意,
Block
不会本地化符号
dims
,而是本地化由
模块产生的唯一符号,如
dims$77542
模块
的组合使该技术完全安全。使用示例:

In[1466]:= dimM[IdentityMatrix[3],{1,1}]
Out[1466]= {1,1}

In[1467]:= dimM[IdentityMatrix[3]]
Out[1467]= {3,3}  
我认为
模块
的组合是一种有趣的技术,可能会有其他用途。从本质上说,它是动态范围界定的一个版本,通过词汇范围界定(或者更准确地说,它在Mathematica中的模仿)变得安全,因为动态范围界定的主要危险之一是具有相同名称的动态本地化符号的无意碰撞


在一个不相关的问题上-最好不要以大写字母开头变量和函数,因为它们可能会与系统符号冲突。

谢谢。如果我有多个可选参数呢?如何命名它们?您可以对所有它们使用
Automatic
。然后,在函数内部依次引用每个选项:
a=OptionValue[a]/。自动->默认A;b=期权价值[b]/。自动->默认B
。对,对!如果提供了d的值,我们还会计算维度[A]吗?我认为不是,因为如果OptionValue[d]中没有找到Automatic,那么替换规则就不会被激活。我错过了吗?我的目标是避免计算维度[A],如果在上下文中我已经知道并可以传递它。@Phil如前所述,解决方案在任何情况下都会计算
维度。为了避免在这种方法中计算
维度
,您可以简单地使用延迟规则:
自动:>defaultA
,等等。如果选项值不是
自动
,则不会激活替换规则,这是正确的。然而,正如我所写的,
Dimensions[A]
将始终进行计算。为了避免不必要的计算,替换规则必须作为延迟规则编写,即
Automatic:>Dimensions[a]
。这非常深刻!我唯一关心的是效率。似乎模块/块组合会计算尺寸[a],无论是否提供了d的值,这正是我试图不做的。我错过了什么吗?@Phil是的,你是对的。对于
维度
,开销可能不是很重要,但如果这只是一个玩具示例,我明白你的意思。您可以让它有条件地计算函数,但代价是使代码更加丑陋:
Module[{dims},dimM[a_?MatrixQ,d::dims]:=Block[{dims},If[d==dims,dims=Dimensions[a]];function body]
。也许,这有点破坏了一个目的,但您仍然可以在身体的任何地方使用原始参数
d
。您还可以编写一个宏来抽象出
模块
-
部分。如果我理解正确,在
模块
值中使用
是通过一个本地唯一变量创建一个动态默认值,该变量可以根据需要获取其值。聪明+1.@rcollyer是的,就是这个想法。仅仅使用
Block[{dims},…
是危险的,因为原则上,函数体可能会在对函数体求值产生的函数调用链中使用相同的全局符号
dims
(函数体中不一定存在
dims
)。这是动态作用域的一个主要问题。但是,通过使用
模块
,我们可以确保所讨论的动态作用域符号是唯一的,并且不可能与其他符号冲突。AFAICT,这种动态作用域的变体更安全。我以前使用过几次。还有一篇有趣的论文,Leonid.:-)
In[1466]:= dimM[IdentityMatrix[3],{1,1}]
Out[1466]= {1,1}

In[1467]:= dimM[IdentityMatrix[3]]
Out[1467]= {3,3}