1
$\begingroup$

Position returns lists of numbers consumed by Extract, ReplacePart and others as "positions" in arbitrarily complex forms. This works great: Position[x+f[x],x] --> {{1}, {2, 1}}, 2 matches, each of which can be fed to Extract[x+f[x],{1}] --> x and to ReplacePart[x+f[x],{2,1}->y] -->x+f[y].

However, there seems to be a hiccup when matching the whole input expression. Position[x+f[x],x+f[x]] --> {{}}. This is documented behavior: "A part specification {} returned by Position represents the whole of expr."

But... Extract[x+f[x],{}] --> {}, which seems clearly wrong (there isn't an empty list anywhere in x+f[x]). Interestingly, Extract[x + f[x], {{}}] --> {x + f[x]} works; this is the "extract a list of positions" syntax. But this breaks the easy connection between Position and Extract without using an awkward "ask for a list of one then take the first answer" work-around.

Even worse, ReplacePart[x + f[x], {} -> y] --> x + f[x], i.e. no replacement, while ReplacePart[x + f[x], {{}} -> y] --> y -- ReplacePart seems to want a special {{}} form for the whole. (Note that this isn't ReplacePart's multiple-value syntax, which also doesn't work: ReplacePart[x + f[x], {{} -> y}] --> x + f[x], and so there's no easy work-around to make this work here.

So... what's going on here? Both Extract and ReplaceParts are documented to use Position's output, but neither does when it comes to the whole. Is there a principled approach to take? (Right now, I'm just special-casing this, but that seems utterly unsatisfying...)

Thanks -- perry

$\endgroup$
1
  • $\begingroup$ Welcome to Mathematica.SE! I hope you will become a regular contributor. To get started, 1) take the introductory tour now, 2) when you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge, 3) remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign, and 4) give help too, by answering questions in your areas of expertise. $\endgroup$
    – bbgodfrey
    Commented Oct 31, 2021 at 4:03

1 Answer 1

1
$\begingroup$

Position returns lists of numbers consumed by Extract, ReplacePart and others as "positions" in arbitrarily complex forms.

True

This works great Position[x+f[x],x] --> {{1}, {2, 1}}, 2 matches, each of which can be fed to Extract[x+f[x],{1}] --> x and to ReplacePart[x+f[x],{2,1}->y] -->x+f[y].

Yes, it works great. Extract and Position are fully compatible, but you don't use Extract in this compatible way. The compatibility is effective when you insert the whole result of Position in Extract (as opposed of taking each element of the result in turn):

Extract[x + f[x], Position[x + f[x], x]]  

{x, x}

What you call the "work-around" later is the normal use of Extract. By "normal" I mean the more general one, the one that resists corner cases (in particular the case "get the whole initial expression"). The use of contructions like Extract[x + f[x], 2] is a shorthand for First[Extract[x + f[x], {{2}}]], a form that is too long and too complicated for such a simple action.

So for extracting the whole expression, use this :

positions = Position[x + f[x], x + f[x]]
First[Extract[x + f[x], positions]]  

x + f[x]

In the same manner, in your example Extract[x + f[x], {}], {} should be interpreted as the list of the elements to extract, ie nothing. It is the "normal" interpetation of Extract I mention above (as opposed to the shorthand interpetation).

$\endgroup$
6
  • $\begingroup$ Extract[h[a, b], {}] and Extract[h[a, b], {{}}] are documented in the documentation of Extract (/Possibles Issues) $\endgroup$
    – andre314
    Commented Oct 31, 2021 at 7:44
  • $\begingroup$ Maybe I should replace the word "normal" by something else ("generalised"?) $\endgroup$
    – andre314
    Commented Oct 31, 2021 at 7:59
  • $\begingroup$ Andre, I need to pick the list-of-matches returned by Position apart and process each match individually (by mapping over it), and each individual process needs to extract "its" value. Your suggested Extract[expr, Position[expr, pattern]] syntax always returns all matched values, discarding the position I need for processing, so it's insufficient for my purposes. $\endgroup$ Commented Oct 31, 2021 at 18:16
  • $\begingroup$ Ah. More reading. So both Extract and ReplacePart have an "Issues" entry explaining that {{}} denotes the whole. It looks like my confusion is actually with Position: Position[2 x,_] --> {{0}, {1}, {2}, {}}. This is a list of matches, one of which is {}, as documented under Position: a single empty list. Yet Extract/ReplacePart expect a nested list to denote the whole. So how are they (naturally) compatible? $\endgroup$ Commented Oct 31, 2021 at 18:51
  • $\begingroup$ Yes, Position returns a list of matches. If you want to extract the expression corresponding to the lastest match (the whole original expression), do something like that : exp = 2 x; positions = Position[exp, _]; First[Extract[exp, {positions[[4]]}]]. There are many ways to do that, but nothing shortert than adding a level of {} and remove it at end. You may find this not natural, but it"s the only way to be compatible with the corner cases. $\endgroup$
    – andre314
    Commented Oct 31, 2021 at 22:50

Not the answer you're looking for? Browse other questions tagged or ask your own question.