第 14 章 頂層系統或 REPL (ocaml)

本章描述 ocaml,OCaml 的頂層系統,它允許透過讀取-求值-列印迴圈 (REPL) 互動式使用 OCaml 系統。 在此模式下,系統會重複從輸入讀取 OCaml 短語,然後進行類型檢查、編譯和求值,然後列印推斷的類型和結果值(如果有的話)。 標準輸入上的檔案結尾會終止 ocaml

頂層的輸入可以跨越多行。它從系統列印的 # (井號) 提示符後開始,並以 ;; (雙分號) 終止,後面可選擇性地加上空白和註解,以及行尾。 頂層輸入由一個或多個頂層短語組成,語法如下

頂層輸入::={ 定義 } ;;
 運算式;;
 #識別符 [ 指令引數 ] ;;
 
指令引數::= 字串文字
 整數文字
 值路徑
 true ∣ false

一個短語可以包含一系列定義,例如在編譯單元的實作中或在 structend 模組運算式中找到的定義。 這些定義可以繫結值名稱、類型名稱、例外、模組名稱或模組類型名稱。 頂層系統會執行繫結,然後列印所定義名稱的類型和值(如果有的話)。

短語也可以包含一個值運算式 (章節 11.7)。 它會在不執行任何繫結的情況下簡單地求值,並列印其值。

最後,短語也可以包含一個頂層指令,以 # (井號) 開頭。 這些指令控制頂層的行為;它們在下面的章節 14.2 中列出。

Unix:  頂層系統由命令 ocaml 啟動,如下所示
        ocaml options objects                # interactive mode
        ocaml options objects scriptfile        # script mode
選項 在下面描述。物件 是以 .cmo.cma 結尾的檔案名稱;它們會在設定 選項 後立即載入到解譯器中。腳本檔案 是任何不以 .cmo.cma 結尾的檔案名稱。

如果命令列上未提供任何 腳本檔案,則頂層系統會進入互動模式:短語會在標準輸入上讀取,結果會列印在標準輸出上,錯誤則列印在標準錯誤上。 標準輸入上的檔案結尾會終止 ocaml (另請參閱章節 14.2 中的 #quit 指令)。

在啟動時 (在讀取第一個短語之前),會將初始化檔案的內容讀取為一系列 OCaml 短語,並按照章節 14.2 中描述的 #use 指令執行。不會顯示每個短語的求值輸出碼。

初始化檔案是以下第一個找到的檔案

  1. 目前目錄中的 .ocamlinit
  2. 如果 XDG_CONFIG_HOME 是絕對路徑,則為 XDG_CONFIG_HOME/ocaml/init.ml
  3. 否則,在 Unix 上,為 HOME/ocaml/init.ml,或在 Windows 上,為 LocalAppData 下的 ocaml\init.ml (例如 C:\Users\Bactrian\AppData\Local\ocaml\init.ml);
  4. XDG_CONFIG_DIRS 中任何絕對路徑下的 ocaml/init.mlXDG_CONFIG_DIRS 中的路徑在 Unix 上以冒號分隔,在 Windows 上以分號分隔;
  5. 如果 XDG_CONFIG_DIRS 不包含任何絕對路徑,則在 Unix 上為 /usr/xdg/ocaml/init.ml,或在 Windows 上,為 LocalAppData (例如 C:\Users\Bactrian\AppData\Local)、RoamingAppData (例如 C:\Users\Bactrian\AppData\Roaming) 或 ProgramData (例如 C:\ProgramData) 下的 ocaml\init.ml
  6. 如果 HOME 為非空值,則為 HOME/.ocamlinit

頂層系統不執行行編輯,但可以輕鬆地與外部行編輯器 (例如 leditrlwrap) 結合使用。 還有一個改進的頂層 utop 可用。 另一個選項是在 Gnu Emacs 下使用 ocaml,這會提供 Emacs 的完整編輯能力 (來自程式庫 inf-caml 的命令 run-caml)。

在任何時候,都可以按下 ctrl-C (或更準確地說,是將 INTR 訊號傳送到 ocaml 處理程序) 來中斷目前短語的剖析、編譯或求值。 然後頂層會立即返回 # 提示符。

如果 腳本檔案 在命令列上提供給 ocaml,則頂層系統會進入腳本模式:會將檔案的內容讀取為一系列 OCaml 短語並執行,如同 #use 指令 (章節 14.2)。 不會列印求值的結果。 到達檔案結尾時,ocaml 命令會立即結束。 不會從標準輸入讀取任何命令。 Sys.argv 會被轉換,忽略所有 OCaml 參數,並以 Sys.argv.(0) 中的腳本檔案名稱開始。

在腳本模式下,如果腳本的第一行以 #! 開頭,則會忽略該行。 因此,應該可以將腳本本身設為可執行檔,並將 #!/usr/local/bin/ocaml 作為第一行,以便在執行腳本時自動呼叫頂層系統。 然而,ocaml 本身在大多數 OCaml 安裝中都是 #! 腳本,而且 Unix 核心通常不處理巢狀 #! 腳本。 更好的解決方案是將以下內容作為腳本的第一行

        #!/usr/local/bin/ocamlrun /usr/local/bin/ocaml

1 選項

ocaml 命令可辨識以下命令列選項。

-absname
強制錯誤訊息顯示檔案名稱的絕對路徑。
-no-absname
不要嘗試在錯誤訊息中顯示絕對檔案名稱。
-args 檔案名稱
檔案名稱 讀取其他以換行符號終止的命令列引數。 無法透過檔案將 腳本檔案 傳遞給頂層。
-args0 檔案名稱
檔案名稱 讀取其他以空字元終止的命令列引數。 無法透過檔案將 腳本檔案 傳遞給頂層。
-I 目錄
將給定的目錄新增至搜尋原始檔和編譯檔的目錄清單。 預設情況下,會先搜尋目前目錄,然後是標準程式庫目錄。 使用 -I 新增的目錄會在目前目錄之後,按照它們在命令列中給定的順序搜尋,但在標準程式庫目錄之前。 另請參閱選項 -nostdlib

如果給定的目錄以 + 開頭,則會將其視為相對於標準程式庫目錄。 例如,-I +unix 會將標準程式庫的子目錄 unix 新增至搜尋路徑。

一旦頂層執行,也可以使用 #directory 指令 (章節 14.2) 將目錄新增至清單。

-init 檔案
載入給定的檔案,而不是預設的初始化檔案。 預設的初始化檔案是以下第一個找到的檔案
  1. 目前目錄中的 .ocamlinit
  2. 如果 XDG_CONFIG_HOME 是絕對路徑,則為 XDG_CONFIG_HOME/ocaml/init.ml
  3. 否則,在 Unix 上,為 HOME/ocaml/init.ml,或在 Windows 上,為 LocalAppData 下的 ocaml\init.ml (例如 C:\Users\Bactrian\AppData\Local\ocaml\init.ml);
  4. XDG_CONFIG_DIRS 中任何絕對路徑下的 ocaml/init.mlXDG_CONFIG_DIRS 中的路徑在 Unix 上以冒號分隔,在 Windows 上以分號分隔;
  5. 如果 XDG_CONFIG_DIRS 不包含任何絕對路徑,則在 Unix 上為 /usr/xdg/ocaml/init.ml,或在 Windows 上,為 LocalAppData (例如 C:\Users\Bactrian\AppData\Local)、RoamingAppData (例如 C:\Users\Bactrian\AppData\Roaming) 或 ProgramData (例如 C:\ProgramData) 下的 ocaml\init.ml
  6. 如果 HOME 為非空值,則為 HOME/.ocamlinit
-labels
標籤在類型中不會被忽略,標籤可以用在應用程式中,且帶標籤的參數可以以任何順序給定。這是預設行為。
-no-app-funct
停用函子的應用行為。使用此選項時,每個函子應用都會在其結果中產生新的類型,並且將同一個函子應用兩次到相同的參數會產生兩個不相容的結構。
-noassert
不編譯斷言檢查。請注意,特殊形式 assert false 始終會被編譯,因為它具有特殊的類型。
-nolabels
忽略類型中非可選的標籤。標籤不能用在應用程式中,且參數順序會變得嚴格。
-noprompt
等待輸入時不顯示任何提示符號。
-nopromptcont
在多行輸入中等待後續行時,不顯示次要提示符號。這應該在例如在 emacs 視窗中執行 ocaml 時使用。
-nostdlib
不要將標準函式庫目錄包含在搜尋原始碼和編譯檔案的目錄清單中。
-ppx command
在解析後,將抽象語法樹透過預處理器 command 傳輸。在第30章中描述的模組 Ast_mapper Ast_mapper ,實現了預處理器的外部介面。
-principal
在類型檢查期間檢查資訊路徑,以確保所有類型都以主要方式推導。當使用帶標籤的參數和/或多型方法時,此旗標是必要的,以確保未來版本的編譯器即使內部演算法發生變更,也能正確推斷類型。在 -principal 模式下接受的所有程式碼,在預設模式下也會被接受,且具有等效的類型,但二進位簽名可能不同,這可能會減慢類型檢查的速度;但建議在發布原始碼之前使用一次。
-rectypes
在類型檢查期間允許任意遞迴類型。預設情況下,僅支援遞迴通過物件類型的遞迴類型。
-safe-string
強制區分 stringbytes 類型,從而使字串為唯讀。這是預設行為,並且自 OCaml 5.0 起強制執行。
-safer-matching
不使用類型資訊來最佳化模式匹配。這樣可以檢測到匹配失敗,即使模式匹配被錯誤地假設為窮盡的。這僅影響 GADT 和多型變體編譯。
-short-paths
當一個類型在多個模組路徑下可見時,在推斷的介面以及錯誤和警告訊息中列印類型的名稱時,使用最短的路徑。以底線 _ 開頭或包含雙底線 __ 的識別符號名稱,在計算其長度時會受到 +10 的懲罰。
-stdin
將標準輸入讀取為腳本檔案,而不是啟動互動式會話。
-strict-sequence
強制每個序列的左側部分都具有 unit 類型。
-strict-formats
拒絕舊版格式實作中接受的無效格式。您應該使用此旗標來檢測和修復此類無效格式,因為它們將被未來的 OCaml 版本拒絕。
-unsafe
關閉陣列和字串存取的邊界檢查(v.(i)s.[i] 建構)。使用 -unsafe 編譯的程式碼因此會更快,但不安全:如果程式碼存取超出其邊界的陣列或字串,則可能會發生任何事情。
-unsafe-string
stringbytes 類型識別為相同的,從而使字串可寫入。這旨在與舊的原始碼相容,不應與新軟體一起使用。自 OCaml 5.0 以來,此選項會無條件引發錯誤。
-v
列印編譯器的版本號和標準函式庫目錄的位置,然後結束。
-verbose
在執行之前列印所有外部命令,有助於除錯 C 函式庫問題。
-version
列印版本字串並結束。
-vnum
列印簡短版本號並結束。
-no-version
啟動時不列印版本標頭。
-w warning-list
啟用、停用或將 warning-list 引數指定的警告標記為嚴重錯誤。每個警告都可以啟用停用,並且每個警告都可以是嚴重非嚴重的。如果警告被停用,則不會顯示該警告,並且不會以任何方式影響編譯(即使它是嚴重的)。如果警告被啟用,則當原始碼觸發該警告時,編譯器會正常顯示該警告。如果已啟用且為嚴重錯誤,編譯器還會在顯示該警告後停止並顯示錯誤。

warning-list 引數是一系列的警告規範,它們之間沒有分隔符號。警告規範是下列其中一項

+num
啟用警告號碼 num
-num
停用警告號碼 num
@num
啟用並將警告號碼 num 標記為嚴重錯誤。
+num1..num2
啟用指定範圍內的警告。
-num1..num2
停用指定範圍內的警告。
@num1..num2
啟用並將指定範圍內的警告標記為嚴重錯誤。
+letter
啟用與 letter 對應的一組警告。字母可以是大小寫字母。
-letter
停用與 letter 對應的一組警告。字母可以是大小寫字母。
@letter
啟用並將與 letter 對應的一組警告標記為嚴重錯誤。字母可以是大小寫字母。
uppercase-letter
啟用與 uppercase-letter 對應的一組警告。
lowercase-letter
停用與 lowercase-letter 對應的一組警告。

或者,warning-list 可以使用其助記名稱(如下所示)指定單個警告,如下所示

+name
啟用警告 name
-name
停用警告 name
@name
啟用並將警告 name 標記為嚴重錯誤。

目前未定義的警告號碼、字母和名稱將被忽略。警告如下(每個數字後面的名稱指定該警告的助記符)。

1 comment-start
看起來可疑的註解開始標記。
2 comment-not-end
看起來可疑的註解結束標記。
3
已棄用的 'deprecated' 警告的同義詞。
4 fragile-match
脆弱的模式匹配:即使將額外的建構子新增到匹配的變體類型之一,仍將保持完整的匹配。
5 ignored-partial-application
部分應用的函式:結果具有函式類型且被忽略的表示式。
6 labels-omitted
在函式應用中省略標籤。
7 method-override
方法被覆寫。
8 partial-match
部分匹配:模式匹配中缺少案例。
9 missing-record-field-pattern
記錄模式中缺少欄位。
10 non-unit-statement
序列左側的表示式不具有類型 unit(且不是函式,請參閱警告編號 5)。
11 redundant-case
模式匹配中的多餘案例(未使用的匹配案例)。
12 redundant-subpat
模式匹配中的多餘子模式。
13 instance-variable-override
實例變數被覆寫。
14 illegal-backslash
字串常數中非法反斜線跳脫字元。
15 implicit-public-methods
隱式公開的私有方法。
16 unerasable-optional-argument
無法抹除的可選引數。
17 undeclared-virtual-method
未宣告的虛擬方法。
18 not-principal
非主要類型。
19 non-principal-labels
沒有主性的類型。
20 ignored-extra-argument
未使用的函式引數。
21 nonreturning-statement
不回傳的陳述式。
22 preprocessor
預處理器警告。
23 useless-record-with
無用的記錄 with 子句。
24 bad-module-name
錯誤的模組名稱:原始檔名稱不是有效的 OCaml 模組名稱。
25
已忽略:現在是警告 8 的一部分。
26 unused-var
可疑的未使用變數:使用 letas 繫結的未使用變數,且不以底線 (_) 字元開頭。
27 unused-var-strict
無害的未使用變數:未使用 letas 繫結的變數,且不以底線 (_) 字元開頭。
28 wildcard-arg-to-constant-constr
作為常數建構子引數給定的萬用字元模式。
29 eol-in-string
字串常數中未跳脫的行尾(不可移植的程式碼)。
30 duplicate-definitions
在兩個相互遞迴的類型中,定義了兩個相同名稱的標籤或建構子。
31 module-linked-twice
同一個可執行檔中連結了兩次模組。
I
已忽略:現在是一個硬性錯誤(自 5.1 起)。
32 unused-value-declaration
未使用的值宣告。(自 4.00 起)
33 unused-open
未使用的 open 陳述式。(自 4.00 起)
34 unused-type-declaration
未使用的類型宣告。(自 4.00 起)
35 unused-for-index
未使用的 for 迴圈索引。(自 4.00 起)
36 unused-ancestor
未使用的祖先變數。(自 4.00 起)
37 unused-constructor
未使用的建構子。(自 4.00 起)
38 unused-extension
未使用的擴充建構子。(自 4.00 起)
39 unused-rec-flag
未使用的 rec 旗標。(自 4.00 起)
40 name-out-of-scope
建構子或標籤名稱超出範圍使用。(自 4.01 起)
41 ambiguous-name
不明確的建構子或標籤名稱。(自 4.01 起)
42 disambiguated-name
已消除歧義的建構子或標籤名稱 (相容性警告)。(自 4.01 起)
43 nonoptional-label
非選擇性標籤被當作選擇性標籤使用。(自 4.01 起)
44 open-shadow-identifier
Open 語句遮蔽了已定義的識別符號。(自 4.01 起)
45 open-shadow-label-constructor
Open 語句遮蔽了已定義的標籤或建構子。(自 4.01 起)
46 bad-env-variable
環境變數發生錯誤。(自 4.01 起)
47 attribute-payload
不合法的屬性酬載。(自 4.02 起)
48 eliminated-optional-arguments
隱式消除選擇性參數。(自 4.02 起)
49 no-cmi-file
在查找模組別名時缺少 cmi 檔案。(自 4.02 起)
50 unexpected-docstring
意外的文件註解。(自 4.03 起)
51 wrong-tailcall-expectation
函數呼叫使用不正確的 @tailcall 屬性進行註解。(自 4.03 起)
52 fragile-literal-pattern (參見 13.5.3)
易碎的常數模式。(自 4.03 起)
53 misplaced-attribute
屬性無法在此環境中使用。(自 4.03 起)
54 duplicated-attribute
屬性在一個表達式中使用了多次。(自 4.03 起)
55 inlining-impossible
無法內聯。(自 4.03 起)
56 unreachable-case
在模式匹配中無法到達的情況 (基於類型資訊)。(自 4.03 起)
57 ambiguous-var-in-pattern-guard (參見 13.5.4)
在保護條件下不明確的 or 模式變數。(自 4.03 起)
58 no-cmx-file
缺少 cmx 檔案。(自 4.03 起)
59 flambda-assignment-to-non-mutable-value
指派給不可變的值。(自 4.03 起)
60 unused-module
未使用的模組宣告。(自 4.04 起)
61 unboxable-type-in-prim-decl
在原始宣告中無法拆箱的類型。(自 4.04 起)
62 constraint-on-gadt
在 GADT 類型宣告上的類型約束。(自 4.06 起)
63 erroneous-printed-signature
錯誤的列印簽名。(自 4.08 起)
64 unsafe-array-syntax-without-parsing
-unsafe 與返回語法樹的預處理器一起使用。(自 4.08 起)
65 redefining-unit
類型宣告定義了一個新的 '()' 建構子。(自 4.08 起)
66 unused-open-bang
未使用的 open! 語句。(自 4.08 起)
67 unused-functor-parameter
未使用的函子參數。(自 4.10 起)
68 match-on-mutable-state-prevent-uncurry
依賴於可變狀態的模式匹配會阻止其餘參數被取消柯里化。(自 4.12 起)
69 unused-field
未使用的記錄欄位。(自 4.13 起)
70 missing-mli
缺少介面檔案。(自 4.13 起)
71 unused-tmc-attribute
未使用的 @tail_mod_cons 屬性。(自 4.14 起)
72 tmc-breaks-tailcall
尾呼叫因 @tail_mod_cons 轉換而變為非尾呼叫。(自 4.14 起)
73 generative-application-expects-unit
生成式函子應用於空結構 (struct end) 而不是 ()。(自 5.1 起)
A
所有警告
C
警告 1, 2。
D
警告 3 的別名。
E
警告 4 的別名。
F
警告 5 的別名。
K
警告 32, 33, 34, 35, 36, 37, 38, 39。
L
警告 6 的別名。
M
警告 7 的別名。
P
警告 8 的別名。
R
警告 9 的別名。
S
警告 10 的別名。
U
警告 11, 12。
V
警告 13 的別名。
X
警告 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 30。
Y
警告 26 的別名。
Z
警告 27 的別名。

預設設定為 -w +a-4-6-7-9-27-29-32..42-44-45-48-50-60。它由 -help 顯示。請注意,警告 5 和 10 並非總是觸發,取決於類型檢查器的內部結構。

-warn-error 警告清單
將參數 警告清單 中指定的警告標記為致命。當發出這些警告之一時,編譯器將停止並顯示錯誤。警告清單 的含義與 -w 選項相同:+ 符號 (或大寫字母) 將相應的警告標記為致命,- 符號 (或小寫字母) 將它們變回非致命警告,而 @ 符號則同時啟用並標記相應的警告為致命。

注意:不建議在生產程式碼中使用警告集 (即字母) 作為 -warn-error 的參數,因為當未來版本的 OCaml 新增一些新警告時,可能會破壞您的建置。

預設設定為 -warn-error -a (沒有警告是致命的)。

-warn-help
顯示所有可用警告號碼的說明。
- 檔案
即使 檔案 以連字號 (-) 開頭,仍將其用作腳本檔案名稱。
-help--help
顯示簡短的使用摘要並退出。
Unix:  還會參考以下環境變數
OCAMLTOP_INCLUDE_PATH
用於搜尋已編譯物件程式碼檔案 (.cmi.cmo.cma) 的其他目錄。指定的目錄會從左到右依序考慮,在搜尋完命令列上透過 -I 指定的包含目錄之後。自 OCaml 4.08 起可用。
OCAMLTOP_UTF_8
在列印字串值時,如果 OCAMLTOP_UTF_8 設定為 false,則非 ASCII 位元組 ( > \0x7E ) 會列印為十進位跳脫序列。否則,它們會以未跳脫的形式列印。
TERM
在列印錯誤訊息時,頂層系統會嘗試以視覺方式標示錯誤的位置。它會參考 TERM 變數來判斷輸出終端的類型,並在終端資料庫中查找其功能。
XDG_CONFIG_HOME, HOME, XDG_CONFIG_DIRS
初始化檔案查找程序 (請參閱上方)。

2 頂層指示詞

以下指示詞控制頂層行為、在記憶體中載入檔案,並追蹤程式執行。

注意:所有指示詞都以 # (井號) 符號開頭。這個 # 必須在指示詞之前輸入,並且不得與互動迴圈顯示的 # 提示混淆。例如,輸入 #quit;; 將會退出頂層迴圈,但輸入 quit;; 會導致「未綁定值 quit」錯誤。

一般
#help;;
列印所有可用的指示詞清單,如果適用,會附帶相應的參數類型。
#quit;;
退出頂層迴圈並終止 ocaml 命令。
載入程式碼
#cd "目錄名稱";;
變更目前的工作目錄。
#directory "目錄名稱";;
將給定的目錄新增至搜尋來源和編譯檔案的目錄清單。
#remove_directory "目錄名稱";;
從搜尋來源和編譯檔案的目錄清單中移除給定的目錄。如果清單中不包含給定的目錄,則不執行任何動作。
#load "檔案名稱";;
在記憶體中載入由批次編譯器 ocamlc 產生的位元組碼物件檔案 (.cmo 檔案) 或程式庫檔案 (.cma 檔案)。
#load_rec "檔案名稱";;
在記憶體中載入由批次編譯器 ocamlc 產生的位元組碼物件檔案 (.cmo 檔案) 或程式庫檔案 (.cma 檔案)。當載入依賴於其他尚未載入之模組的物件檔案時,也會遞迴搜尋並載入這些模組的 .cmo 檔案。載入順序未指定。
#use "檔案名稱";;
從給定的檔案讀取、編譯和執行原始程式碼片語。這是文字包含:處理程式碼片語的方式與在標準輸入上輸入的方式相同。讀取檔案會在遇到第一個錯誤時停止。
#use_output "命令";;
執行命令並評估其輸出,如同已將其捕獲到檔案並傳遞給 #use
#mod_use "檔案名稱";;
#use 類似,但也會按照編譯器的語義,將程式碼包裝到名稱與大寫的檔案名稱 (不含副檔名) 相同的頂層模組中。

對於將檔案名稱作為參數的指令,如果給定的檔案名稱未指定目錄,則會在以下目錄中搜尋檔案:

  1. 在腳本模式下,會搜尋目前正在執行的腳本所在的目錄;在互動模式下,則搜尋目前的工作目錄。
  2. 使用 #directory 指令加入的目錄。
  3. 在命令列中使用 -I 選項給定的目錄。
  4. 標準函式庫目錄。
環境查詢
#show_class 類別路徑;;
#show_class_type 類別路徑;;
#show_exception 識別符號;;
#show_module 模組路徑;;
#show_module_type 模組類型路徑;;
#show_type 型別建構子;;
#show_val 值路徑;;
印出對應組件的簽名。
#show 識別符號;;
印出所有上述類別中名稱為 識別符號 的組件的簽名。
美化列印
#install_printer 印表機名稱;;
此指令將名為 印表機名稱 的函式 (一個值路徑) 註冊為印表機,用於列印其類型與函式的引數類型相符的值。也就是說,當有此類值要列印時,頂層迴圈會呼叫 印表機名稱

列印函式 印表機名稱 應具有類型 Format.formatter -> t -> unit,其中 t 是要列印的值的類型,並應使用 Format 函式庫提供的函式,在給定的格式器上輸出類型為 t 的值的文字表示形式。為了向後相容性,印表機名稱 也可以具有類型 t -> unit,然後應在標準格式器上輸出,但這種用法已被棄用。

#print_depth n;;
將值的列印限制為最大深度 n。深度超過 n 的值的部分會列印為 ... (省略號)。
#print_length n;;
將列印的值節點數限制為最多 n。值的剩餘部分會列印為 ... (省略號)。
#remove_printer 印表機名稱;;
從頂層印表機表中移除指定的函式。
追蹤
#trace 函式名稱;;
執行此指令後,對名為 函式名稱 的函式的所有呼叫都將被「追蹤」。也就是說,每次呼叫都會顯示引數和結果,以及從函式中逸出的例外狀況,這些例外狀況可能是由函式本身或它呼叫的另一個函式所引發。如果函式是 curried 的,則會在其傳遞給函式時列印每個引數。
#untrace 函式名稱;;
停止追蹤指定的函式。
#untrace_all;;
停止追蹤目前追蹤的所有函式。
編譯器選項
#debug 布林值;;
開啟/關閉插入偵錯事件。預設值為 true
#labels 布林值;;
如果引數為 false,則忽略函式類型中的標籤,如果引數為 true,則切換回預設行為 (交換樣式)。
#ppx "檔案名稱";;
剖析後,透過前處理器命令傳送抽象語法樹。
#principal 布林值;;
如果引數為 true,則在類型檢查期間檢查資訊路徑,以確保所有類型都以主要方式導出。如果引數為 false,則不檢查資訊路徑。
#rectypes;;
在類型檢查期間允許任意遞迴類型。注意:一旦啟用此選項,就無法停用,因為這會導致類型系統不健全。
#warn_error "警告清單";;
將引數啟用的警告視為錯誤,並將引數停用的警告視為正常警告。
#warnings "警告清單";;
根據引數啟用或停用警告。

3 頂層和模組系統

頂層語句可以使用與單獨編譯單元相同的機制來引用在編譯單元中定義的識別符號:透過使用限定名稱 (模組名稱.區域名稱),或使用 open 建構子和非限定名稱 (請參閱第 ‍11.3 節)。

但是,在引用另一個編譯單元之前,該單元的實作必須存在於記憶體中。在啟動時,頂層系統包含標準函式庫中所有模組的實作。使用者模組的實作可以使用上述的 #load 指令輸入。引用未提供實作的單元會導致錯誤 Reference to undefined global `...'

請注意,輸入 open 模組 只會存取 模組 的已編譯介面 (.cmi 檔案),但不會載入 模組 的實作,並且如果沒有載入 模組 的實作,則不會導致任何錯誤。「引用未定義的全域 模組」的錯誤只會在執行引用 模組 的值或模組定義時發生。

4 常見錯誤

本節描述並解釋最常遇到的錯誤訊息。

無法找到檔案 檔案名稱
在目前目錄中或在搜尋路徑的目錄中找不到指定的檔案。

如果 檔案名稱 的格式為 模組.cmi,則表示您已引用編譯單元 模組,但找不到其已編譯的介面。修正:先編譯 模組.mli模組.ml,以建立已編譯的介面 模組.cmi

如果 檔案名稱 的格式為 模組.cmo,則表示您嘗試使用 #load 載入尚不存在的位元組碼物件檔案。修正:先編譯 模組.ml

如果您的程式跨越多個目錄,則也會出現此錯誤,因為您尚未指定要查找的目錄。修正:使用 #directory 指令將正確的目錄新增至搜尋路徑。

此表達式的類型為 t1,但使用時的類型為 t2
請參閱第 ‍13.4 節。
引用未定義的全域 模組
您忽略使用 #load 將模組的實作載入記憶體中。請參閱上方的第 ‍14.3 節。

5 建立自訂頂層系統:ocamlmktop

ocamlmktop 命令會建立在啟動時預先載入使用者程式碼的 OCaml 頂層。

ocamlmktop 命令會將一組 .cmo.cma 檔案作為引數,並將它們與實作 OCaml 頂層的物件檔案連結起來。典型的用法是

        ocamlmktop -o mytoplevel foo.cmo bar.cmo gee.cmo

這會建立位元組碼檔案 mytoplevel,其中包含 OCaml 頂層系統,以及來自三個 .cmo 檔案的程式碼。此頂層可以直接執行,並透過以下方式啟動:

        ./mytoplevel

這會進入常規的頂層迴圈,但來自 foo.cmobar.cmogee.cmo 的程式碼已經載入到記憶體中,就像您輸入了以下內容一樣:

        #load "foo.cmo";;
        #load "bar.cmo";;
        #load "gee.cmo";;

在進入頂層時。模組 FooBarGee 並不會被開啟;如果你希望這樣做,你仍然必須自己執行。

        open Foo;;

你必須自行執行,如果你希望這樣做的話。

5.1 選項

ocamlmktop 可以辨識下列的命令行選項。

-cclib libname
在以「自訂執行時」模式連結時,將 -llibname 選項傳遞給 C 連結器。請參閱第 ‍13 章中 ocamlc 的對應選項。
-ccopt option
在以「自訂執行時」模式連結時,將給定的選項傳遞給 C 編譯器和連結器。請參閱第 ‍13 章中 ocamlc 的對應選項。
-custom
以「自訂執行時」模式連結。請參閱第 ‍13 章中 ocamlc 的對應選項。
-I 目錄
將給定的目錄添加到搜尋已編譯目標碼檔案(.cmo.cma)的目錄清單中。
-o exec-file
指定連結器產生的頂層檔案名稱。預設值為 a.out

6 原生頂層:ocamlnat(實驗性)

本節描述一個尚未正式支援,但可能會覺得有用的工具。

在傳統頂層系統中執行的 OCaml 程式碼使用位元組碼解譯器。當需要更高的效能,或者為了測試只有在編譯為原生程式碼時才能正確執行的程式時,可以使用原生頂層來代替。

對於大多數安裝,原生頂層不會與其餘的 OCaml 工具鏈一起安裝。在這種情況下,有必要從原始碼建置 OCaml 發行版。從發行版的建置原始碼樹中,您可以使用 make natruntop 來建置並執行原生頂層。(或者可以使用 make ocamlnat,它只執行建置步驟。)

如果在建置原生頂層之後執行 make install 命令,則可以直接調用 ocamlnat 程式(來自原始碼或安裝目錄),而不是使用 make natruntop