How to avoid recursion with parenReference

4 views (last 30 days)
Using Matlab 2021B version
I create a class which inherits both handel & matlab.mixin.indexing.RedefinesParen.
classdef Abc <handle & matlab.mixin.indexing.RedefinesParen
I create object arrays using this class.
I want to overload the parenthesis for the class so that it can perform special handling in addition to indexing into the object array ( normal operation ).
For example
Abc('special') - performs special handling
Abc(2:3) - down selects only objects 2 to 3 (normal operation without RedefinesParen)
I have written the parenReference function as follows
function varargout = parenReference(obj,indexOp)
if isscalar(indexOp)
varargout{1} = obj(indexOp(1).Indices);
% Other special handling and forward indexing
The problem is that no matter how I try to select the subset of objects to return in the third line, it calls parenReference recusively and faults when recursion limit is reached. I have even tried
varargout{1} = builtin('subsref',obj,substruct('()',indexOp(1).Indices))
How do I select a subset of obj in this function without it being called recursively.

Accepted Answer

Matt J
Matt J on 1 Nov 2021
Edited: Matt J on 1 Nov 2021
Classic subsref doesn't seem to difficult in this case. You can't beat the classics!
function varargout = susbref(obj,S)
if S(1).type~="()"
[varargout{1:nargout}] = builtin('subsref',obj,S); return
if isscalar(S.subs) && isscalar(S.subs{1})
out = obj(S(1).subs{1});
% Other special handling and forward indexing
[varargout{1:nargout}] = builtin('subsref',out,T);
Mike Falcinelli
Mike Falcinelli on 2 Nov 2021
Okay - I have discarded Redefines Dot also and am using subsref & subsasgn. In this case, they are pretty simple and not execution time critical.
I had moved to the RedefinesDot because previously ( 2 to 3 years ago) I tried the subsref/subsasgn route for another application. I found it cumbersome and slow because I had to implement much of the built-in functionality. I liked the ease and simplicity of the RedefinesDot, and it added almost no overhead cost in terms of execution time for 'buit-in' capability.

Sign in to comment.

More Answers (1)

Shanmukha Voggu
Shanmukha Voggu on 28 Oct 2021
Hi Mike,
The recursion limit is reached because the parenReference is calling itself recursively,
The solution is to create a property that holds the given array in the class Abc
properties (Access=private)
And in the constructor of class Abc assign the given array to the property above
function obj = Abc(arr)
obj.copyOfArray = arr;
Now you can use indexing on the property to get the desired results, Instead of using below statement in parenReference function
varargout{1} = obj(indexOp(1).Indices);
use the following statements
obj.CopyOfArray = obj.CopyOfArray.(indexOp(1));
varargout{1} = obj; %if you want output as object array, or use obj.copyOfArray in order to have array alone as output
Refer this for more information.
James Lebak
James Lebak on 5 Nov 2021
Edited: James Lebak on 5 Nov 2021
I want to offer reassurance that in our experience with using the modular indexing APIs internally, we haven't found recursion to be a big problem. The APIs don't currently do everything that subsref and subsasgn can, but I would hate to see you avoid them just because of the potential to encounter this problem.
It's true that it's easy to write code that encounters the recursion, and we did see developers new to the API write this code. In the case that RedefinesParen is primarily designed for, the scalar that presents itself as an array, we also found it to be a relatively easy problem to avoid, and to be easily uncovered by simple testing.
We are currently moving several MathWorks classes from subsref and subsasgn to modular indexing and in our production test system, we haven't encountered failures due to modular indexing classes unexpectedly calling overloaded indexing recursively.

Sign in to comment.




Community Treasure Hunt

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

Start Hunting!