Ваша конструкция технически в порядке, но концептуально это смешивание привязки переменных и сопоставление с образцом. Другими словами, это опирается на определенное недокументированное поведение сопоставителя шаблонов (которое не обязательно является злым, просто заметьте). Хуже всего то, что это довольно неясно. Если вы уверены, что у вас не возникнет проблем с чтением этого документа в более широком контексте через несколько месяцев, и вы будете кодировать только для собственного использования, тогда я не вижу проблем. B.t.w., другая альтернатива (как уже было предложено другими): f[{x_, ___}] := f[x]; f[x__] := g[x]
. Кроме того, обернуть Quiet
вокруг SetDelayed
легче, чем On/Off
.
EDIT
Вот мой расширенный взгляд на проблему, добавленный по запросу @ Mr.Wizard. Отказ от ответственности заключается в том, что это всего лишь предположения, они могут быть полностью или частично ошибочными.
Стадия переменной привязки - это, по большей части, бесшумная стадия при оценке таких объемных конструкций, как Module
, With
, Block
, Function
. Задержанные правила, сформированные с помощью RuleDelayed
, также являются ограничивающими конструкциями, в том смысле, что переменные шаблона имеют определенную защиту от конфликтов имен с другими ограничивающими конструкциями, плюс там также происходит связывание переменных. Привязка переменных - это процесс связывания имени переменной с некоторым значением (полученным посредством деструктуризации выражения для правил). Для таких областей видимости, как Module
, With
, Block
, Function
, мы имеем большой контроль над связыванием переменных, поскольку мы можем переопределить атрибуты Hold * этих конструкций, записав что-то вроде x=y;Function[Evaluate[x],y^2]
, Для правил привязка переменной происходит внутри сопоставителя шаблонов и не так управляема. Как правило, вы мало задумываетесь о том, как происходит связывание, либо потому, что нет никакой двусмысленности, либо потому, что семантика разрешения конфликтов имен прописана в документах или где-либо еще (например, существует общее правило, которое применяется для конфликтов имен во вложенных лексических контекстных конструкциях предпочтительны внутренние привязки).
В данном случае вы зависите от механизма привязки переменных к правилам и от того, как он взаимодействует с сопоставителем шаблонов. Один факт (не знаю, документировано или нет) о шаблоне-сопоставителе заключается в том, что он пытается выполнить сопоставление слева направо, когда дано построение шаблона с Alternatives
. Из здравого смысла следует ожидать, что привязка переменной происходит после совпадения, и, следовательно, ваша конструкция в порядке. Тем не менее, это копание во внутренних органах, которые мы не можем контролировать. Может случиться так, что не будет другого логически согласованного способа поведения механизма сопоставления с образцом / привязки, или это может быть иначе.
Как я уже сказал, это само по себе не обязательно плохо - мы часто полагаемся на какое-то недокументированное поведение, если у нас есть эмпирические доказательства для функции, и эта функция позволяет нам легко делать что-то нетривиальное. Моим главным возражением против конструкции является ее неясность - ее сложнее читать, чем код, использующий два отдельных правила (для меня в любом случае).