Ответ 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), поскольку одной из основных опасностей динамического охвата является непреднамеренное столкновение динамически локализованных символов с тем же именем.
В несвязанной материи - лучше не начинать переменные и функции с большой буквы, так как они могут сталкиваться с системными символами.