Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a 'self' to refer own struct in MATLAB?

I'm grouping a set of anonymous functions into a structure and some variables within that structure. Is there a way to refer 'self', i.e, own structure? What I'd like to accomplish is to have a function returns some values based on the member variables. For simplicity, say I have a struct a, where

a.value_1 = 3;
a.value_2 = 2;
a.sum = @()(self.value_1 + self.value_2)

Is there something like that possible in MATLAB?

like image 638
radarhead Avatar asked Aug 12 '13 14:08

radarhead


2 Answers

Before objected-oriented programming was introduced in MATLAB (including both classdef-style and the obsolete @-directory style classes), one could create lightweight objects using closures and nested functions (lacking inheritance of course). This concept also exists in other languages.

Here is an example:

function s = mystruct()
    s = struct('value_1',[], 'value_2',2, 'sum',@mysum);
    s.value_1 = 3;

    function out = mysum()
        out = s.value_1 + s.value_2;
    end
end

Which is used as:

>> s = mystruct()
s = 
    value_1: 3
    value_2: 2
        sum: @mystruct/mysum
>> s.value_1 = 10;     % NOTE: this wont do what you expect!
>> s.sum()
ans =
     5

Note that variables are immediately captured when creating a closure (functions have their own private copy if you will). So if you change one of the exposed fields from the returned structure, it will not be reflected in the enclosed state (think of them as read-only properties).

One solution is to provide accessor methods:

function obj = mystruct()
    % think of those as private properties
    value_1 = 3;
    value_2 = 2;

    % returned object (this or self)
    obj = struct();

    % public accessors for properties
    obj.value_1 = @accessValue1;
    function out = accessValue1(in)
        if nargin > 0, value_1 = in; end
        out = value_1;
    end
    obj.value_2 = @accessValue2;
    function out = accessValue2(in)
        if nargin > 0, value_2 = in; end
        out = value_2;
    end

    % member method
    obj.sum = @mysum;
    function out = mysum()
        out = value_1 + value_2;
    end
end

So now we could say:

>> s = mystruct()
s = 
    value_1: @mystruct/accessValue1
    value_2: @mystruct/accessValue1
        sum: @mystruct/mysum
>> x = s.value_1();   % get
>> s.value_1(10);     % set
>> s.sum()
ans =
    12

Which is starting to look like the current recommended approach to create classes:

classdef mystruct < handle
    properties
        value_1 = 3;
        value_2 = 2;
    end
    methods
        function out = sum(obj)
            out = obj.value_1 + obj.value_2;
        end
    end
end

Used in a similar manner:

>> s = mystruct()
s = 
  mystruct with properties:

    value_1: 3
    value_2: 2
>> s.value_1 = 10;
>> s.sum
ans =
    12

We could also define get/set access methods as before..

like image 123
Amro Avatar answered Oct 30 '22 01:10

Amro


This seems to work but I think you should rather create a class than a struct to do this:

a.value_1 = 3;
a.value_2 = 2;

a.sum = @(x)(x.value_1 + x.value_2)

a.sum(a)
like image 35
Dan Avatar answered Oct 30 '22 01:10

Dan