Coming from other languages, I find MATLAB's flagrant copy behavior to
be surprising, and very slow. However, it is an interesting choice.

The ! convention specifically declares that a function mutates an
input. Since this is a violation of the previously stated assumption
of many function that the inputs will not be changed, the convention
helps to keep the user aware of the effect of these functions.
However, it should be noted that a.b = x and a[b] = x are also muting
operations in this same class (but without the visible !).

Julia does not allow += to operate inplace for the reason you described

To write fast code, I think programmers have reached an informal
consensus that a function should not modify it's inputs, leading to
the optimization that the function can also expect that its inputs
will remain unmodified. This helps to make functions more easily
composable (since a function only changes data it just created). If
the user wants to modify the inputs later, the user is expected to
make a copy.

Some languages make everything immutable to enforce this convention.
This is cool from a pure CS standpoint. However, Julia does not do
this since it forces a very different way of writing many common
algorithms.

Note, that I will tend to explicitly call out functions that make
copies in their documentation (copy, unsafe_ref, bytestring come to
mind). My default assumption is that the inputs are shared by the
output of the function, and should no longer be mutated.

On Thu, Apr 24, 2014 at 12:04 AM, Ethan Anderes <ethanande...@gmail.com> wrote:
> Hi Tobias:
>
> My 'hard to find bug' statement should really have read 'hard to find bug 
> from a newbie perspective'. These bugs would be obvious to someone familiar 
> with basic programming. My numpy example is too big to give now but here is a 
> simple metropolis hasting markov chain short example:
>
> theta_curr = 0.0
> for k=1:10_000
>         theta_prop = theta_curr
>         theta_prop += randperturbation()
>         likelihoodratio = computelr(theta_prop, theta_curr)
>         if rand() < minimum([1,likelihoodratio])
>                 theta_curr = theta_prop
>         else
>                 theta_curr = theta_curr
>         end
> end
>
> The variable theta_prop is only supposed to be set to theta_curr if the first 
> conditional is true. I guess in python += acts inplace, so that line 3 
> actually changes theta_curr, which would be a bug. In my numpy excursion, 
> once I realized this (after many more lines of code) my stomach turned and I 
> suddenly decided I didn't know what the heck I was doing and ended up running 
> back to safe matlab. I had a similar feeling with vec(a) where after learning 
> the output was the same as input I suddenly had to review all my code that 
> used vec(a) to make sure I wasn't spuriously fusing variables. The thing 
> about Julia that I like is that I could start out reasoning about code 
> immediately (if I avoided functions with ! at the end) and then slowly 
> venture into the more modern techniques....but the point is I was 
> scientifically productive immediate without knowing much about programing.
>
> I definitely agree that the suffix "!" works well. In fact I like it so much 
> I was just hoping that there would be something similar to indicate when 
> output shared input member. I was thinking there would be reshape(A,dims), 
> reshape!(A,dims) and reshape*(A,dims) where reshape(A,dims) returned a copy, 
> reshape!(A,dims) mutated A and reshape*(A,dims) left the arguments alone but 
> returned a variable which shared memory with A. Anyway, that suggestion now 
> seems silly after hearing Tim say that there are really only corner, easy to 
> understand, cases where I need to worry about it.
>
> Again, thanks all for the discussion!
> Ethan

Reply via email to