Вот окончательная версия моего ответа, содержащая вклады от ответа Бретта Чемпиона.
ClearAll[def];
SetAttributes[def, HoldAll];
def[lhs : f_[args___] :> rhs_] /; !FreeQ[Unevaluated[lhs], OptionsPattern] :=
With[{optionNames = Options[f][[All, 1]]},
lhs := Block[optionNames, optionNames = OptionValue[optionNames]; rhs]];
def[lhs : f_[args___] :> rhs_] := lhs := rhs;
Причина, по которой определение приводится в качестве отложенного правила в аргументе, заключается в том, что таким образом мы можем извлечь выгоду из подсветки синтаксиса.Блочный трюк используется потому, что он подходит к проблеме: он не мешает возможным вложенным лексическим конструкциям внутри вашей функции, и поэтому нет опасности непреднамеренного захвата переменных.Мы проверяем наличие OptionsPattern, так как этот код не будет корректным для определений без него, и мы хотим, чтобы def
также работал в этом случае.Пример использования:
Clear[f, a, b, c, d];
Options[f] = {a -> c, b -> d};
(*The default values.*)
def[f[n_, OptionsPattern[]] :> (a + b)^n]
Теперь вы можете посмотреть определение:
Global`f
f[n$_,OptionsPattern[]]:=Block[{a,b},{a,b}=OptionValue[{a,b}];(a+b)^n$]
f[n_,m_]:=m+n
Options[f]={a->c,b->d}
Мы можем проверить это сейчас:
In[10]:= f[2]
Out[10]= (c+d)^2
In[11]:= f[2,a->e,b->q]
Out[11]= (e+q)^2
Изменения сделаны на"время компиляции" и довольно прозрачно.В то время как это решение экономит некоторую типизацию по Бретту, оно определяет набор имен опций во время компиляции, в то время как у Бретта - во время исполнения.Следовательно, он немного более хрупок, чем у Бретта: если вы добавите новую функцию в функцию после того, как она была определена с помощью def
, вы должны очистить ее и повторно запустить def
.Однако на практике принято начинать с ClearAll и помещать все определения в один фрагмент (ячейку), поэтому это не представляется реальной проблемой.Кроме того, он не может работать с именами строковых опций, но ваша оригинальная концепция также предполагает, что они являются символами.Кроме того, они не должны иметь глобальных значений, по крайней мере, во время выполнения def
.