After thinking about it some more, I understand now why the .+=
case is more difficult than the .=
case, although I think it could be supported with a little more effort. The idea is that
a += x
expands to
a = a + x
and the a
is duplicated onto both left and right hand sides. This cannot be an issue because for the standard =
operator, the only kinds of expressions a
for which this makes sense are names, fields, and ref
s. For each of these, the operation of “setting” is a fundamentally different operation than “getting”.
In the case of
A .= x
considerably greater flexibility is available for the left-hand side A
, and indeed this can take on any value that can normally be on the right hand side without issue. (Except, perhaps, as a special case values like A[x:y]
are rewritten to be views, because otherwise the behaviour of modifying a newly-allocated object and then throwing away the result is nonsensical and error-prone. This seems to be the case on 0.5 at least; I don’t know if it has been changed in 0.6.)
In the case of
A .+= x
it is expanded to
A .= A .+ x
and it is here that A
is restricted to being something simple. Suppose it were not; then we might have
somefunction(A) .= somefunction(A) .+ x
and the somefunction
would be called twice, perhaps expensive, and perhaps with additional unwanted side effects. Instead this would need to be expanded to
let tmp = somefunction(A)
tmp .= tmp .+ x
end
which is not currently supported by the update operator expander.
Hence, if my understanding is correct, it is not a semantic reason that @views(A[x:y]) .+= x
is not allowed, but instead simply that the code to do it properly has not been written yet, so it is prohibited. Since alternatives like @views
exist, presumably this is a low priority and unlikely to make it into 0.6.
Does this sound right?