Archive
Windows 7 Command Line Help mistake for IF command
If you type
help IF
at the Windows 7 command-line (can launch this by searching at Windows Start menu search box for “Command” or by typing cmd there and pressing ENTER), you get in one of the help pages printed out for the batch files’ IF command:
%ERRORLEVEL% will expand into a string representation of
the current value of ERRORLEVEL, provided that there is not already
an environment variable with the name ERRORLEVEL, in which case you
will get its value instead. After running a program, the following
illustrates ERRORLEVEL use:goto answer%ERRORLEVEL%
:answer0
echo Program had return code 0
:answer1
echo Program had return code 1
If a program you launched from the batch file returns error code 0 (meaning usually no error), then you jump to label (using “goto” command) answer%ERRORLEVEL% that is answer0 (labels are prefixed with : in DOS/Windows batch files) and it prints out (using echo command) on the console “Program had return code 0”.
Fine till here, but then it will proceed to next commands (the block labeled :answer1) and also print out “Program had return code 1”. Obviously the correct example should be:
goto answer%ERRORLEVEL%
:answer0
echo Program had return code 0
goto finish
:answer1
echo Program had return code 1
:finish
Could also have a goto finish after the last echo, but its needless since we don’t have :answer2 etc. labels after that and proceeds to finish by itself anyway.
Thinking of this example again, it’s a pretty silly one since one could do instead:
echo Program had return code %ERRORLEVEL%
BTW, to output an empty line to the console you can use echo:
And speaking of batch file tips, you can use :: for comment lines instead of REM command.
VB gotcha: when If function isn’t equivalent to an If-Then-Else block
Just got bitten by the following:
Dim takeN As Integer = If(Integer.TryParse(EdTake.Text, takeN), takeN, itemsCount)
I had used that instead of writing in 2 lines:
Dim takeN As Integer
If not Integer.TryParse(EdTake.Text, takeN) then takeN = itemsCount
However, there’s an important difference:
“If” is a function, so its arguments are evaluated at call-time. The “If” signature is:
I guess the default is to pass arguments ByVal (by value) and not ByRef (by reference), although I’d expect the signature to specify it explicitly to avoid confusion. When one passes a literal value (say 15) to TruePart or FalsePart it just gets “boxed” into an Object, whereas if one passes an expression (e.g. “takeN+1” or even just “takeN”) it gets evaluated first, then result is boxed and passed as an Object.
So, whereas one might think (esp. if coming from the ALGOL “Call-By-Name” era) the 1st line to be equivalent to:
Dim takeN As Integer
If Integer.TryParse(EdTake.Text, takeN) then takeN = [RESULT OF TRYPARSE] else takeN = itemsCount
in fact it’s equivalent to:
Dim takeN As Integer
If Integer.TryParse(EdTake.Text, takeN) then takeN = [ANY] else takeN = itemsCount
where ANY is whatever the takeN variable one had defined contains.
I thought the VB compiler was warning when using a variable before having assigned a value to it, but it seems in this case it misses to issue a warning. In fact I just tried:
Public ReadOnly Property Take As Integer
Get
Dim takeN As Integer
Return takeN
End Get
End Property
and it still doesn’t complain. Strange, probably it sets new local variables to 0 by default, but it shouldn’t encourage a programming style that relies on implicit default values – such syntax usually means there’s a mistake in the source code that can lead to a nasty bug.
The moral of the story? Avoid such shorthand expressions and stick to classic keyword-based syntactical structures – after all structured programming had been introduced as an alternative to the many times incomprehensible programs written in functional programming languages (e.g. due to overuse of nested function calls).