3
$\begingroup$

I expected 3 from both of these

j = 2; new = {1, 1, 1, 1, 1}; new[[++j]] += 2; j
j = 2; new = {1, 1, 1, 1, 1}; new[[++j]] = 2; j

4
3

Why does the first one return 4?

$\endgroup$
2
  • $\begingroup$ Mathematica is not a programming language like C. It is a system for rewriting expressions. Some rewrites imitate conventional procedural programming constructs, but be wary. Usually, there are better ways to do what you want. $\endgroup$
    – John Doty
    Jul 21, 2018 at 18:41
  • $\begingroup$ Note that your first line of code increments the 4th element of list, not the 3rd. $\endgroup$
    – m_goldberg
    Jul 22, 2018 at 3:17

1 Answer 1

5
$\begingroup$

That's really a nasty one. I don't think that it is supposed to work this way, but apparently,

new[[++j]] += 2

is equivalent to

new[[++j]] = new[[++j]] + 2

That's why ++j gets executed twice.

I am not sure, but maybe AddTo is implemented as follows:

SetAttributes[addto, HoldFirst];
addto[a_, b_] := a = a + b;

Since the first argument is held, new[[++j]] is evaluated twice under execution of addto[new[[++j]],2].

$\endgroup$
2
  • $\begingroup$ Both AddTo and PreIncrement have the attribute HoldFirst $\endgroup$
    – Bob Hanlon
    Jul 21, 2018 at 21:00
  • $\begingroup$ My uncertainty about the implementation was more about the true internals than about the fact that AddTo has that attribute. In principle, the held expression could be analyzed for occurences of Part and this behavior could be prevented by enforcing that the second arguments of Part get evaluated only once. $\endgroup$ Jul 21, 2018 at 21:11

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