Search code examples
matlabequalityfunction-handle

Transform equal function handles to other equal function handles


Minimalistic Example:

classdef MyClass
properties
    arr
    handArr
end
properties(Dependent)
    rowAcc
    colAcc
end
methods
    function obj = MyClass(arr, handRow, handCol)
        obj.arr = arr;
        obj.handArr{1} = handRow;
        if ~isequal(handRow, handCol)
            obj.handArr{2} = handCol;
        end
    end
    function r = get.rowAcc(obj)
        r = obj.handArr{1}(obj.arr);
    end
    function c = get.colAcc(obj)
        c = obj.handArr{end}(obj.arr);
    end
end
end

Now assume I pass equal functions to the constructor, I want the row and col access would also be the same:

f=@(x)@(y) y;
x=MyClass(1, f, f);
isequal(x.rowAcc, x.colAcc) //should be 1

Is this possible?

I have a good reason for this 'insane' requirement:

I have several algorithms which run with 100+ MBs of input and takes those two functions as input, and when they are equal they can be optimized very efficiently; to call the algorithms I need to make transformations to the input functions which are encapsulated inside this class. I can't change the algorithms (not my code) and they use isequal on they're own functions to dispatch.


Solution

  • Two variables pointing to the same anonymous function are considered to be equal

    f = @(x)x;
    g = f;
    
    isequal(f, g)
    %   1
    

    However, if you define the anonymous functions at different times, then they are not considered to be equal because the internal workspaces of the two functions could differ.

    f = @(x)x;
    g = @(x)x;
    
    isequal(f, g)
    %   0
    

    In order to have your property return equal handles, you could have some "shadow" property (accessors_) which caches the accessors and you update these cached values whenever the arr property is changed.

    classdef MyClass
    
        properties
            arr
            handArr
        end
    
        properties (Access = 'protected')
            accessors_      % An array of accessor functions for rows & columns
        end
    
        properties (Dependent)
            rowAcc
            colAcc
        end
    
        methods
            function set.arr(obj, value)
                % Set the value
                obj.arr = value;
    
                % Update the accessors_
                self.accessors_ = obj.handArr{1}(obj.arr);
    
                % Only assign another accessor if we have a second one
                if numel(obj.handArr) > 1
                    self.accessors_(2) = obj.handArr{2}(obj.arr);
                end
            end
    
            function res = get.rowAcc(obj)
                res = obj.accessors_(1);
            end
    
            function res = get.colAcc(obj)
                % If only one was stored, this will return a duplicate of it
                res = obj.accessors_(end);
            end
        end
    end
    

    This also has the added benefit that you aren't creating function handles every time that colAcc and rowAcc are retrieved.