Определение функции с необязательным значением, которое по умолчанию является функцией другого параметрирования функции в математике

Я пытаюсь определить функцию, которая принимает матрицу, и когда ее размеры не представлены в качестве входных данных, вычислите эти измерения в необязательном параметре d

Это не работает, но дает вам идею (параметр параметров должен быть константами):

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

В самом деле, простой способ - ввести невозможное значение, а в функции def поставить условие if, как в

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

Как я могу выполнить это наиболее эффективно?

Ответ 1

Для вашей оригинальной формулировки @WReach дал прекрасный ответ. Тем не менее, имеет смысл немного пересмотреть ваш дизайн: обратите внимание, что в любом случае вы имеете значение (зависит от входных аргументов) для d. Необязательные аргументы предназначены именно для этого - быть необязательными. В вашем случае аргумент по умолчанию кажется более подходящим. Вы можете настроить его с помощью Automatic, аналогично тому, что предложил @WReach:

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 и Block представляет собой интересную технику, которая может найти другое применение. По сути, это версия динамического охвата, сделанная безопасным путем лексического охвата (или, точнее, его подражания в Mathematica), поскольку одной из основных опасностей динамического охвата является непреднамеренное столкновение динамически локализованных символов с тем же именем.

В несвязанной материи - лучше не начинать переменные и функции с большой буквы, так как они могут сталкиваться с системными символами.

Ответ 2

Это не улучшает ваш "простой способ", но для многих встроенных функций 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} *)