AyamGorengPedes
AyamGorengPedes

Reputation: 155

MatLab can't modify data in place

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

Answers (1)

Cris Luengo
Cris Luengo

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

Related Questions