Three years ago, almost to the day, I wrote about a very handy undocumented feature of Matlab classes that enables us to specify type restrictions for any Matlab class property. We can specify property type (for example,
double or any Matlab class) as well as dimensionality (
matrix) and complexity indication (
complex). Doing so has multiple benefits for code performance, robustness and maintainability. For example:
% Undocumented syntax - works well since at least R2010a (possibly earlier) classdef Packet properties PacketType@char HeaderLength@uint16 PayloadLength@uint16 scalar = uint16(0); % initial value PacketData@uint8 vector end end
In the recent release of Matlab R2016a, a similar feature have finally become fully supported and documented. The corresponding snippet above would look something like this:
% Documented syntax - only works in R2016a or newer classdef Packet properties PacketType char HeaderLength uint16 PayloadLength uint16 = uint16(0); % initial value PacketData uint8 end end
Unfortunately, I dislike the new documented functionality, so I didn’t feel like promoting it in this blog when it came out. But since a blog reader mentioned it a few days ago, I wanted to come out publicly with my opinion and a detailed explanation.
If you look closely at the code snippets above, you will notice two important differences:
- The “@” symbol was replaced with a space
- The dimensionality and complexity cannot be specified
The new syntax has some drawbacks compared to the previous (undocumented) one:
- Backward compatibility – We can run the older (undocumented) syntax on any Matlab release since who-knows-when (at least as far back as R2010a [tested], and possibly older releases [untested]), including the very latest R2016a. On the other hand, the new (documented) syntax will only work on R2016a and will crash the program if you try to run it in older releases. This is not even something that you can catch with a try-catch block – the class will simply not load on any older Matlab release. If you need your code to run on older releases in addition to 16a, you have no choice other than to use the older syntax.
- Dimensionality – the new syntax, unlike the undocumented syntax, does not enable users to limit the data dimensionality (scalar/vector/array). This is a very important feature for program robustness and maintainability. Complexity is another type limitation that is missing, although it is less important than the dimensionality. And just in case you were wondering – the new syntax does not accept the additional
complexattributes like the older syntax; using them with the new syntax evokes an error.
- Cross compatibility – it is very confusing to users coming to Matlab from other programming languages, all of which (without any important exception) place the type name to the LEFT of the identifier name, not to its RIGHT. People coding in both Matlab and Java/C/C++ would easily get confused and frustrated.
- Consistency – despite what I hoped, the new syntax still does not apply to function input args: we cannot (AFAIK) limit the input/output args of methods/functions in the same way that we can limit properties. If there’s a way to do this, I’d be delighted to learn (this comment may indicate that it is work in progress). It is true that this feature is not a drawback of the new syntax compared to the older one, since the old syntax didn’t have it either (AFAIK). But I would have expected a documented feature to be consistent across the Matlab language (or at least across the MCOS subset), and unfortunately the new feature fails this test.
In fact, aside from the fact that the new syntax is documented, I can see no advantages that it offers over the older syntax, only disadvantages. Or am I missing something? Please do tell if you see any important advantages that I’ve missed.
Luckily for us, the old syntax remains operational, side-by-side with the new one. This enables us to keep running our existing code without worrying [too much] that it might break in R2016a. Maybe the new syntax will grow on me (or improve) in upcoming years, but for the time being I see no benefit in switching away from the @ syntax.
For the past few years, I hoped that the property typing feature will become documented and that it will be a continuation of the undocumented syntax rather than what eventually aired. I’m afraid it’s too late to revert it now that it has… Realistically speaking, the best we can hope for now is for the older syntax to remain operational, and not be withdrawn in some future Matlab release. Making the undocumented syntax documented as-is would be great, but I’m afraid it is unrealistic given the new circumstances.
I’m sorry if I take the wind off MathWorks’ sails a bit here, but MathWorks knows that it can count on me to speak my mind without bullshit. Sometimes for the good, sometimes not. All in good spirit and the common interest of improving Matlab over time. No offence intended – it’s just my personal opinion after all.
In my opinion this is one of those rare cases where the developers obviously intended to make something better but eventually came out with something worse. They should have stuck to what was. After all, the first and foremost rule of engineering is, and always was:
@Yair – Addressing your “In fact, aside from the fact that the new syntax is documented, I can see no advantages that it offers over the older syntax, only disadvantages. Or am I missing something? Please do tell if you see any important advantages that I’ve missed.”
Some may see it as an advantage, but I think the following is making things even worse. In addition to different syntax there is also different semantics of the old (undocumented) and new property type declarations. Assuming
objis an instance of a class with the following
there is this interesting behavior:
This means the new syntax automatically converts to the declared type, if possible. (To be fair, this is documented.) The old syntax is more strict and throws an error on type mismatch, something I find much more desirable.
The following transcript reveals the difference in internal representation:
This also means that writing
NewStyle@char propertyis equivalent to
NewStyle charand will give the new behavior using the old syntax. All of this feels pretty convoluted and like you I fail to see the benefit of creating yet another syntax instead of documenting (and extending) the old syntax that has existed for a long time.
Isn’t inputParser a solution to the function input typecheck issue (kludgy and convoluted, but functional)?