1

I am working with some code that uses values from an enumeration class (extending uint8) to access matrix columns "by name" rather than by a hard-coded number. The reason for this approach is that matrices are perceived as more performant compared to other constructs that allow named field access (such as structs/object or tables) - which supposedly improves code readability without sacrificing performance.

The trouble is that the enum class is found inside a package, giving it a rather long name. This hurts readability quite significantly to the point it almost defeats the purpose of "named indices":

% What it looks like without using an enum:
val = foo(:, 7); % Magic number, :(

% Current situation (the enum is called "somePackage.SomeMeaningfulCollectionEnum"):
val = foo(:, somePackage.SomeMeaningfulCollectionEnum.varName1); % Very long name, :(

% Desired solution:
E = somePackage.SomeMeaningfulCollectionEnum; % This throws an error in R2020a
val = foo(:, E.varName1); % Short and descriptive!

When attempting to use the "desired solution" above, we get the following error:

Error using somePackage.SomeMeaningfulCollectionEnum
Cannot call the constructor of 'somePackage.SomeMeaningfulCollectionEnum' outside of its enumeration block.

I have come up with a workaround consisting of storing each enumeration member in a struct field with the same name (see my own answer below), but I'm wondering if there's a "proper" way to do this.

Dev-iL
  • 23,742
  • 7
  • 57
  • 99

2 Answers2

1

One option is to create a struct whose fields are the individual enumeration members:

E = enumeration('somePackage.SomeMeaningfulCollectionEnum'); % Get all enumeration members
E = [cellstr(E), num2cell(E)].'; % Prepares name-value pairs for `struct` creation
E = struct(E{:});

Then E is effectively a type-alias for somePackage.SomeMeaningfulCollectionEnum, and can be accessed as desired.

See also: enumeration.

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
  • Interesting approach. Is this actually faster than using a `table`? I know `table` is quite slow, but it's still worth comparing IMO. – Cris Luengo May 04 '20 at 15:16
  • @Cris adding to your comment: TMW published in a [recent blog post](https://blogs.mathworks.com/loren/2020/04/30/faster-indexing-in-tables-datetime-arrays-and-other-data-types/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+mathworks%2Floren+%28Loren+on+the+Art+of+MATLAB%29) that they optimized tables in R2019b-R2020a, so yeah, this definitely should be benchmarked. – Dev-iL May 04 '20 at 17:55
1

One alternative you could consider is to not use an enumeration but a normal class with immutable properties. somePackage.SomeMeaningfulCollectionEnum would be:

classdef SomeMeaningfulCollectionEnum
   properties (Constant)
      col1 = 1
      col2 = 2
      col3 = 3
   end
end

Then you can do:

E = somePackage.SomeMeaningfulCollectionEnum;
val = foo(:, E.col1);

The other approach I was thinking of is using functions (which are traditionally used in MATLAB to define constants), but I can't get that be pretty either. The best approach I found is simply a function that returns the same struct created in the OP's solution:

function out = SomeMeaningfulCollectionEnum
out = struct('col1',1,'col2',2,'col3',3);

Now again you can do:

E = somePackage.SomeMeaningfulCollectionEnum;
val = foo(:, E.col1);
Cris Luengo
  • 55,762
  • 10
  • 62
  • 120