3

Consider the following code:

list={1,2}
MemberQ[list, x_ /; (x == #)] & /@ list

This gives {True,True}

MemberQ[list,form] means that an element of List matches form,

But how does mathematica know what to put for the pattern x_?

Asked differently, I view the above MemberQ as doing the following:

  • MemberQ is a pure function as input above
  • Map (/@) applies list to the MemberQ (pure) function
    • This means that Map evaluates MemberQ with each element of list in place of #
  • What part of the code tells mathematica what to use for the named pattern x_??. (in other words, how does mathematica know what $x$ is when checking x==# is true or not)

I thought maybe Map was applying the list elements to both # and x_, but

f[x_, #] & /@ {5}

gives {f[x_,5]}


Edit: An example of where this construct is potentially relevant: This answer


Edit 2: I think maybe this is what is happen:

First let us look at MemberQ[list,x_]. This will give True For (almost?) list. What is this doing? This is saying does list match the form of Pattern[x,Blank[]]. Well, Pattern[x,Blank[]], is just any expression, so yes list matches.

Now let us consider MemberQ[list,x_/;(x==#)]. This is asking whether list matches patterns that are an expression AND have (x==#). Well, if # is an expression, it will match (the condition will be satisfied), and since we are doing /@list, we are asking if expressions of the form in list match elements in list, which is true.

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
majmun
  • 207
  • 1
  • 6

2 Answers2

1

It is applying the test to each element of the list. Consider this:

list = {1, 2}
MemberQ[list, x_ /; (x + # == 4)] & /@ list

{False, True}

When x and # are both 2 the x_ pattern as 2 is tested in MemberQ. Otherwise the x_ pattern is False. I.e. MemberQ[list, False] which in turn yields False.

In the case of your code

MemberQ[list, x_ /; (x == #)] & /@ list

it seems unlikely the test would ever yield False, but then again strange cases can be produced:

list = {a = 1, Unevaluated[1 + a]};
MemberQ[list, x_ /; (x == #)] & /@ list

{True, False}

I.e. The x pattern remains unevaluated while # evaluates in the map, so

Unevaluated[1 + a] == 2 tests False and then MemberQ does too.

Finally,

The constructions in the "potentially relevant" answer you mention are these:

MemberQ[{1, 2, 3}, _?(# == 2 &)]

and

MemberQ[{1, 2, 3}, x_ /; x == 2]

both of which are equivalent, and evaluate to True. Your actual case is like the latter, with a pure function # added for the map.

MemberQ[{1, 2, 3}, x_ /; x == #] & /@ {2, 4}

{True, False}

Chris Degnen
  • 30,927
  • 2
  • 54
  • 108
  • But why are x and # being taken to be the same? I realize that x_ stands for any expression, and we call it x, but when I look at the code It looks to me like it needs to be told two things: what is the expression x_, and what is #. Obviously this is not the case – majmun Jan 29 '20 at 22:58
  • 1
    Using the x_ pattern just facilitates a test on #, so it is testing itself. And its value is each item in list, taken in turn. – Chris Degnen Jan 29 '20 at 23:02
1

I think perhaps you are seeking or misunderstanding the function of /; which is shorthand for Condition. You write: "how does mathematica know what x is when checking x==# is true or not." The value bound to the pattern x_ is substituted into the right hand side of /; where x appears, in the manner of rules or function definitions.

Compare:

f[x_] := Print[something[x]]

f /@ {1, 2, 3}

MemberQ[{1, 2, 3}, x_ /; Print[something[x]]]

Cases[{1, 2, 3}, x_ :> Print[something[x]]]

These all print:

something1

something[2]

something[3]


Preserved for reference, you wrote:

I will try rephrasing: what is "the value bound to the pattern" in the 3rd and 4th lines of your code? I look at the second line and I see map that says "hey, apply {1,2,3} to f. But in lines 3 and 4 I don't see what part of the commands binds a value to x (I understand that the value bound to x is substituted in the right hand side, but I don't understand why (in your lines 3 and 4) 1,2, and 3 are being bound to x)

Both MemberQ and Cases have an implicit levelspec(1) of {1}, as does Map. Writing these out in explicit form:

MemberQ[{1, 2, 3}, x_ /; Print[x], {1}];
Cases[{1, 2, 3}, x_ :> Print[x], {1}];
Map[Print, {1, 2, 3}, {1}];

A different levelspec can be used for each, e.g. {0, 1} to include the complete expression:

MemberQ[{1, 2, 3}, x_ /; Print[x], {0, 1}];
Cases[{1, 2, 3}, x_ :> Print[x], {0, 1}];
Map[Print, {1, 2, 3}, {0, 1}];

Each function also supports the Heads option.

Observe that List in List[1, 2, 3] is itself a level one component:

MemberQ[{1, 2, 3}, x_ /; Print[x], {1}, Heads -> True];
Cases[{1, 2, 3}, x_ :> Print[x], {1}, Heads -> True];
Map[Print, {1, 2, 3}, {1}, Heads -> True];

(Printing omitted throughout to avoid cluttering this post.)

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • I will try rephrasing: what is "the value bound to the pattern" in the 3rd and 4th lines of your code? I look at the second line and I see map that says "hey, apply {1,2,3} to f. But in lines 3 and 4 I don't see what part of the commands binds a value to x (I understand that the value bound to x is substituted in the right hand side, but I don't understand why (in your lines 3 and 4) 1,2, and 3 are being bound to x) – majmun Jan 31 '20 at 07:49
  • @majmun Got it! :-) – Mr.Wizard Jan 31 '20 at 14:57