Here’s a nice little puzzle that came to me from long-time Matlab veteran Andrew Janke:
Without actually running the following code in Matlab, what do you expect its output to be? ‘Yaba’? ‘Daba’? perhaps ‘Doo!’? or maybe it won’t run at all because of a parsing error?
function test try if (false) or (true) disp('Yaba'); else disp('Daba'); end catch disp('Doo!'); end end |
To muddy the waters a bit, do you think that short-circuit evaluation is at work here? or perhaps eager evaluation? or perhaps neither?
Would the results be different if we switched the order of the conditional operands, i.e. (true) or (false)
instead of (false) or (true)
? if so, how and why?
And does it matter if I used “false
” or “10< 9.9
” as the “or” conditional?
Are the parentheses around the conditions important? would the results be any different without these parentheses?
In other words, how and why would the results change for the following variants?
if (false) or (true) % variant #1 if (true) or (false) % variant #2 if (true) or (10< 9.9) % variant #3 if true or 10< 9.9 % variant #4 if 10> 9.9 or 10< 9.9 % variant #5 |
Please post your thoughts in a comment below (expected results and the reason, for the main code snippet above and its variants), and then run the code. You might be surprised at the results, but not less importantly at the reasons. This deceivingly innocuous code snippet leads to interesting insight on Matlab’s parser.
Full marks will go to the first person who posts the correct results and reasoning/interpretation of the variants above (hint: it’s not as trivial as it might look at first glance).
Addendum April 9, 2019: I have now posted my solution/analysis of this puzzle here.
USA visit
I will be travelling in the US (Boston, New York, Baltimore) in May/June 2019. Please let me know (altmany at gmail) if you would like to schedule a meeting or onsite visit for consulting/training, or perhaps just to explore the possibility of my professional assistance to your Matlab programming needs.
– or is logical OR, thus no parsing error or ‘Doo!’
– false is interpreted first, so result would be ‘Daba’
hold on, that was way too quick
I said that it’s not as trivial as it might look at first glance 🙂
So, back from lunch 😉
The parser seems to interpret “
or
” different to | and ||, i.e. as a new command.or(true)
would then cause an error, but the line is not reached. The same would apply for “and
“.I guess why it is interpreted differently is the big Q – I have no answer to that 😉
This looks like a Python programmer tried writing MATLAB code. OR is a function, not an operator.
Does MATLAB interpret this as
?
So Cris – what would you expect to happen in Matlab with the variants above? (code as-is; switching
false
<=>true
; and without parentheses)or(true)
andor true
both are missing an argument, I would guess.or true
is the same asor('true')
, it passes a char array as argument. The function needs two arguments. If executed they’d throw an error. So starting withif true
would cause the catch to execute.I don’t know what happens with the parenthesis around the argument to
if
, maybe they’re needed to prevent a syntax error because of the missing comma, but this is just a guess.Great Sunday morning exercise! I’m curious to see what happens when I type this into MATLAB tonight. 🙂
The answer is Doo!
Your answer is doo-doo!
this one works as expected:
the parsing is:
Prior to running it, I would have expected the if to error. Then I pasted it into the editor and the lint told me to put a comma after the false. That caused me to believe it saw the false as the complete conditional, which would cause the else to be executed (which seems to be the case when running it).
I suspect the reason for this stems from the support for a single line if. I suspect Matlab parses everything from the if to the end of the first function call (or of course || or &&) as the conditional.
Replacing the true and if statements by anything that returns those statements does not change the parsing. Removing the parentheses will only change the or() call to be in the char mode, which would then still be missing its second input. Curiously, you can’t enter a false in char mode. If you try with eval to have a char(0) to force a false, an error is returned instead (not enough inputs), as eval seems to crop from char(0) onwards.
Hi everyone,
new here 🙂
nice puzzle. I have never used ‘or’ like that, only used function or(A,B), or the || operator. I would have expected error there…so that was my answer 🙂
Now I’ll need to review my knowledge on syntax…
Very intriguing puzzle! I never knew that parentheses around the expression immediately following if allowed you to continue with the first line of the statement group without a comma or semicolon. Is this syntactic logic really not documented? I certainly couldn’t find any.
That behaviour is of course the reason the main puzzle results in Daba, after seeing that the full condition of the if statement is just false. I don’t think that an if statement skipping the block it would execute if true and proceeding to the else block can be described as short-circuit evaluation, but maybe my understanding of execution engine theory falls short here.
The variants are fun, too.
In variant #2 we pass the if condition and get to the function call to or (disguised as a binary operator to fool users of more verbose languages than MATLAB) with only one argument – throwing an exception that results in a Doo!
In variant #3 nothing changes, because of course 10< 9.9 just evaluates to a scalar false which still isn’t an adequate input to the or function. But of course this is just a set up for
variant #4, which cunningly uses command syntax to pass two character vector arguments to or, each carefully engineered to be three characters long so that we evaluate the equivalent of ’10<‘ | ‘9.9’ which is a valid vector boolean operation. Since none of the characters involved is the null character the result is `[true true true]` so we finally get a `Yaba`.
Happy April Fools’!
Oh dear, seems I was wrong on (at least) two counts above…
First, the first set of brackets seem to do nothing. I was sure you normally needed a comma after the condition expression, but apparently not?!
Second, the command in variant #4 still doesn’t qualify as part of the if condition. So after having satisfied the if true condition, first the result of the unsuppressed command or 10< 9.9 is displayed in the command window:
then ‘Yaba’ is displayed!
Is it cheating if I not only work at MathWorks, but asked the development lead for the MATLAB Front End and Code Analyzer for an answer? Andrew emailed me the same puzzle over the weekend, which I forwarded on to the dev lead. Here’s the scoop:
For backwards compatibility, space is a valid separator between the expression in the if-condition and the first statement in the body. We don’t want to encourage users to write more such code because we realize this can be very confusing, but we also don’t want to break existing code which is out there and works correctly.
Therefore, the Code Analyzer tries to provide an indication of the current behavior and direct users away from it. For this specific code example, it provides these two messages on the “or” in the MATLAB Editor:
It looks like this is just syntax muddling. Rewritten with better formatting, we get this:
We never actually reach the line “or(true)”, which would throw an error, causing the catch block to print ‘Doo!’, so instead we simply print ‘Daba’. The parentheses are required in order to have the (false) alone apply to the if statement, as opposed to what comes after.
Regarding the other questions:
if (false) or (true) % variant #1
if (true) or (false) % variant #2 — my guess is this will print ‘Doo!’, since the or(false) will throw an error
if (true) or (10< 9.9) % variant #3 — will also print ‘Doo!’ for the same reason: “or(10<9.9)” is invalid
if true or 10< 9.9 % variant #4 — will also print ‘Doo!’, but this time it’s because “true or 10< 9.9” or: “10>9.9 or 10<9.9” is invalid — the or function requires 2 arguments
Ha, it looks like variant #4 got me. Quite clever. When pasted in Matlab it’s a bit more obvious because the “10< 9.9" is coded purple, indicating character arrays.
(I meant variant #5)
Hi Yair, I would expect the conditional expression to fail during parsing, and therefore lead to “Doo!” output per catch block. The proper “functional” syntax for logical OR is as follows: