Определить пользовательские обозначения в Mathematica
Мне часто нужно извлекать, чтобы ограничить списки значений подсписками, то есть, если vals
дает значения vars={x1,x2,x3,x4}
, и мне нужны значения svars={x2,x4}
, я делаю restrict[list,vars,svars]
где
restrict[vars_, svars_, vals_] :=
Extract[vals, Flatten[Position[vars, #] & /@ svars, 1]]
Я хотел бы улучшить читабельность кода, возможно, определив следующие пользовательские обозначения для restrict[vars,svars,vals]
(источник: yaroslavvb.com)
Мои вопросы
- Какой хороший способ реализовать это?
- Это хорошая идея в целом?
Ответы
Ответ 1
Хорошие обозначения могут быть очень полезными - но я не уверен, что этот конкретный нужен...
Тем не менее, пакет Notation
делает это довольно легко. Поскольку при использовании палитры "Нотация" есть много скрытых ящиков, я воспользуюсь скриншотом:
Вы можете увидеть базовую структуру NotationMake*
downvalues, используя опцию Action -> PrintNotationRules
. В [4] на скриншоте генерируется
NotationMakeExpression[
SubscriptBox[vals_, RowBox[{vars_, "|", svars_}]], StandardForm] :=
MakeExpression[
RowBox[{"restrict", "[", RowBox[{vars, ",", svars, ",", vals}],
"]"}], StandardForm]
NotationMakeBoxes[Subscript[vals_, vars_ | svars_], StandardForm] :=
SubscriptBox[MakeBoxes[vals, StandardForm],
RowBox[{Parenthesize[vars, StandardForm, Alternatives], "|",
Parenthesize[svars, StandardForm, Alternatives]}]]
Ответ 2
Что касается 2: я бы передал список правил Thread[vars -> vals]
вместо отслеживания имен и значений отдельно.
Одна из моих любимых идиом Mathematica состоит в том, чтобы использовать списки правил вместе с WithRules
, как определено ниже: Эта конструкция оценивает выражение в блоке With
, где все заменяющие символы были (рекурсивно определены). Это позволит вам делать такие вещи, как
WithRules[{a -> 1, b -> 2 a + 1}, b]
и вы довольно далеко приближаетесь к именованным аргументам.
SetAttributes[WithRules, HoldRest]
WithRules[rules_, expr_] := Module[{notSet}, Quiet[
With[{args = Reverse[rules /. Rule[a_, b_] -> notSet[a, b]]},
Fold[With[{#2}, #1] &, expr, args]] /. notSet -> Set,
With::lvw]]
Изменить: конструкция WithRules
основана на этих двух потоках usenet (благодаря Simon для их выкапывания):