Безопасно ли выключать Pattern :: patv? - PullRequest
9 голосов
/ 04 декабря 2011

По умолчанию Mathematica выдает предупреждающее сообщение, если я использую одно и то же имя для шаблонов Blank и BlankSequence:

f[{x_, ___} | x__] := g[x]
Pattern::patv: Name x used for both fixed and variable length patterns. >>

Pattern::patv: Name x used for both fixed and variable length patterns. >>

И все же функция работает так, как я хочу:

f[{1, 2, 3}]
f[1, 2, 3]
g[1]
g[1, 2, 3]

Следовательно, безопасно ли использовать Off[Pattern::patv] и продолжать, как мне угодно?


Я знаю о множестве различных, более многословных методов, которые могут выполнить одну и ту же задачу, и я не желаю анализировать их достоинства. Меня интересует только безопасность этого конкретного.

Ответы [ 2 ]

6 голосов
/ 04 декабря 2011

Ваша конструкция технически в порядке, но концептуально это смешивание привязки переменных и сопоставление с образцом. Другими словами, это опирается на определенное недокументированное поведение сопоставителя шаблонов (которое не обязательно является злым, просто заметьте). Хуже всего то, что это довольно неясно. Если вы уверены, что у вас не возникнет проблем с чтением этого документа в более широком контексте через несколько месяцев, и вы будете кодировать только для собственного использования, тогда я не вижу проблем. 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. Из здравого смысла следует ожидать, что привязка переменной происходит после совпадения, и, следовательно, ваша конструкция в порядке. Тем не менее, это копание во внутренних органах, которые мы не можем контролировать. Может случиться так, что не будет другого логически согласованного способа поведения механизма сопоставления с образцом / привязки, или это может быть иначе.

Как я уже сказал, это само по себе не обязательно плохо - мы часто полагаемся на какое-то недокументированное поведение, если у нас есть эмпирические доказательства для функции, и эта функция позволяет нам легко делать что-то нетривиальное. Моим главным возражением против конструкции является ее неясность - ее сложнее читать, чем код, использующий два отдельных правила (для меня в любом случае).

5 голосов
/ 04 декабря 2011

Когда вы выключаете и снова включаете сообщение, вы пишете 3 строки, чтобы использовать ваш шаблон. Если вы хотите выразить, что f должен взять первый элемент, если ему дан один список, и взять все элементы, если ему дано более одного параметра, что не так с

f[{x_, ___}] := g[x];
f[x__] := g[x];

что еще на одну строку меньше писать?


Но чтобы высказать мнение о вашей модели: проблема, которую я вижу здесь,

f[{x_, __} | x__] := {x};
g[x__ | {x_, __}] := {x};
f[{1, 2, 3}]
g[{1, 2, 3}]

Out[6]= {1}

Out[7]= {{1, 2, 3}}

Это было бы неожиданно и, возможно, сложно отладить. Использование двух определений с разными шаблонами делает правильную работу:

f[{x_, __}] := {x};
f[x__] := {x};
g[x__] := {x};
g[{x_, __}] := {x}
f[{1, 2, 3}]
g[{1, 2, 3}]

Out[7]= {1}

Out[8]= {1}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...