User-defined classes and support for '{}' type linear indexing.

Dear all,
I overloaded subsref() and subsasgn() in a class that I built and I seem unable to reproduce the behavior that built-in types/classes, typically cell/struct arrays, have when linearly indexed with {} (this generalizes to any case of linear/mixed indexing with n subs on cell arrays with more than n dimensions). Here are a few tests to illustrate:
>> a = {3, 4} ;
>> a{:} % Comma separated list of elements
ans = % (cells content).
3
ans =
4
>> S = substruct( '{}', {':'} ) ; % Build S struct array.
>> subsref( a, S ) % Call class cell subsref().
ans = 3
>> builtin( 'subsref', a, S ) % Same, just in case.
ans = 3
>> b = a{:} % Single LHS => only first RHS saved.
b = 3
>> ans = a{:} % Special behavior with ans? No.
ans = 3
>> c = cell( numel(a), 1 ) ; % Matching LHS, RHS when we know
>> [c{:}] = a{:} % a priori the size of the block
c = % targeted by the sub.
[3]
[4]
>> ans, ans = a{1}, a{2} % Hand-made comma separated list
ans = % when we know a priori the size
3 % of the block targeted by the sub.
ans =
4
>> ans, ans = subsref( a, S ) % Even for built-ins, subsref()
ans = % outputs at most a cell array.
4 % <- this is the previous ans
ans = % <- this is the output of subsref()
3 % So a{:} is not managed by subsref(),
% but transformed into
% ans, ans = a{1}, a{2}
% by the interpreter that is able to
% manage linear indexing with {} for
% built-in classes only??
It seems to me that managing a{:} is not or cannot be done at the subsref() level as the method must output a cell array (varargout) and cannot output a comma separated list. Then, the way I understand the behavior above when using the syntax a{:}, is that the interpreter checks whether "a" is an instance of a built-in type/class (typ. cell and struct array), and if so is able to compute a priori the number of elements of a{:} and evaluate the following
ans, ans = a{1}, a{2}
If I am not too wrong, it is therefore not possible to build user-defined classes that are treated the same way by the interpreter (that cannot know a priori the size of the block being indexed)?, .. unless there is a way to tell MATLAB that instances of this user-defined class behave like built-ins, or some numel()-like method call including subs, that we could manage with an overload? What did I understand/misunderstand?
Thank you and best regards,
Cedric
(R2011b, 64-bit)

2 Commenti

Am I correct that this is only an issue with cell arrays? Are you basically trying to create a user defined cell array class?
Cedric
Cedric il 10 Gen 2013
Modificato: Cedric il 10 Gen 2013
Daniel, you are correct. It is specific to managing indexing that is interpreted as something that should "generate" a comma separated list. I am creating a class that generalizes "arrays", and that should behave like cell arrays when built based on @cell.

Accedi per commentare.

 Risposta accettata

Matt J
Matt J il 10 Gen 2013
Modificato: Matt J il 10 Gen 2013
If you supply an overloaded numel() method then the problem should go away, as long as you're just trying to imitate cell arrays.
However, there are definitely limitations in overloading comma-separated lists when you use more deeply nested indexing. See this related thread for an expanded discussion

5 Commenti

Cedric
Cedric il 10 Gen 2013
Modificato: Cedric il 10 Gen 2013
Matt, it seems though that if x = MyClass(), then x.numel() is never called when MATLAB interprets x{:}. I implemented the test.. but I might have done this wrong.
Your example is not clear. You claim to have overloaded subsref, so the behavior of the indexing expression x.numel() is dictated by whatever your subsref method is doing. Below is an example of a class that successfully overloads a{:}
>> a=myclass({3,4,5}); a{:}
ans =
3
ans =
4
ans =
5
classdef myclass
properties
subcell
end
methods
function obj=myclass(subcell)
obj.subcell=subcell;
end
function varargout = subsref(obj,S)
[varargout{1:nargout}] = builtin('subsref',obj.subcell,S);
end
function N=numel(obj,varargin)
N=numel(obj.subcell,varargin{:});
end
end
Thank you VERY much! I must have made a mistake when I tested the overload of numel(). Now it is working perfectly!
Cedric
I'm glad it's working, though I urge you to read the link I gave you so that you're apprised of some of the general limitations of of {:} overloading.
I had found your question from 2009 with no answer before I wrote mine, but not the 2012 thread, which I fully read before updating my code. Thank you again!

Accedi per commentare.

Più risposte (0)

Categorie

Prodotti

Community Treasure Hunt

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

Start Hunting!

Translated by