Main Content

numArgumentsFromSubscript

Number of arguments for customized indexing based on subsref and subsasgn

Description

This function supports customized indexing for classes that implement subsref and subsasgn. For classes authored in R2021b and later, the recommended process to customize indexing is to inherit from some combination of matlab.mixin.indexing.RedefinesParen, matlab.mixin.indexing.RedefinesDot, and matlab.mixin.indexing.RedefinesBrace. The equivalent function for calculating the number of arguments for this type of indexing is listLength. For more information, see Customize Object Indexing.

example

n = numArgumentsFromSubscript(obj,s,indexingContext) returns the number of expected inputs to subsasgn or the number of expected outputs from subsref.

Overload numArgumentsFromSubscript to describe the number of values to return from indexing expressions that return or assign to a comma-separated list. That is, indexing expressions that end in '{}' or '.' indexing. The numArgumentsFromSubscript function can:

  • Access the indexing operations and indices used in the indexing expression.

  • Determine if an indexing operation is made in the context of a reference statement, an expression passed to a function, or an assignment.

If a class overloads numArgumentsFromSubscript, MATLAB® calls it to determine the number of array elements involved in an indexing operation when the number of elements is greater than one. For example, these '.' indexing operations generate a call to numArgumentsFromSubscript:

  • objArray.a — Number of elements referenced in a statement (Statement)

  • func(objArray.a) — Number of elements returned in an expression (Expression)

  • [objArray.a] = rhs — Number of values assigned with a comma-separated list (Assignment)

MATLAB uses the calling context to determine when to apply the value returned by numArgumentsFromSubscript. Your implementation of numArgumentsFromSubscript can provide different outputs for the three types of indexing statements. For example, this overload of numArgumentsFromSubscript:

  • Changes the expected number of output arguments from subsref for indexing expressions that are passed to functions.

  • Uses the indexing substructure s to determine the number of arguments required by the indexing operation

function n = numArgumentsFromSubscript(obj,s,indexingContext)
   if indexingContext == matlab.mixin.util.IndexingContext.Expression
      n = 1;
   else
      n = length(s(1).subs{:});
   end
end

Implement the subsref method with a varargout output to enable MATLAB to call this method with the specified number of output arguments.

function varargout = subsref(obj,s)
   ...
end

Examples

collapse all

Use words as indices for object properties.

By default, MATLAB treats each character in a character array as a separate element. Therefore, MATLAB interprets a character array index as multiple index values.

Without overloading numArgumentsFromSubscript, keyword indexing statements request too many arguments for subsref and subsasgn methods. To implement indexing that uses character arrays as a single keyword, define a numArgumentsFromSubscript method to return 1 as the number of elements referenced or assigned.

Overload numArgumentsFromSubscript to support the following kinds of indexed reference and assignment.

Index reference with character array:

obj{'keyword'}

Index reference in function argument:

func(obj{'keyword'})

Assign comma-separated list to object array:

[obj{'keyword'}] = right-side values;

In these cases, subsref and subsasgn cannot determine the number of required output and input arguments, respectively, from the calling context. Provide this information using the numArgumentsFromSubscript function.

Define the KeyIndex class with two properties. KeyCell stores key names. DataArray stores corresponding data. To customize indexing:

  • Implement a subsref method that returns the data values that correspond to the specified keyword.

  • Implement a subsasgn method that assigns the specified values to the corresponding element in DataArray properties.

  • Overload numArgumentsFromSubscript to return a value of 1 or scalar objects and a value of numel(objArray) for object arrays.

Specify a cell array containing the names of months for the KeyCell property. Specify a numeric array of the snow fall for the corresponding months in the DataArray property.

snow15 = KeyIndex({'Jan','Feb','March'},[36 42 2])
snow15 = 

  KeyIndex with properties:

      KeyCell: {'Jan'  'Feb'  'March'}
    DataArray: [36 42 2]

Reference the snow amount for a particular month using the keyword:

snow15{'Feb'}
ans =

    42

Assign to the corresponding element using '{}' indexing with the keyword:

snow15{'Feb'} = 52;

The value corresponding to the key 'Feb' changes:

snow15{'Feb'}
ans =

    52

Create an array with the snow fall for 2 years:

snow14 = KeyIndex({'Jan','Feb','March'},[12 8 2]);
sTotal = [snow14,snow15];

Show the snow fall for both years for February:

sTotal{'Feb'}
ans =

     8


ans =

    52

Update the values of snow fall for both years for the month of February. Indexing into a cell array returns a comma-separated list:

c{1} = 34;
c{2} = 56;
[sTotal{'Feb'}] = c{:};

Here is the KeyIndex class. This class shows a particular programming technique. It does not include error checking and other features that your class can require.

classdef KeyIndex
   properties
      KeyCell
      DataArray
   end
   methods
      function obj = KeyIndex(key,data)
         if nargin > 0
            obj.KeyCell = key;
            obj.DataArray = data;
         end
      end
      function n = numArgumentsFromSubscript(obj,~,~)
         n = numel(obj);
      end
      function varargout = subsref(obj,s)
         a = numel(obj);
         switch s(1).type
            case '{}'
               varargout = cell(1,a);
               for j = 1:a
                  for k = 1:numel(obj(j).KeyCell)
                     if strcmp(s.subs(:),obj(j).KeyCell{k})
                        varargout{j} = obj(j).DataArray(k);
                     end
                  end
               end
            case '.'
               varargout = {builtin('subsref',obj,s)};
            case '()'
               varargout = {builtin('subsref',obj,s)};
         end
      end
      function obj = subsasgn(obj,s,varargin)
         a = numel(varargin);
         switch s(1).type
            case '{}'
               for j = 1:a
                  for k = 1:numel(obj(j).KeyCell)
                     if strcmp(s.subs(:),obj(j).KeyCell{k})
                        obj(j).DataArray(k) = varargin{j};
                     end
                  end
               end
            case '.'
               obj = builtin('subsasgn',obj,s,varargin{:});
            case '()'
               obj = builtin('subsasgn',obj,s,varargin{:});
         end
      end
   end
end

Define a class that supports per-element and per-array indexing for properties.

The numArgumentsFromSubscript function enables classes to customize references to specific properties. The indexing substructure argument (s) to numArgumentsFromSubscript contains the name of the property referenced in a dot indexing expression (that is, a reference of the form obj.PropertyName). Using the indexing substructure, numArgumentsFromSubscript can return a unique value for any given property.

The PerArray class uses the information in the indexing substructure to specify the number of outputs for each property reference.

Overload numArgumentsFromSubscript to return:

  • A comma-separated list of values for the ByElement property, one value per array element

  • A single value for the ByArray property for the entire array

Create an array of PerArray objects:

for k = 1:4
   pa(k) = PerArray(rand(k));
end

Query the ByElement property to return a comma-separated list of property values:

pa.ByElement
ans =

    0.7513


ans =

    0.2551    0.6991
    0.5060    0.8909


ans =

    0.9593    0.1493    0.2543
    0.5472    0.2575    0.8143
    0.1386    0.8407    0.2435


ans =

    0.9293    0.6160    0.5853    0.7572
    0.3500    0.4733    0.5497    0.7537
    0.1966    0.3517    0.9172    0.3804
    0.2511    0.8308    0.2858    0.5678

Query the ByArray property to return a single value for the array:

pa.ByArray
ans =

    3.1416

Here is the PerArray class. This class shows a particular programming technique. It does not include error checking and other features that your class can require.

classdef PerArray
   properties
      ByElement
   end
   properties (Constant)
      ByArray = pi;
   end
   methods
      function obj = PerArray(be)
         if nargin > 0
            obj.ByElement = be;
         end
      end
      function n = numArgumentsFromSubscript(obj,s,indexingContext)
         import matlab.mixin.util.IndexingContext
         if (indexingContext ~= IndexingContext.Assignment)
            if length(s) < 2
               switch (s.subs(:)')
                  case 'ByElement'
                     n = numel(obj);
                  case 'ByArray'
                     if strcmp(s(1).type,'.')
                        n = 1;
                     end
               end
            elseif length(s) > 1
               n = length([s(1).subs{:}]);
            end
         end
      end
      function varargout = subsref(obj,s)
         
         switch s(1).type
            case '.'
               varargout = cell(1,numel(obj));
               for k = 1:numel(obj)
                  varargout{k} = obj(k).(s.subs(:));
               end
            case '()'
               if length([s(1).subs{:}]) > 1
                  ind = [s(1).subs{:}];
                  numInd = length(ind);
                  varargout = cell(1,numInd);
                  for k = 1:numInd
                     varargout{k} = obj(ind(k)).(s(2).subs(:));
                  end
               else
                  varargout = {builtin('subsref',obj,s)};
               end
         end
      end
   end
end

Input Arguments

collapse all

Object of overloading class used in the indexing operation. The class of this object determines which subsref or subsasgn method MATLAB calls as a result of an indexing operation.

Indexing structure or array of indexing structures containing information about the specific indexing expression. Each structure has two fields:

  • type — Indexing expression can be '()', '{}', '.'

  • subs — Subscript values (property name or cell array of index numbers)

Data Types: struct

Context in which result applies, specified as one of these enumerations:

  • matlab.mixin.util.IndexingContext.Statement — Indexed reference used as a statement (obj.a)

  • matlab.mixin.util.IndexingContext.Expression — Indexed reference used as an argument to a function (func(obj.a))

  • matlab.mixin.util.IndexingContext.Assignment — Indexed assignment ([obj.a] = x).

Output Arguments

collapse all

Number of arguments returned by overloaded subsref or passed to overloaded subsasgn. Overload numArgumentsFromSubscript to return the values required by your class for various indexing scenarios.

Tips

  • Overload numArgumentsFromSubscript instead of numel to control the results from overloaded subsref and subsasgn. Overloading numArgumentsFromSubscript can avoid errors caused by overloading numel.

Version History

Introduced in R2015b