Is there a good reason for choosing assert() over an if condition with an error?

I want to make sure a condition is valid, so I write a quick test for it with a boolean output. Does it matter whether I put the test in an if/error block or an assertion? Is easier reading/fewer lines the only goal?

12 commentaires

I think it is simply syntactic sugar, yes.
If the purpose of the test is simply for the error condition and all one is going to do is error, then it saves the explicit construct, but that's it.
TIL, syntactic sugar and cyclomatic complexity. Thanks to both of you.
It doesn't change the complexity metric; the two paths exist either way whether implmented by the if...end construct or by assert()
True. I still learned a new term.
It looks like in C, asserts were designed to be selectively ignored based on whether the program was being debugged. In Matlab, that kind of debugging style doesn't really fit--so the usage has changed.
I am kind of leaning toward the if,error,end style, even though it's old school. It's impossible to misunderstand.
"It doesn't change the complexity metric; the two paths exist either way whether implmented by the if...end construct or by assert()"
That statement is incorrect according to the original definition of McCabe complexity, which is the one used by MATLAB's CHECKCODE/MLINT code checker. Lets check it with some actual code (attached):
checkcode usesASSERT.m -cyc
L 1 (C 14-23): The McCabe cyclomatic complexity of 'usesASSERT' is 1.
checkcode usesIFERR.m -cyc
L 1 (C 14-22): The McCabe cyclomatic complexity of 'usesIFERR' is 4.
According to McCabe's original definition the IF defines a new path, but ASSERT does not.
Interesting. But why?
I can check the complexity of PLOT:
checkcode plot -cyc
L 1 (C 14-17): The McCabe cyclomatic complexity of 'plot' is 17. L 144 (C 54-68): The McCabe cyclomatic complexity of 'checkinputnames' is 13.
(also, that's a different output than I get)
But checking ASSERT leads to a suspicious answer:
checkcode assert -cyc
L 1 (C 1): The McCabe cyclomatic complexity is 0.
Is it only analyzing code the end user can inspect?
"Interesting. But why?"
Why what?
"also, that's a different output than I get"
Different version, different path, different file. Welcome to MATLAB.
"But checking ASSERT leads to a suspicious answer:"
It looks like you have just found an indirect way to identify if an operator is pcode or compiled or a keyword, which of course CHECKCODE/MLINT cannot analyze. I don't see anything suspicous about that, the same applies to many other inbuilt operators:
checkcode error -cyc
L 1 (C 1): The McCabe cyclomatic complexity is 0.
checkcode else -cyc
L 1 (C 1): The McCabe cyclomatic complexity is 0.
checkcode dir -cyc
L 1 (C 1): The McCabe cyclomatic complexity is 0.
checkcode if -cyc
L 1 (C 1): The McCabe cyclomatic complexity is 0.
checkcode i -cyc
L 1 (C 1): The McCabe cyclomatic complexity is 0.
"Is it only analyzing code the end user can inspect?"
Do you expect a static code analyzer to decompile code for you?
The metric apparently doesn't know anything about the functionality of the keyword so it misses there being a hidden branch.
Would be of pedagogical interest to know what vocabulary it uses -- it it only includes structures such as if..end and doesn't understand the meaning of assert(), then "Yes, Virginia, it's not going to recognize the existence of a branch."
That may have some value, but it isn't quite the whole truth about the code structure.
Stephen23
Stephen23 le 5 Mai 2022
Modifié(e) : Stephen23 le 5 Mai 2022
@dpb: I don't really see ASSERT as any different from ERROR: both of them are the end of an execution path.
But it's not the error() that is the difference in the metric is the point -- counting an
if flag, error(), end
any differently than
assert(flag)
favors the implicit branch unduly and penalizes the equivalent -- to be on a level footing, the metric should examine the content of the condition stucture and not count those as above that are simple ends as well; they're no more complex.
"favors the implicit branch unduly and penalizes the equivalent"
As it should: they are not equivalent.
"they're no more complex."
The IF is more complex by McCabe's definition, it is another path which can execute other code:
IF ohno
WHATEVER()
ERROR()
END
whereas this can never start another path:
ASSERT(~ohno)
Note that there is nothing in McCabe's definition that says that a path must execute code: this still adds one path:
IF blah
END
Nor does the definition provide a way to exclude paths that will never be executed (e.g. due to numeric/logical conditions), however you appear to want to optimize such things away... sadly McCabe did not deign to include a code optimizer in the definition of cyclomatic complexity. What happens in this case?:
IF ohno
HELLO()
end
% possibly nested down some function calls but with no extra paths:
function HELLO()
ERROR()
end
Given that MATLAB has a dynamic search path and scope, your concept essentially means that we cannot know the cyclomatic complexity of that code until runtime... or perhaps never, if HELLO() is pcode/compiled and ohno is false.
I much prefer the standard, simple, original/current McCabe definition which can be achieved using static code analysis of nothing more than the single function we wish to analzye. Which, incidentally, is what MLINT/CODECHECK does.
But I can see that we view this differently. Thank you for the interesting discussion!
But in the particular case they are equivalent -- while the if...end COULD could include more code, in this case it doesn't.
I don't argue that it would make computing a metric much more difficult, but imo one should recognize that one can have the same effective metric and the code is just as robust despite what the present metric may indicate as the one being higher than the other.
For a simple, short routine with only one or two exits, the numerical difference probably wouldn't show up much; a more involved routine with lots of error checking could really show up as a loser when, in fact, it really isn't.

Connectez-vous pour commenter.

 Réponse acceptée

Stephen23
Stephen23 le 4 Mai 2022
Modifié(e) : Stephen23 le 4 Mai 2022
"Is easier reading/fewer lines the only goal?"
Why call two operators when you can call just one?
It certainly can make the intent clearer: ASSERT makes it clear that no other actions are intended/possible. In my quick internet search just now (not MATLAB specific), the general consensus seems to be that ASSERT should be used (much like its name implies) at particular points in code where certain condition/s must be met for the code to work. In contrast, an IF certainly implies that some other action might be performed at the programmers discretion.
My observation: ASSERT tends to be underused in MATLAB.
My recommendation: use whichever one makes your code look best and easier to read.

1 commentaire

Mayhaps it's just me and being an old dog, but I find I almost always have it backwards the first time for some reason...so almost always have to spend extra time debugging/fixing my logic when I try using it.
For legibility, I'll often use something like
if errortest(), error('Error msg'), end
instead of the full-blown indented if...end structure so it doesn't break up the code linear flow when scanning.

Connectez-vous pour commenter.

Plus de réponses (2)

Xiangrui Li
Xiangrui Li le 30 Juil 2025
Modifié(e) : Xiangrui Li le 30 Juil 2025
I hit this qustion while exploring python assert. I recall that Matlab assert is alway bad for performance, compared to if ... error(); end, although most of time the difference is negligible.
The reason is that assert alway evaluate 2nd input even if the condition is met. For example:
assert(2>1, nonExistingVar);
will complain Unrecognized function or variable 'noExistingVar', indicating it checks the 2nd input.
if 1>2, error(nonExistingVar); end
This won't complain, indicating it won't check the msg part if the condition is not met.
So when no error needs to throw, we can expect if.. error() has better performance than assert.
For this reason, except assert line may look cleaner, there is no reason to prefer it.

1 commentaire

I would expect the times in which the execution difference is more than barely measurable are rare, indeed.
I think the advantage of asset if one chooses to use its features is that it returns an MException object that can be used to amplify the error message for the user. The same can be done in an error() routine, just a little more effort.

Connectez-vous pour commenter.

My personal style is that assert() is mostly for conditions that should always be true contextually, with the assert() being double-checking. By contrast, if,error,end is for expected error
For example if there is a function that is only designed to be called by another function that is expected to arrange inputs properly, then the called function might call assert to completely validate the parameters "just in case" there is a bug in the calling routine or something outside the intended calling routine invokes it. assert() is for "something went wrong in the coding" cases.
By way of contrast, if,error,end is more for functions called directly by the user, in which it is not uncommon for the user to pass in bad values, and perhaps a more user-friendly error message is called for.

1 commentaire

I hadn't really considered the context in that light, Walter, but that somewhat echoes my use of when use assert; most of the cases happen to be in code that isn't directly callable by the use, but the user does enter data via spreadsheets or other tools so it is not unlikely there can be a mistake. I guess in the end it ends up just which seems more convenient at the time as am writing the code rather than any specific rule...

Connectez-vous pour commenter.

Catégories

En savoir plus sur Startup and Shutdown dans Centre d'aide et File Exchange

Produits

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by