附錄B 在DOS中運行Scheme腳本
==========================
DOS的腳本也叫做“批處理”。通常一個輸出`Hello World!`的DOS批處理文件應該這樣寫:
```shell
echo Hello, World!
```
這里用到了DOS的命令`echo`。腳本文件被命名為`hello.bat`,這樣會被操作系統認為是可執行的。然后可以放入任一在`PATH`環境變量中的目錄下。然后任何時候在DOS提示符下輸入
```shell
hello.bat
```
或者更簡單的:
```shell
hello
```
就能立即得到這句俗得不能再俗的問候。
Scheme版本的`hello`批處理文件會用Scheme產生相同的輸出,但是我們需要在文件中寫一些東西來告訴DOS讓它用Scheme來分析文件內容,而不是理解為它默認的腳本批處理語言。Scheme的批處理文件(也命名為`hello.bat`),內容如下:
```bat
;@echo off
;goto :start
#|
:start
echo. > c:\_temp.scm
echo (load (find-executable-path "hello.bat" >> c:\_temp.scm
echo "hello.bat")) >> c:\_temp.scm
mzscheme -r c:\_temp.scm %1 %2 %3 %4 %5 %6 %7 %8 %9
goto :eof
|#
(display "Hello, World!")
(newline)
;:eof
```
到`|#`之前全部是標準的DOS批處理命令。后面是Scheme的問候代碼。最后還有一行標準的DOS批處理,即`;:eof`。
當用戶在DOS提示符下輸入`hello`時,DOS讀取并將`hello.bat`作為一個普通的批處理文件來運行。第一行,`;@echo off`,關閉了命令運行時產生的輸出――我們不想讓大量冗余信息淹沒我們腳本產生的輸出。第二行,`;goto :start`,讓腳本的執行跳轉到標號`:start`即第四行。后面接著的`echo`行創建了一個叫`c:\_temp.scm`的Scheme臨時文件,其內容如下:
```scheme
(load (find-executable-path "hello.bat" "hello.bat"))
```
下一個批處理命令調用MzScheme。`-r`選項加載Scheme文件`c:\_temp.scm`。所有的參數(在這個例子里沒有)可以在Scheme中通過`argv`向量來獲得。這個調用的Scheme會對我們的腳本進行求值,我們下面會看到。Scheme執行返回后,我們仍然需要讓批處理文件正常地結束(否則就會碰到它不認識的Scheme代碼了)。下一個批處理命令是`goto :eof`,這會讓控制流跳過所有的Scheme代碼,到達文件末尾,也就是包含`;:eof`標簽的一行。然后腳本結束運行。
現在我們知道如何讓Scheme來執行它的那部分代碼,即運行嵌入在批處理文件中的Scheme表達式。載入`c:\_temp.scm`會使Scheme找到`hello.bat`文件的絕對路徑(用`find-executable-path`過程),然后載入`hello.bat`。
因此,Scheme腳本文件現在會以Scheme文件來運行,文件中的Scheme表達式可以通過向量`argv`來訪問腳本的原始參數。
現在Scheme略過腳本中的批處理命令。這是因為這些批處理命令要么以分號開頭,要么用`#|...|#`包裹,這在Scheme看來是注釋。
文件剩下的部分當然是Scheme代碼,因此表達式被依次求值(最后的表達式`;:eof`是一個Scheme注釋,因此沒有關系)總之所有的表達式被求值后,Scheme會退出。
綜上所述,在DOS提示符下輸入hello會產生
```
Hello, World!
```
并返回DOS提示符。