MATLAB Answers

subsref overload has fewer outputs than expected on cell attribute

3 views (last 30 days)
Nath on 28 Dec 2012
Edited: per isakson on 14 Sep 2016
I am overloading subsref in a class (reason is out topic here). Say for simplicity that my subsref should have the same behaviour as the builtin subsref in everycase. So I simply wrap a call to the builtin. But when using instance.some_cell{:}, where some_cell is a cell attribute, only the first element of the instance.some_cell is returned by my subsref.
In the following exemple, you can see a if bloc in subsref. Its only purpose is to pick the proper nargout size. The debugger shows me that varargout is of correct size (ie 3) right before my subsref returns. However, once my subsref is done, I only receive the first cell element oustide !!!
instance= exemple_subsrf_oncell({1,2,3});
instance.some_cell{:} %WEIRD returns only 1
I know numel isn't involved here, because some_cell is of a builtin type. I wonder how I should define subsref so that it returns me the proper number of outputs when using expression like instance.some_cell{:} I wish to let matlab find the proper nargout alone (the uggly if block in subsref is just a stupid attempt to solve the problem).
exemple class code
classdef exemple_subsrf_oncell < handle
some_cell= {};
function self= exemple_numel(cn)
self.some_cell= cn;
function varargout= subsref(self,idx)
if isequalwithequalnans(idx(end),substruct('{}',{':'}))
varargout= cell(1,length(self.some_cell));
varargout= cell(1,1);
[varargout{:}]= builtin('subsref',self,idx);
Thank you very much for your attention


Sign in to comment.

Accepted Answer

Matt J
Matt J on 28 Dec 2012
Edited: Matt J on 4 Jan 2013
Sadly, it's a known and old problem with subsref overloading. You cannot overload the syntax obj.prop{:}. Since the issue has been around for at least 7 years, my guess is it's buried too deep in the MATLAB source code to ever be fixed.
You can, of course, do things like this as a workaround,
Incidentally, it is a numel issue ( EDIT: or rather an issue in the way nargout interacts with numel). For user-defined classes, MATLAB's default numel for expressions obj.prop will always return 1. Overloading numel can't fix this, because dot-indexing expressions won't invoke the overloaded NUMEL method.


Show 2 older comments
Nath on 4 Jan 2013
Crystal clear now. Thank you very much. Isn't there a way to patch the BUILTIN numel ?
Sean de Wolski
Sean de Wolski on 4 Jan 2013
@Nath, overload it for the class of your choice:
e.g. in an @cell folder, numel.m
Matt J
Matt J on 4 Jan 2013
Isn't there a way to patch the BUILTIN numel ?
The only people who control the built-in NUMEL are TMW software engineers. As I said, if it were easy to fix, they would have done so 7 years ago. I'm actually no longer certain the bug is in NUMEL. I think it might be in NARGOUT. Specifically, NARGOUT will call NUMEL or it may not depending on the indexing syntax. It makes no difference, though. We don't have a way to overload NARGOUT either, as far as I can see.
Overloading NUMEL can't help because, as my example showed, there are situations when NUMEL overloads are ignored by NARGOUT.

Sign in to comment.

More Answers (1)

Daniel Shub
Daniel Shub on 4 Jan 2013
I am not following everything ... The two commands instance.some_cell and instance.some_cell{:} mean different things. See an old question of mine about cell array expansion. That said, I am not sure if you want them to return. It sounds like you want them to return the same thing. If that is the case, then add
if isequalwithequalnans(idx(end),substruct('{}',{':'}))
varargout = {varargout};
to your subsref. It is not obvious to me how to overload subsref so it behaves like the built-in. For example, it seems overloading subsref to give the following behavior is difficult.
instance.some_cell = {1,2,3};


Nath on 8 Mar 2013
As you said, they are different things and I dont want them returning the same value, as to for instance cell concatenation : {instance.some_cell,1} and {instance.some_cell{:},1} are definitely not the same
Nath on 8 Mar 2013
The only (very heavy!) workaround I can think of would be to implement some cell-like class and have every cell attribute wrapped with this user cell class

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!