Defining a function with an optional value that is by default a function of another paramether of the function in mathematica

北城以北 提交于 2019-12-17 18:44:14

问题


I am trying to define a function that takes in a Matrix and when its dimensions are not provided as input, compute these dimensions in the optional parameter d

This does not work but gives you the idea (The options parameter need be constants):

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

Indeed the simple way is to input an impossible value and in the function def put an if condition as in

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

How can I accomplish this most efficiently?


回答1:


For your original formulation, @WReach gave a fine answer. However, it may make sense to reconsider your design a bit: note that you have a (dependent on input arguments) value for d in any case. Optional arguments are designed exactly for that - to be optional. In your case, a default argument seems more appropriate. You can set it up with Automatic, similarly to what @WReach suggested:

dimMAuto[a_?MatrixQ, d_: Automatic] :=
     If[d === Automatic, Dimensions[a], d];

To use this in more than one place in your code, you will however need to introduce an auxiliary variable or constant (using With or Module), to store this value. As an alternative, you can also use the following code:

Module[{dims},
  dimM[a_?MatrixQ, d_: dims] :=
      Block[{dims = Dimensions[a]}, 
          d]
] 

which has the advantage that you can use the same original parameter d everywhere in the body of your function. What happens here is rather non-trivial: Module is used to generate a unique symbol, which is then given as a default for d and used to dynamically compute the dimensions. Note that Block localizes not the symbol dims, but the unique symbol like dims$77542 produced by Module. This combination of Module and Block makes this technique completely safe. Examples of use:

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

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

I think this combination of Module and Block is an interesting technique which may find other uses. Essentially, it is a version of dynamic scoping made safe by lexical scoping (or, more precisely, its imitation in Mathematica) - since one of the main dangers of dynamic scoping is inadvertent collisions of dynamically localized symbols with the same name.

On an unrelated matter - it is best to not start your variables and functions with a capital letter, since they may collide with the system symbols.




回答2:


This is not really an improvement over your "simple way", but for many built-in Mathematica functions the symbol Automatic is used as the "impossible value". For example:

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} *)


来源:https://stackoverflow.com/questions/7394113/defining-a-function-with-an-optional-value-that-is-by-default-a-function-of-anot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!