How to assign to a collection of object properties stored in an object array, using a numerical array of compatible type and size (one statement, without for-loop!)?

3 views (last 30 days)
I am building a minimal discrete-event simulation support, where sequences of events will be initialized from external weather records (of precipitation, for example). Class EventList_MWE (subscript '_MWE' denoting 'minimum working example') implements the DEVS list using a circular array (buffer) of events of base class MySimEvent, from which I derive user-specific event classes and methods, such as DerivedSimEvent. To handle polymorphic events, MySimEvent inherits from the class matlab.mixin.Heterogeneous.
The event list class is an aggregation of an object array of MySimEvent objects (objArray) and has further properties, but is not inherited from an array class. The constructor EventListExp(N) initializes the buffer with N events with undefined (NaN) properties:
objArray(1:N) = MySimEvent().
Events are currently Value, not Handle, class objects; and event properties are kept public to be accessible from EventListExp.
The error occurs in my method EventListExp.ArrayInit(obj, T, ID), which initializes a subset of events using as input the arrays T and ID:
[obj.objArray(IndexSet).tstmp] = T(1:nI);
Error: Insufficient number of outputs from right hand side of equal sign to satisfy assignment.
IndexSet is an array of valid indices of the same size as T(1:nI) (in my example: 10); both arrays are double-typed.
I also tried subsasgn function and defined a “substruct” structure argument, but I do not yet overload / override the function:
subs = substruct('.','objArray', '()',{IndexSet}, '.','tstmp');
obj = subsasgn(obj, subs, T(1:nI));
Error: Expected one output from a curly brace or dot indexing expression, but there were 10 results.
Questions: Isn't the property collection (array) enclosed in square brackets '[]' a valid target for an assignment (i.e. a vallid left-hand-side)? Do I wrongly use subsasgn for indexing, or must I overwrite subsasgn (in which class?)? Or is my approach pointless, since no performance will ever be gained compared to iterating event constructor calls?
rng('shuffle');
N = 25;
DEVS_List_Test = EventList_MWE(N);
for i=1:10
DEVS_List_Test.InsertEvent(randi(10,1), i, 1, rand());
end
T = rand(1,N);
ID = randi(100,1,N);
DEVS_List_Test.ArrayInit(T, ID);
Insufficient number of outputs from right hand side of equal sign to satisfy assignment.

Error in EventList_MWE/ArrayInit (line 27)
[obj.objArray(IndexSet).tstmp] = T(1:nI);

Accepted Answer

Jeffrey Clark
Jeffrey Clark on 21 Sep 2022
Edited: Jeffrey Clark on 21 Sep 2022
@Peter, without getting into your specific code I suspect that [obj.objArray(IndexSet).tstmp] = T(1:nI) is incorrect in that the tstmp should be indexed not the objArray: obj.objArray.tstmp(IndexSet) = T(1:nI) (note that the brackets are only needed on the assignment side when expecting individual outputs). However after getting it to run with minor changes to your test program this is what it should be changed to use deal since you are expecting multiple outputs:
% Fix in EventList_MWE
[obj.objArray(IndexSet).tstmp] = deal(T(1:nI));
[obj.objArray(IndexSet).evid] = deal(ID(1:nI));
[obj.objArray(IndexSet).evtype] = deal(ones(1,nI));
% Fix in TestSimEvent_MWE
T = rand(1,DEVS_List_Test.N);
ID = randi(100,1,DEVS_List_Test.N);
Also, a subsasgn override in a base or derrived class is only needed if you are trying to change the default behaviour of indexing on the assignment size. See exampe in my Utility package: Utility package containing NoGrow for fixed size arrays - File Exchange - MATLAB Central (mathworks.com)
  6 Comments
Jeffrey Clark
Jeffrey Clark on 23 Sep 2022
@Peter, with the test code you provided (except changing to rng(0) to compare runs) this code seems to give the same results whether mat2cell or num2cell is used. I've made this more robust and am going to put it in my utilites for future needs; I don't know why/what problem you are seeing with num2cell:
function varargout = mat2csl(varargin)
if nargin==nargout
varargout = varargin;
elseif nargin~=1
throwAsCaller(MException('MATLAB:maxrhs','Too many input arguments.'))
elseif numel(varargin{1})==1
[varargout(1:nargout)] = deal(varargin);
elseif numel(varargin{1})==nargout
varargout = num2cell(varargin{1});
% varargout = mat2cell(varargin{1},ones(size(varargin{1},1),1),ones(1,size(varargin{1},2)));
elseif numel(varargin{1})<nargout
throwAsCaller(MException('MATLAB:maxlhs','Too many output arguments.'))
else
throwAsCaller(MException('MATLAB:minlhs','Too few output arguments.'))
end
end

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!