# Pick bug? level 0 matching

A previous discussion of this issue (Is there a bug in Pick?) accepted that matching at level 0 is not a bug in Pick. Was that correct? I am not yet persuaded.

Here is the documentation (http://reference.wolfram.com/language/ref/Pick.html): "Pick[list,sel,patt] picks out those elements of list for which the corresponding element of sel matches patt."

This clearly speaks of corresponding elements. It seems to me that either there is a documentation bug or there is an implementation bug. Why am I wrong? Furthermore, the documentation gives the obvious statement of intent, so I suspect an implementation bug.

Here is (yet) another example that illustrates how bizarrely unexpected is the current behavior:

x = Range[20]
Pick[x, x/2, _Integer]  (* works as expected *)
Pick[x, x/2, Except[_Integer]]  (* does not work as expected *)


I find it almost impossible to believe that Pick was intended to cause this simple use of Except to fail by matching the entire list x/2 rather than, as the documentation states, checking for a match in the corresponding element.

Note that I am not asking how to get the intended match; I realize that Except[_Integer|_List] will accomplish that in this case. Also, I am using Mma 9.

Quite often the documentation is not complete in describing the behavior of Mathematica functions. In my opinion a user has to accept in vivo behavior as at least co-authoritative with the documentation. I know this causes consternation for those who want a rigorous language definition but as far as I know from the beginning we have never been provided with one.

A number of functions that are only documented as working on lists also work on arbitrary expressions. Pick actually does have (limited) documentation unlike these.

The heads in list and sel do not have to be List.

The function summary given at the top of the documentation page and the ::usage message is not a complete description of the function and often is arguably not entirely correct. I believe that simple language is chosen over technical precision for these summaries. In this case:

This is restated more technically in the Details section of the documentation:

It directly follows from this more technical description that heads may be included as they are accessed with expr[[0]]:

a = foo[1, 2, 3]; b = bar[4, 5, 6];

a[[0]]

b[[0]]

Pick[a, b, bar]

foo

bar

foo[]


Consider then this example:

a[[All]]

b[[All]]

Pick[a, b, Except[4]]

foo[1, 2, 3]

bar[4, 5, 6]

foo[1, 2, 3]


This also agrees with the technical description. The remaining issue is whether (effectively) All should be included in the list of parts considered. The documentation does not state. I feel that one must return to the "in vivo behavior" and a bit of guesswork here. Because outer expressions are checked before inner ones it appears that Pick is a rare function that uses depth-first pre-order traversal. Its scan is then most similar to ReplaceAll which of course (effectively) includes All in its search. This isn't clearly documented but then again the traversal of ReplaceAll isn't fully documented either and that is a foundational operator in Mathematica. Once again we seem to be left with a choice between ignorance and in vivo experimentation; I choose the latter.

I think your real problem is the "definition of correct": the only reference for Mathematica (or the "Wolfram language") is the documentation, and that is in many cases somewhat vague. So for every behavior that is not in a clear conflict with the documentation you basically have to accept what you get. The level 0 matching of Pick might be a corner case but I'm not convinced that the documentation is really in an obvious conflict with the behavior. I'm quite sure that WRI won't see this as an error but you could try and see what support will answer when you send a bug report. I guess you'll have to live with it the way it is, but maybe they'll improve the documentation :-)...

Pick works in a multiple forms and there are many workarounds for the problem.

x = Range[20];

Pick[x, x, _?EvenQ] ==
Pick[x, x, _?(EvenQ[#] &)] ==
Pick[x, x/2, _Integer] ==
Pick[x, x/2, _?IntegerQ] ==
Pick[x, x/2, _?(IntegerQ[#] &)] ==
Pick[x, IntegerQ /@ (x/2)] ==
Cases[x, _?EvenQ] ==
Cases[x, _?(EvenQ[#] &)] ==
Select[x, EvenQ] ==
Select[x, EvenQ[#] &] ==
DeleteCases[x, _?OddQ] ==
DeleteCases[x, _?(OddQ[#] &)] ==
Range[2, 20, 2]


True

Pick[x, x, _?OddQ] ==
Pick[x, x, _?(OddQ[#] &)] ==
Pick[x, x/2, _Rational] ==
Pick[x, (Head[#] === Rational) & /@ (x/2)] ==
Pick[x, (! IntegerQ[#]) & /@ (x/2)] ==
Cases[x, _?OddQ] ==
Cases[x, _?(OddQ[#] &)] ==
Select[x, OddQ] ==
Select[x, OddQ[#] &] ==
DeleteCases[x, _?EvenQ] ==
DeleteCases[x, _?(EvenQ[#] &)] ==
Range[1, 19, 2]


True

• The OP explicitly states that workarounds are not sought, rather an explanation of Pick and whether its behavior is intended and sensible. – Michael E2 Sep 9 '14 at 17:42