Mathematica 10 представила Association
, который обладает многими наиболее важными свойствами struct
(и имеет синтаксис, аналогичный правилам замены, с которыми вы экспериментировали).
plotLimits = <| "lowerLimit" -> -Pi, "upperLimit" -> Pi |>;
(*this is the syntax for an Association[]*)
foo[p_]:=Module[{},
Plot[Sin[x],{x,p["lowerLimit"],p["upperLimit"]}]
];
(* assoc["key"] is one of many equivalent ways to specify the data *)
Мы также можем легко реализовать проверку аргументов
fooWithChecks[p_?(NumericQ[#["lowerLimit"]] && NumericQ[#["upperLimit"]] &)] := Module[{},
Plot[Sin[x], {x, p["lowerLimit"], p["upperLimit"]}]
];
В этом случае foo[plotLimits]
и fooWithChecks[plotLimits]
дают один и тот же график, поскольку plotLimits
имеет хорошие числовые значения.Но если мы определим
badPlotLimits = <|"lowerLimit" -> bad, "upperLimit" -> Pi|>;
, то оценка foo[badPlotLimits]
даст ошибку
Plot::plln: Limiting value bad in {x,<|lowerLimit->bad,upperLimit->2 \[Pi]|>[lowerLimit],<|lowerLimit->bad,upperLimit->2 \[Pi]|>[upperLimit]} is not a machine-sized real number. >>
Plot[Sin[x], {x, <|"lowerLimit" -> bad, "upperLimit" -> 2 \[Pi]|>["lowerLimit"], <|"lowerLimit" -> bad, "upperLimit" -> 2 \[Pi]|>["upperLimit"]}]
, но оценка fooWithChecks[badPlotLimits]
просто останется без оценки, поскольку аргумент не проходит проверку NumericQ:
fooWithChecks[<|"lowerLimit" -> bad, "upperLimit" -> 2 \[Pi]|>]
Мне не понятно, почему вы спрашиваете о форме foo[from_?NumericQ, to_?NumericQ]
, а не foo[p_?(someCheckFunction)]
.Ключевым преимуществом наличия структуры в первую очередь является то, что вы можете реорганизовать, как структура хранится в памяти, скажем, меняя порядок «lowerLimit» и «upperLimit», не переписывая ни одну из функций, которые ее используют (так как они называют это p["lowerLimit"]
, а не p[[1]]
).Эта способность нарушается, если вы определяете foo
таким образом, что при вызове foo
аргументы выводятся по порядку.(Другими словами, вы не позволяете foo
узнать о структуре.) Конечно, вы все еще можете сделать это, возможно, потому что вы хотите использовать foo
и для неструктур:
foo[from_?NumericQ, to_?NumericQ] :=
Module[{}, Plot[Sin[x], {x, from, to}]];
foo[p] := foo[p["lowerLimit"], p["upperLimit"]];
Если вы хотите быть очень осторожным, вы можете использовать это:
foo[p_?(SubsetQ[Keys[#],{"lowerLimit", "upperLimit"}]&)] :=
foo[p["lowerLimit"], p["upperLimit"]];
К сожалению, вы не можете дать имена определенным Association
шаблонам (которые будут Association
аналог этот метод для списков) с использованием чего-то подобного
plotLimitType=<|"lowerLimit"->_NumericQ, "upperLimit"->_NumericQ|>
, потому что ассоциации являются атомарными (ish).См. здесь .
Кстати, обратите внимание, что такие ключи, как "lowerLimit" не обязательно должны быть в кавычках.Использование этого стиля
plotLimits = <|lowerLimit -> -Pi, upperLimit -> Pi|>;
также работает.
Для получения дополнительной информации см.