Matlab Strict Mode?
Show older comments
Can we please have a "strict mode" in Matlab, which does not guess what you mean, but instead does things consistently? Take this example:
x = (3:7)';
size(x([1; 2; 2; 3; 3; 4])) % 6 x 1
size(x([1 2; 2 3; 3 4])) % 3 x 2
size(x([1 2 2; 3 3 4])) % 2 x 3
size(x([1 2 2 3 3 4])) % 6 x 1 !?!?
Just to be clear: if Matlab were consistent, the last result would be 1x6.
Code that runs on arbitrary input data, annoyingly, needs endless if-then blocks to compensate for Matlab's horrendous inconsistencies, making it slow to develop, cluttered, slow to run, and just a pain in general.
I understand Mathworks is probably not keen on breaking everybody's code in one language update.
But perhaps a simple "strict mode" (somewhat akin to Javascript's "use strict" directive at the top of files and functions) could trigger a consistent dimensions mode, and in general provide a more mature interpretation of the programming language?
9 Comments
per isakson
on 11 Oct 2016
I fail to find this way of indexing in the R2016b on-line documentation. It's not in Matrix Indexing(?). My first question is whether the behavior agrees with the documentation.
Steven Lord
on 11 Oct 2016
This behavior is documented, although it's not called out very clearly. "If you index into a vector with another vector, the orientation of the indexed vector is honored for the output" in the Nonconsecutive Elements subsection of the Accessing Multiple Elements section on that documentation page.
In the first case where Paul indexes into x, the orientation of the index vector matches the orientation of x. In the second and third cases the index array is not a vector so its size and shape is respected. In the last case, the index vector is of a different orientation than the vector into which Paul is indexing, so the orientation of x wins.
per isakson
on 11 Oct 2016
Thanks Steven, my bad; I missed that.
Here is another example. M(:) is well described one the same page, but not M(1:end)(?)
>> M = magic(3);
>> M(1:end)
ans =
8 3 4 1 5 9 6 7 2
>> M(:)
ans =
8
3
4
1
5
9
6
7
2
>>
per isakson
on 12 Oct 2016
Edited: per isakson
on 12 Oct 2016
By and large, I agree regarding your description of the problem. Nevertheless, I'm using Matlab. And I think the Mathworks is aware and indeed regard it as a problem.
I don't think "strict mode" is going to happen, partly because of the difficulties to define "consistent". (Maybe, the Mathworks has already considered it. We cannot know.)
Philip Borghesani
on 9 Dec 2016
Edited: Philip Borghesani
on 9 Dec 2016
One other thought here: Don't think of 1:end as an indexing operation here. The code is syntactically equivalent to idx=1:numel(M); M(idx) and therefor follows the general rules mentioned by Steve. Note also the output of M((1:end)')
John D'Errico
on 9 Dec 2016
"So my proposal was that we could have a declaration in the source files to trigger a mode with consistent interpretation of the language. Say, in a comment on the first line of an .m file and/or on the first line of a function.
Would such a feature ever be seriously considered?"
Answer: NO. It will simply not happen, as much as you might want it. There is a huge heritage of code that has been in existence for many years. People use those old tools still. In fact, I have tools that are now approaching 30 years in age, and still run. (Although I think most of the people who were there to use those codes back then are now retired.)
Mode changes as you suggest will cause those old codes to fail. One thing that I have seen over the years is when changes are made (even for good reasons) many people seem highly resistant. They don't want to go back and verify their old codes, then making any repairs to cover necessary language changes.
The answer is just to learn the language. Any language will have some things that you perceive to be inconsistent. English is a bad one of course, but there are still many people who use it, despite those flaws.
Kevin
on 19 Apr 2017
I don't understand your objections, John. An opt-in "strict mode" doesn't have to break old code. Other languages do this successfully with something like a 'use strict' pragma at the top of source files.
If you don't want old code to break, or don't want to take responsibility for cleaning up old code that relies on ambiguous language features, then don't enable strict mode.
As a relative newcomer, I find it beyond frustrating when MATLAB allows me to clobber essential built-in functions like 'dist' or 'cluster' with no warnings, and then I get warnings like "Subscript indices must either be real positive integers or logicals" when I try to run the actual functions later on.
Sure, OK, that's a mistake I only have to make once or twice before I remember not to name variables 'dist' or 'cluster', but is "just learn the language"—all those hundreds of built-in functions, plus those from any toolboxes you have loaded—a good answer for your new users in this case? Answer: NO. And flagging weird, ambiguous, or bad language behavior (or keeping the user from shooting themself in the foot) is exactly what "strict" modes are supposed to do.
Walter Roberson
on 19 Apr 2017
A question comes up as to whether the effects of the strict pragma would carry through into routines that are called. If so then it is likely that deeper down calls would break. If not, then you might have to put the strict pragma in for each routine, which could be tedious. Perhaps it would be workable to "scope" such a pragma -- e.g., have it before the first "function" line if it is to apply to the file as a whole.
Answers (1)
A "strict mode" would not even break old code, but even the idea behind Matlab to allow to users to perform matrix operations conveniently. The complete "operate on the first non-singelton dimension" is not-strict:
m = mean(X)
s = sum(X)
without specifying the dimension to operate on. If X is a [nMeasuremenmts x nChannel] matrix and the number of measurements can be 1, the results may differ from the intention. What should happen with such commands in "strict" mode?
What about:
AxesH = axes;
plot(y)
This is a racing condition: when the use clicks in another figure after the axes command, but before the plot, the diagram appears in the wrong figure. "Strict" would be:
plot(y, 'Parent', AxesH)
Or perhaps: plot(AxesH, y)? No! Because this can fail in older Matlab versions, where the axes handles was a double and might (or should!) be misinterpreted as the x coordinate.
You find many such details, which allows users to be intentionally lazy. But this convenient programming style is prone to bugs in productive code. To write "strict" code, a strict-flag will not help, but only to specify each an every detail explicitely. This will and must slow down the code, but there is no way to let Matlab guess strictly, what the user wants to get. Finally the code is not slow, when you compare it with an equivalently flexible implementation in another porgramming language.
The problem of shadowing builtin functions is severe. Matlab should show a warning in such cases, and as far as I remeber this happens sometimes. I use FEX: UniqueFuncNames to check ambiguities, but this considers the toolboxes of my local Matlab installation only. When my code runs in a different Matlab version or installation, different problems can appear. But this is not specific to Matlab, but it can happen in other languages also - including the languages spoken by humen.
Summary: Matlab saves the users from shooting in their knees very well already (compare it to C :-) ) and its tries to guess smartly the users intention is sometimes not sufficient. If you want to restrict the behavior of Matlab, you cannot let Matlab guess in a "strict" mode, what it should not guess smartly, but you have to write strict code manually:
x = (3:7)';
index = [1 2 2 3 3 4];
result = reshape(x(index), size(index));
This is fast, clear and safe. Neither Matlab nor the user has to guess the intention.
An incomplete list of strict programming styles:
- No eval or assignin
- Specify the dimension to operate on in every case
- Specify the parent of graphic objects
- Use full path names instead of cd and relative paths
- Check if fopen was successful
- Count the output of fwrite to detect a full disk
- Do not shadow builtin functions (controlled by an automatic tool)
- Check each subfunction by an exhaustive unit tests including known-answer-tests and a correct detection of bad inputs (NaN, [], wrong type). Force the users to run the unit tests, when the code runs on a new Matlab version
- Include exhaustive comments to allow for debugging and maintaining the code
- Document all changes in a version history
- No switch without otherwise. If a variable is defined inside an if, do this in an else block also.
- Close files in the same function and indentation level as it is opened (means: do not open it in an IF block and close it outside of it, or the other way around)
- Read the FAQ and Answers: dump mistakes to profit from the mistakes made by others.
Categories
Find more on Special Values in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!