3

Lots of people bump into unexpected shallow copy behavior when they start off in Python, and I'd like to make sure I don't make any of those mistakes in MATLAB (with which I have less experience).

I read this article about object behaviors in MATLAB and I read this question that pertains to pointer/handle behavior. Are there any situations where isa(obj, 'handle') would return false but you would still encounter the situation where modification of obj would result in the modification of another variable (to my knowledge, any argument modification by a function call should trigger a copy on write and duplicate the variable in memory)?

Is this a complete understanding of "shallow copy"-like behavior in MATLAB? Are there any additional caveats to standard value object copy behavior?

1 Answers1

3

A value class can contain a handle class, and if you modify it you will change the instance of the handle class. For example (note that containers.Map is a built-in class that is a handle - nothing special about it, I just chose it for convenience:

>> a = containers.Map; a('hello') = 1;
>> b = struct('field1', 1, 'field2', a);
>> isa(b, 'handle')
ans =
  logical
   0
>> b.field2('hello') = 2;
>> a('hello')
ans =
     2

So b is a struct (which has value semantics), but one of its fields contains a containers.Map, which is a handle and has reference semantics. When you modify that field, you also change a, which is another reference to the underlying containers.Map.

Sam Roberts
  • 23,951
  • 1
  • 40
  • 64
  • Excellent answer. I hadn't considered that edge case at all. I really appreciate the code demonstration of the specific questions asked – Peter Barrett Bryan Jan 18 '18 at 13:31
  • 2
    Glad my answer helped. It's not really an edge case though - it's an example of a more general issue. `b` needn't have been a struct - it could have been a cell array with `a` as an element, or an instance of a value class with `a` as a property. It could have been a function handle that had captured `a` in its workspace, and so on. And `a` may have been hidden several levels deep within `b`. – Sam Roberts Jan 18 '18 at 13:58
  • 1
    Though in this case `isa(b.field2, 'handle')` returns true. So you can always know in advance that this would happen. – Cris Luengo Jan 18 '18 at 16:18
  • @CrisLuengo That's true in the case where `b` is a struct and the handle is stored as a field, but it's not always possible - for example, if the handle was stored in a private property of a value class `b`. The handle could be modified by a method of `b`, causing other references to it to change, but you'd have no access to the handle in order to verify it in the way you're describing. – Sam Roberts Jan 18 '18 at 23:08
  • @SamRoberts: Hum, that's interesting. And surprising. I guess you're right about that. – Cris Luengo Jan 19 '18 at 00:28