Is it safe to turn off Pattern::patv?

点点圈 提交于 2020-01-21 04:28:48

问题


By default Mathematica throws a warning message if I use the same name for both Blank and BlankSequence patterns:

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. >>

Yet the function works as I desire:

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

Therefore, is it safe to use Off[Pattern::patv] and continue as I please?


I am aware of a variety of different, more verbose methods that can accomplish the same task, and it is not my desire to analyze their respective merits. I am interested only in the safety of this specific one.


回答1:


Your construction seems technically ok, but conceptually this is mixing variable binding and the pattern-matching. In other words, this relies on certain undocumented behavior of the pattern-matcher (which is not necessarily evil, just to note). What is worse is that this is rather obscure. If you are sure you will have no problem reading this yourself in a larger context a few months from now, and you only code for your own use, then I don't see a problem. B.t.w., another alternative (as already suggested by others): f[{x_, ___}] := f[x]; f[x__] := g[x]. Also, wrapping Quiet around SetDelayed is easier than On/Off.

EDIT

Here is my expanded view on the problem, added upon @Mr.Wizard's request. A disclaimer is that these are just speculations, they may be totally or partially wrong.

The variable - binding stage is a mostly silent stage in evaluation of scoping constructs such as Module, With, Block, Function. The delayed rules formed with RuleDelayed also are scoping constructs, in the sense that pattern variables have certain protection from the name collisions with other scoping constructs, plus variable binding is happening there too. Variable binding is a process of associating a variable name with some value (obtained through expression destructuring for rules). For scoping constructs like Module, With, Block, Function, we have a good deal of control over the variable binding since we may override the Hold*-attributes of these constructs, writing something like x=y;Function[Evaluate[x],y^2]. For rules, the variable binding is happening inside the pattern-matcher, and is not as controllable. Normally, you don't think much about how the binding is happening, either because there is no ambiguity, or because the name conflict resolution semantics is spelled out in the docs or elsewhere (for example, there is a generic rule that for name conflicts in nested lexical scoping constructs, inner bindings are favored).

For the case at hand, you are at the mercy of the variable-binding mechanism of rules, and the way it interacts with the pattern-matcher. One fact (don't know documented or not) about the pattern - matcher is that it attempts matches left to right when given a pattern build with Alternatives. From common sense, we should expect that the variable binding is happening after the match, and therefore your construct is fine. However, this is digging into internals over which we have no control. It may be, that there would be no other logically - consistent way for the pattern - matcher / binding mechanism to behave, or it may be otherwise.

As I said, this by itself is not necessarily bad - we often rely on some undocumented behavior if we have empirical evidence for a feature, and this feature allows us to do something non-trivial easily. My main objection of the construction is its obscurity - it is plain harder to read than the code using two separate rules (for me anyway).




回答2:


When you switch the message off and afterwards on again, you write 3 lines to use your pattern. If you want to express that f should take the first element if it's given one list and take all elements if it's given more than one parameter, what's wrong with

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

which is still one line less to write?


But to give an opinion about your pattern: The problem I see here is

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

Out[6]= {1}

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

This would be kind of unexpected and maybe hard to debug. Using two definitions with different patterns does the job right:

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}


来源:https://stackoverflow.com/questions/8374056/is-it-safe-to-turn-off-patternpatv

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!