8
$\begingroup$

For reasons I won't go into here, I became curious about the what would happen should I make a query that applies PreIncrement to one key in a list of associations. I admit that it could be argued that PreIncrement should not be used in this way. In fact, because PreIncrement is HoldFirst and expects a symbol bound to a value, I was rather expecting Mathematica to complain about what I was about to do. I couldn't see how Mathematica was going to find such a symbol in the situation I was setting up.

The list of associations I will use is

assocs = {<|"a" -> 1, "b" -> 3|>, <|"a" -> 2, "b" -> 2|>, <|"a" -> 3, "b" -> 1|>};

and the query I will make is

Query[All, "b", PreIncrement] @ assocs

The first evaluation.

result = Query[All, "b", PreIncrement] @ assocs; {result, assocs}
{{4, 3, 2}, 
 {<|"a" -> 1, "b" -> 3|>, <|"a" -> 2, "b" -> 2|>, <|"a" -> 3, "b" -> 1|>}}

Surprise. No complaints from Mathematica and the result seems reasonable. Now I'll do it a couple of more times.

result = Query[All, "b", PreIncrement] @ assocs; {result, assocs}
{{5, 4, 3}, 
 {<|"a" -> 1, "b" -> 3|>, <|"a" -> 2, "b" -> 2|>, <|"a" -> 3, "b" -> 1|>}}
result = Query[All, "b", PreIncrement] @ assocs; {result, assocs}
{{6, 5, 4}, 
 {<|"a" -> 1, "b" -> 3|>, <|"a" -> 2, "b" -> 2|>, <|"a" -> 3, "b" -> 1|>}}

This is very strange. I expected result to have the same value after each evaluation. Since none of the associations in assocs is modified by the query, what is PreIncrement actually incrementing?

$\endgroup$
  • $\begingroup$ For what it's worth ++assocs[[All, "b"]] appears to work correctly. $\endgroup$ – Mr.Wizard May 21 '17 at 19:11
  • $\begingroup$ @Mr.Wizard. That's a good observation, but everyone should understand that your code in no way involves the Query mechanism. The behavior you report is a simple effect of the associations in assocs being destructively modified, so there is no mystery about where the incremented values are coming from. $\endgroup$ – m_goldberg May 21 '17 at 19:48
  • $\begingroup$ Right, I just meant that: (1) for some purposes it is a solution (2) the fact that it works as desired but Query does not makes me think that the latter is a bug. $\endgroup$ – Mr.Wizard May 21 '17 at 19:52
  • $\begingroup$ @Mr.Wizard. I have updated the question's title to make clear that Query is a big part of the issue. As to Slice not being in a state of grace, I feel nervous about the way it's implemented. 1) Should it memoize? This thread seems to show that doing so can be dangerous (at least to anybody expecting functional behavior). 2) Can a function that depends on another function called Internal`UnsafeQuietCheckever be fully trusted? $\endgroup$ – m_goldberg May 21 '17 at 20:08
8
$\begingroup$

The 2nd example given under Query > Properties & Relations tells us

Before being applied, Query expressions are "compiled" into ordinary compositions of ordinary Wolfram Language functions and their operator forms. To see the compiled form of a Query, use Normal.

That seems like a good line of exploration. Let's see where it leads.

Query[All, "b", PreIncrement] // Normal
Map[GeneralUtilities`Slice["b"] /* PreIncrement]

And, yes, that function can be used in place of the query I've been using.

Map[GeneralUtilities`Slice["b"] /* PreIncrement] @ assocs

{7, 6, 5}

Let's try for more information.

?? GeneralUtilities`Slice

info

Satori. GeneralUtilities`Slice is doing memoization. The queries do not extract values from assocs except when the first evaluation of Query is done.

This could cause real trouble. It would be good to have a way to remove the memoization. The following will work for this particular example.

SubValues @ GeneralUtilities`Slice = 
    DeleteCases[SubValues @ GeneralUtilities`Slice, RuleDelayed[_, _Integer]]

The behavior reported in the question also applies to Increment, Decrement, PreDecrement and to the use of all such operators with data sets.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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