Bizarre Substitutions in Windows Batch Files (December 1, 2006)

I have learned twice now that Windows substitutes variables in a bizarre order with its batch files. The latest example, found by Keith Hodel, originally looked like this:
if "%OS%"=="Windows_NT" (
  rem ...stuff...
) else (
  set _SCALA_HOME=%SCALA_HOME%
  if "%_SCALA_HOME%"=="" goto error1
)

This code sets _SCALA_HOME from SCALA_HOME, and then tests whether _SCALA_HOME is non-empty. You would think that if SCALA_HOME were non-empty, then the second "if" statement would never fail.

You would be wrong. Before entering an "if" or "for" branch, Windows goes ahead and substitutes all variables. For example, if you suppose SCALA_HOME starts as "C:\scala" and _SCALA_HOME starts as "", then the above "else" clause would get substituted like this:

  set _SCALA_HOME=c:\scala
  if ""=="" goto error1

Notice that this second "if" will call error1 regardless of what _SCALA_HOME gets set to!

Keith figured out the following workaround:

) else (
  set _SCALA_HOME=%SCALA_HOME%
  rem The following line tests SCALA_HOME instead of _SCALA_HOME, because
  rem the above change to _SCALA_HOME is not visible within this block.
  if "%SCALA_HOME%"=="" goto error1
)

I wonder how many hours of productivity have been lost around the world due to this mystery? We have lost about 10 man-hours internally in the Scala group, and it looks like Keith lost another few himself. It is indisputable that Windows remains a viable operating system, a topic which cuts to the heart of efforts to make better programming languages. Leaving that topic aside, I still wonder: how much better could Windows be if its core scripting language had intuitive semantics?

Personally, I would love to take this idea further, and see a really nice shell language. It seems that Windows could get a productivity boost by simply adopting the decades-old Bourne shell that is used in Linux distributions. Linux users should not be complacent, though; Scheme Shell, for example, can boost shell-scripting productivity for those who adopt it. Looking further ahead, a good shell is a crucial part of what I think of as the hacker's OS of the future. A good shell is what makes Smalltalk and the Lisp Machine be more than just good languages, but good platforms for hacking.


Lex Spoon