Reputation: 155
I have issues with functions that operate in place with MatLab. I've also read Loren's blog on in-place operation on MatLab, and the example there is a bit lacking. First, let me show you a function:
% a method of my_class < handle
function obj = ip_find(obj, value)
if value == obj.value
return
elseif value < obj.value
if isa(obj.left, 'Node')
obj = ip_find(obj.left, value);
else
obj = nan;
end
else
% similar to above
end
end
The function ip_find
is an in-place operation that works as intended (to specify, ip_find
is a method of my_class < handle
, and returns a my_class
object). Here is what I mean: suppose that the I'm looking for data1
using ip_find()
, and I set x=ip_find(arg)
. If I then modify x
, then data1
is also modified, x
is not only a copy of data1
.
Now please take a look at this function below (priv_delete
works as intended, set
is a method of matlab.mixin.SetGet
):
function delete23(obj, value)
[left, right] = neighbours(obj, value);
lvalue=nan;rvalue=nan;
if isa(left, 'Node_augmented')
lvalue = left.value;
end
if isa(right, 'Node_augmented')
rvalue = right.value;
end
% priv_delete works as intended, the issue is not here
obj.root = priv_delete(obj.root, value);
if ~isnan(lvalue)
lnode = ip_find(obj.root, lvalue);
if ~isnan(rvalue)
rnode = ip_find(obj.root, rvalue);
set(lnode, 'suc', rnode); % <---- issue
else % then right is nan
set(lnode, 'suc', nan); % <---- issue
end
end
if ~isnan(rvalue)
% similar to above
end
end
The issue is with the lines where I invoke set
. It appears to be that I'm operating on a copy of the data, instead of directly on the data. Thus my tests fail, as I only modified the copies! I'm not sure what is wrong, I can't seem to find the bug. I have thought of using pointers but MatLab does not even support it.
Upvotes: 1
Views: 95
Reputation: 60443
I think you confuse the concept of “in place operation” (a function that modifies its input directly, instead of copying it first), and “handle object” (an object that points at data, so that when it’s copied, the copy points at the same data).
Where you do
set(lnode, 'suc', rnode);
you modify lnode
, which is a local variable. You don’t write this variable to anywhere else, so at the end of the function your modified object will be deleted. Unless lnode
is a handle object, in which case, by modifying it, you modify some global value somewhere that is also referenced by other local variables.
In MATLAB, everything is passed by value. You should always think of variables inside your function as containing copies to the data passed in. Sometimes these values are handles to data elsewhere, in which case it’ll appear as if the variable was passed by reference, but in effect you passed a copy of the handle.
A handle object is an instantiation of a handle class, a user-defined class that inherits from handle
. All copies of such an object point to the same data (in effect share data), so modifying one copy will modify all other copies as well.
You can write a function that does in-place modifications to its input by making the output variable name the same as an input variable name, only modifying that variable (rather than assigning a new value to it), and calling this function with the same variable as input and output. For example:
v = ones(10);
v = f(v);
function x = f(x)
x(1) = 0;
end
What this does is skip the copy of the matrix v
, which would otherwise be made inside a function that modifies its inputs. In this case the copy can be avoided because the original matrix won’t exist any more after the function call. So the in-place operation is an optimization of the interpreter, not a language feature. The final result would be identical if a copy were made (which is in fact what happened with that code prior to 2015 or whenever this optimization was introduced).
Upvotes: 4