Определить пользовательские обозначения в 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. Какой хороший способ реализовать это?
  2. Это хорошая идея в целом?

Ответ 1

Хорошие обозначения могут быть очень полезными - но я не уверен, что этот конкретный нужен...

Тем не менее, пакет Notation делает это довольно легко. Поскольку при использовании палитры "Нотация" есть много скрытых ящиков, я воспользуюсь скриншотом: alt text

Вы можете увидеть базовую структуру 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 для их выкапывания):