module Format:sig
..end
美觀列印。
如果您是這個模組的新手,請參閱下方的 範例。
此模組實作了一種美觀列印機制,可在 '美觀列印方塊' 和 '語意標籤' 中格式化數值,並結合一組 類似 printf 的函式。美觀列印器會在指定的 換行提示處分割行,並根據方塊結構縮排行。類似地,語意標籤可用於將文字呈現與其內容分離。
此美觀列印機制實作為抽象 格式器之上的覆蓋層,格式器提供基本的輸出函式。一些格式器是預先定義的,特別是
Format
模組中的大多數函式都有兩種變體:一種短版本,作用於使用 Format.get_std_formatter
取得的目前網域的標準格式器,以及以 pp_
為字首的通用版本,將格式器作為其第一個引數。對於作用於目前網域標準格式器的版本,對 Format.get_std_formatter
的呼叫會延遲到收到最後一個引數時。
可以使用 Format.formatter_of_out_channel
、Format.formatter_of_buffer
、Format.formatter_of_symbolic_output_buffer
或使用 自訂格式器建立更多格式器。
警告:由於 格式器包含可變狀態,因此在沒有同步的情況下,在多個網域上並行使用相同的格式器並不是執行緒安全的。
如果多個網域使用預先定義的格式器(例如透過 Format.get_std_formatter
或 Format.get_err_formatter
取得的)寫入相同的輸出通道,則網域的輸出將在格式器被清除的位置(例如使用 Format.print_flush
)彼此交錯。從 Format.formatter_of_out_channel
(在標準輸出通道或其他通道上)取得的格式器不會執行此同步。
您可以將此模組視為提供 printf
機制的延伸,以提供自動換行。將美觀列印註釋新增到您的常規 printf
格式字串,即可提供精美的縮排和換行。美觀列印註釋在函式 Format.fprintf
的文件中描述如下。
您也可以使用此模組提供的明確美觀列印方塊管理和列印函式。這種樣式比簡潔的 fprintf
格式字串更基本,但也更冗長。
例如,序列 open_box 0; print_string "x ="; print_space ();
在美觀列印方塊中列印
print_int 1; close_box (); print_newline ()x = 1
,可以縮寫為 printf "@[%s@ %i@]@." "x =" 1
,甚至更短的 printf "@[x =@ %i@]@." 1
。
此函式庫的臨時使用者需遵循的原則
open_box 0
取得的);print_cut ()
輸出簡單的換行提示,或透過 print_space ()
輸出表示換行提示的空格而取得的;print_int
和 print_string
)顯示其內容;close_box ()
以關閉方塊;print_newline ()
。如果沒有開啟的美觀列印方塊,則美觀列印命令的行為是不明確的。由以下 open_
函式之一開啟的每個方塊都必須使用 close_box
關閉,才能正確格式化。否則,方塊中列印的某些內容可能不會輸出,或者可能格式不正確。
在互動式使用時,每個短語都會在標準美觀列印器的初始狀態下執行:在每個短語執行之後,互動式系統會關閉所有開啟的美觀列印方塊、清除所有擱置的文字,並重設標準美觀列印器。
警告:將此模組的美觀列印函式呼叫與對 Stdlib
低階輸出函式的呼叫混合使用容易出錯。
美觀列印函式輸出的內容會延遲在美觀列印器佇列中,並堆疊以計算正確的換行。相反地,基本 I/O 輸出函式會直接寫入其輸出裝置。因此,基本 I/O 函式的輸出可能會在之前呼叫的美觀列印函式輸出之前出現。例如,
會產生輸出
Stdlib.print_string "<";
Format.print_string "PRETTY";
Stdlib.print_string ">";
Format.print_string "TEXT";
<>PRETTYTEXT
。
type
formatter
與美觀列印器(也稱為格式器)及其所有機制對應的抽象資料。另請參閱 定義格式器。
美觀列印引擎使用美觀列印方塊和換行提示的概念來驅動美觀列印器的縮排和換行行為。
每個不同的美觀列印方塊種類都會引入特定的換行策略
請注意,換行策略是方塊特定的:方塊的策略不會規則內部方塊的策略。例如,如果垂直方塊巢狀在水平方塊中,則垂直方塊內的所有換行提示都會分割行。
此外,在 最大縮排限制之後開啟方塊會分割行,無論該方塊是否最終符合該行。
val pp_open_box : formatter -> int -> unit
val open_box : int -> unit
pp_open_box ppf d
會在格式器 ppf
中開啟具有偏移量 d
的新壓縮美觀列印方塊。
在此方塊內,美觀列印器會在每一行上盡可能列印內容。
如果該行上沒有更多空間可以列印方塊的其餘部分,則換行提示會分割行。
在此方塊內,美觀列印器會強調方塊結構:如果結構方塊無法完全符合單行,則如果分割「向左移動」(也就是說,新行的縮排小於目前行的縮排),則換行提示也會分割行。
此方塊是一般用途的美觀列印方塊。
如果美觀列印器在方塊中分割行,則會將偏移量 d
新增到目前的縮排。
val pp_close_box : formatter -> unit -> unit
val close_box : unit -> unit
關閉最近開啟的美觀列印方塊。
val pp_open_hbox : formatter -> unit -> unit
val open_hbox : unit -> unit
pp_open_hbox ppf ()
會開啟新的「水平」美觀列印方塊。
此方塊會將內容列印在單行上。
水平方塊中的換行提示永遠不會分割行。(換行仍可能發生在巢狀較深的方塊內)。
val pp_open_vbox : formatter -> int -> unit
val open_vbox : int -> unit
pp_open_vbox ppf d
會開啟具有偏移量 d
的新「垂直」美觀列印方塊。
此方塊會在方塊中盡可能多的行上列印內容作為換行提示。
垂直方塊中的每個換行提示都會分割行。
如果美觀列印器在方塊中分割行,則會將 d
新增到目前的縮排。
val pp_open_hvbox : formatter -> int -> unit
val open_hvbox : int -> unit
pp_open_hvbox ppf d
會開啟具有偏移量 d
的新「水平/垂直」美觀列印方塊。
如果此方塊符合單行,則其行為與水平方塊相同,否則其行為與垂直方塊相同。
如果美觀列印器在方塊中分割行,則會將 d
新增到目前的縮排。
val pp_open_hovbox : formatter -> int -> unit
val open_hovbox : int -> unit
pp_open_hovbox ppf d
會開啟具有偏移量 d
的新「水平或垂直」美觀列印方塊。
此方塊會在每一行上盡可能列印內容。
如果該行上沒有更多空間可以列印方塊的其餘部分,則換行提示會分割行。
如果美觀列印器在方塊中分割行,則會將 d
新增到目前的縮排。
val pp_print_string : formatter -> string -> unit
val print_string : string -> unit
pp_print_string ppf s
會在目前的美觀列印方塊中列印 s
。
val pp_print_bytes : formatter -> bytes -> unit
val print_bytes : bytes -> unit
pp_print_bytes ppf b
會在目前的美觀列印方塊中列印 b
。
val pp_print_as : formatter -> int -> string -> unit
val print_as : int -> string -> unit
pp_print_as ppf len s
會在目前的美觀列印方塊中列印 s
。美觀列印器會將 s
格式化,就像其長度為 len
一樣。
val pp_print_int : formatter -> int -> unit
val print_int : int -> unit
在目前的美觀列印方塊中列印整數。
val pp_print_float : formatter -> float -> unit
val print_float : float -> unit
在目前的美觀列印方塊中列印浮點數。
val pp_print_char : formatter -> char -> unit
val print_char : char -> unit
在目前的美觀列印方塊中列印字元。
val pp_print_bool : formatter -> bool -> unit
val print_bool : bool -> unit
在目前的美觀列印方塊中列印布林值。
val pp_print_nothing : formatter -> unit -> unit
不列印任何內容。
「換行提示」會告訴美觀列印器輸出一些空格或分割行,無論哪種方式更適合目前的列印方塊分割規則。
換行提示用於分隔列印項目,並且必須讓美觀列印器正確分割行並縮排項目。
簡單的換行提示包括
注意:對於美化列印引擎而言,空間和換行的概念是抽象的,因為這些概念可以完全由程式設計師重新定義。但是,在美化列印器的預設設定中,「輸出一個空格」僅表示列印一個空格字元(ASCII 代碼 32),而「換行」表示列印一個換行符號(ASCII 代碼 10)。
val pp_print_space : formatter -> unit -> unit
val print_space : unit -> unit
pp_print_space ppf ()
會發出一個「空格」斷行提示:美化列印器可能會在此處換行,否則會列印一個空格。
pp_print_space ppf ()
等同於 pp_print_break ppf 1 0
。
val pp_print_cut : formatter -> unit -> unit
val print_cut : unit -> unit
pp_print_cut ppf ()
會發出一個「剪切」斷行提示:美化列印器可能會在此處換行,否則不會列印任何內容。
pp_print_cut ppf ()
等同於 pp_print_break ppf 0 0
。
val pp_print_break : formatter -> int -> int -> unit
val print_break : int -> int -> unit
pp_print_break ppf nspaces offset
會發出一個「完整」斷行提示:美化列印器可能會在此處換行,否則會列印 nspaces
個空格。
如果美化列印器換行,則將 offset
加到目前的縮排。
val pp_print_custom_break : formatter ->
fits:string * int * string -> breaks:string * int * string -> unit
pp_print_custom_break ppf ~fits:(s1, n, s2) ~breaks:(s3, m, s4)
會發出一個自訂斷行提示:美化列印器可能會在此處換行。
如果它沒有換行,則會發出 s1
,然後是 n
個空格,然後是 s2
。
如果它換行,則會發出 s3
字串,然後是一個縮排(根據方塊規則),然後是 m
個空格的偏移量,然後是 s4
字串。
雖然 n
和 m
由 formatter_out_functions.out_indent
處理,但字串將由 formatter_out_functions.out_string
處理。這允許自訂格式器以不同的方式處理縮排,例如,輸出 <br/>
標籤或
實體。
如果您想在換行或不換行時更改列印的可见(非空白)字元,則自訂換行很有用。例如,當列印列表 [a; b; c]
時,您可能希望在垂直列印時新增尾隨分號
[
a;
b;
c;
]
您可以按如下方式執行此操作
printf "@[<v 0>[@;<0 2>@[<v 0>a;@,b;@,c@]%t]@]@\n"
(pp_print_custom_break ~fits:("", 0, "") ~breaks:(";", 0, ""))
val pp_force_newline : formatter -> unit -> unit
val force_newline : unit -> unit
在目前的美化列印方塊中強制換行。
美化列印器必須在此處換行。
這不是美化列印的正常方式,因為命令式換行可能會干擾目前的行計數器和方塊大小計算。在封閉的垂直方塊中使用換行提示是更好的選擇。
val pp_print_if_newline : formatter -> unit -> unit
val print_if_newline : unit -> unit
如果前一行剛好被分開,則執行下一個格式化命令。否則,忽略下一個格式化命令。
val pp_print_flush : formatter -> unit -> unit
val print_flush : unit -> unit
美化列印結束:將美化列印器重設為初始狀態。
所有開啟的美化列印方塊都會關閉,所有未處理的文字都會列印。此外,美化列印器的低階輸出裝置會被清除,以確保所有未處理的文字都真正顯示出來。
注意:在美化列印常規過程中,切勿使用 print_flush
,因為美化列印器使用複雜的緩衝機制來正確縮排輸出;在隨機時間手動清除這些緩衝區會與美化列印器策略衝突,並導致呈現效果不佳。
只有在顯示所有未處理的資料是強制性的情況下(例如,在互動式使用中,您希望使用者閱讀某些文字)以及重設美化列印器狀態不會干擾進一步美化列印時,才考慮使用 print_flush
。
警告:如果美化列印器的輸出裝置是輸出通道,則重複呼叫 print_flush
表示重複呼叫 flush
以清除輸出通道;這些明確的清除呼叫可能會阻礙輸出通道的緩衝策略,並可能嚴重影響效率。
val pp_print_newline : formatter -> unit -> unit
val print_newline : unit -> unit
美化列印結束:將美化列印器重設為初始狀態。
所有開啟的美化列印方塊都會關閉,所有未處理的文字都會列印。
等同於 Format.print_flush
,並且在清除裝置之前立即在美化列印器的低階輸出裝置上發出新行。請參閱 Format.print_flush
的相應警示字詞。
注意:這不是輸出新行的正常方式;首選方法是在垂直美化列印方塊中使用換行提示。
val pp_infinity : int
pp_infinity
是邊距的最大大小。其確切值取決於實作,但保證大於 109。
val pp_set_margin : formatter -> int -> unit
val set_margin : int -> unit
pp_set_margin ppf d
將右邊距設定為 d
(以字元為單位):美化列印器會根據給定的換行提示,將超出右邊距的行分開。將邊距設定為 d
表示格式化引擎的目標是每行最多列印 d-1
個字元。如果 d
小於 2,則不會發生任何事。如果 d >=
Format.pp_infinity
,則右邊距設定為 Format.pp_infinity
- 1
。如果 d
小於目前的縮排上限,則會降低縮排上限,同時嘗試保留最小比例 max_indent/margin>=50%
,並且盡可能保留目前的差異 margin - max_indent
。
另請參閱 Format.pp_set_geometry
。
val pp_get_margin : formatter -> unit -> int
val get_margin : unit -> int
傳回右邊距的位置。
val pp_set_max_indent : formatter -> int -> unit
val set_max_indent : int -> unit
pp_set_max_indent ppf d
將行的最大縮排上限設定為 d
(以字元為單位):一旦達到此上限,新的美化列印方塊將被拒絕到左側,除非封閉的方塊完全符合目前的行。如範例所示,
set_margin 10; set_max_indent 5; printf "@[123456@[7@]89A@]@."
產生
123456
789A
因為巢狀方塊 "@[7@]"
是在最大縮排上限 (7>5
) 之後開啟的,並且其父方塊不符合目前的行。您可以減少父方塊的長度以使其符合一行
printf "@[123456@[7@]89@]@."
或在符合目前行的最大縮排上限之前開啟一個中間方塊
printf "@[123@[456@[7@]89@]A@]@."
避免了將內部方塊拒絕到左側,並分別列印 "123456789"
和 "123456789A"
。另請注意,垂直方塊永遠不符合一行,而水平方塊始終完全符合目前的行。開啟方塊可能會分開一行,而內容可能已經符合。如果此行為有問題,可以透過將最大縮排上限設定為 margin - 1
來減少此行為。請注意,將最大縮排上限設定為 margin
是無效的。
如果 d
小於 2,則不會發生任何事。
如果 d
大於目前的邊距,則會忽略它,並保留目前的最大縮排上限。
另請參閱 Format.pp_set_geometry
。
val pp_get_max_indent : formatter -> unit -> int
val get_max_indent : unit -> int
傳回最大縮排上限(以字元為單位)。
幾何函式可用於同時操作耦合變數,即邊距和最大縮排上限。
type
geometry = {
|
max_indent : |
|
margin : |
}
val check_geometry : geometry -> bool
檢查格式器幾何是否有效: 1 < max_indent < margin <
Format.pp_infinity
val pp_set_geometry : formatter -> max_indent:int -> margin:int -> unit
val set_geometry : max_indent:int -> margin:int -> unit
val pp_safe_set_geometry : formatter -> max_indent:int -> margin:int -> unit
val safe_set_geometry : max_indent:int -> margin:int -> unit
pp_set_geometry ppf ~max_indent ~margin
設定 ppf
的邊距和最大縮排上限。
當 1 < max_indent < margin <
Format.pp_infinity
時,pp_set_geometry ppf ~max_indent ~margin
等同於 pp_set_margin ppf margin; pp_set_max_indent ppf max_indent
;並避免細微不正確的 pp_set_max_indent ppf max_indent; pp_set_margin ppf margin
;
在此網域之外,pp_set_geometry
會引發無效引數例外,而 pp_safe_set_geometry
則不會執行任何動作。
val pp_update_geometry : formatter -> (geometry -> geometry) -> unit
pp_update_geometry ppf (fun geo -> { geo with ... })
可讓您以對 geometry
記錄的新欄位擴充具有強大適應性的方式更新格式器的幾何。
如果傳回的幾何不滿足 Format.check_geometry
,則會引發無效引數例外。
val update_geometry : (geometry -> geometry) -> unit
val pp_get_geometry : formatter -> unit -> geometry
val get_geometry : unit -> geometry
傳回格式器的目前幾何
最大格式化深度是同時開啟的美化列印方塊的最大數目。
較深巢狀方塊內的材料會列印為省略號(更精確地說是 Format.get_ellipsis_text
()
傳回的文字)。
val pp_set_max_boxes : formatter -> int -> unit
val set_max_boxes : int -> unit
pp_set_max_boxes ppf max
設定同時開啟的美化列印方塊的最大數目。
較深巢狀方塊內的材料會列印為省略號(更精確地說是 Format.get_ellipsis_text
()
傳回的文字)。
如果 max
小於 2,則不會發生任何事。
val pp_get_max_boxes : formatter -> unit -> int
val get_max_boxes : unit -> int
傳回允許省略號之前允許的最大美化列印方塊數。
val pp_over_max_boxes : formatter -> unit -> bool
val over_max_boxes : unit -> bool
測試是否已開啟允許的最大美化列印方塊數。
定位標籤方塊在分為固定長度的儲存格的行上列印材料。定位標籤方塊提供了一種簡單的方法來顯示左對齊文字的垂直欄。
此方塊具有命令 set_tab
來定義儲存格邊界,以及命令 print_tab
來從儲存格移動到儲存格,並且當行中沒有更多儲存格要列印時分割行。
注意:在定位標籤方塊中列印是以行定向的,因此定位標籤方塊內的任意行分割會導致呈現效果不佳。但是,在模組 Format
中控制使用定位標籤方塊允許簡單列印欄。
val pp_open_tbox : formatter -> unit -> unit
val open_tbox : unit -> unit
open_tbox ()
開啟新的定位標籤方塊。
此方塊會將行分割為固定寬度的儲存格列印。
在定位標籤方塊內,特殊的定位標籤標記會定義行上的關注點(例如,分隔儲存格邊界)。函式 Format.set_tab
在插入點設定定位標籤標記。
定位標籤方塊具有特定的定位標籤換行,以移動到下一個定位標籤標記或分割行。函式 Format.print_tbreak
會列印定位標籤換行。
val pp_close_tbox : formatter -> unit -> unit
val close_tbox : unit -> unit
關閉最近開啟的定位標籤方塊。
val pp_set_tab : formatter -> unit -> unit
val set_tab : unit -> unit
在目前的插入點設定定位標籤標記。
val pp_print_tab : formatter -> unit -> unit
val print_tab : unit -> unit
print_tab ()
會發出「下一個」定位標籤換行提示:如果尚未設定在定位標籤標記上,則插入點會移動到右側的第一個定位標籤標記,或美化列印器分割行,且插入點會移動到最左側的定位標籤標記。
它等同於 print_tbreak 0 0
。
val pp_print_tbreak : formatter -> int -> int -> unit
val print_tbreak : int -> int -> unit
print_tbreak nspaces offset
會發出一個「完整」的跳格中斷提示。
如果跳格標記上尚未設定,插入點會移至右側第一個跳格標記,並且美化列印器會印出 nspaces
個空格。
如果右側沒有下一個跳格標記,美化列印器會在該點分割行,然後插入點會移至方塊最左邊的跳格標記。
如果美化列印器換行,則將 offset
加到目前的縮排。
val pp_set_ellipsis_text : formatter -> string -> unit
val set_ellipsis_text : string -> unit
設定當開啟過多的美化列印方塊時,所列印的省略符號文字(預設為單一點號 .
)。
val pp_get_ellipsis_text : formatter -> unit -> string
val get_ellipsis_text : unit -> string
傳回省略符號的文字。
type
stag = ..
語意標籤(或簡稱 標籤)是用戶定義的註釋,用於將用戶特定的操作關聯到列印的實體。
語意標籤的常見用法是文字裝飾,以取得顯示裝置的特定字型或文字大小呈現,或標記實體的界限(例如 HTML 或 TeX 元素或終端跳脫序列)。更複雜的語意標籤用法可以處理美化列印器行為的動態修改,以正確列印某些特定標籤內的內容。例如,我們可以這樣定義一個 RGB 標籤
type stag += RGB of {r:int;g:int;b:int}
為了正確界定列印的實體,語意標籤必須在實體之前開啟,在實體之後關閉。語意標籤必須像使用 Format.pp_open_stag
和 Format.pp_close_stag
的括號一樣正確巢狀排列。
標籤特定操作會在每次開啟或關閉標籤時發生。每次發生時,都會執行兩種操作:標籤標記和標籤列印
粗略地說,標籤標記通常用於在呈現裝置中獲得更好的文字呈現,而標籤列印允許微調列印常式,根據語意標籤以不同的方式列印相同的實體(即列印額外內容,甚至省略部分輸出)。
更精確地說:當開啟或關閉語意標籤時,會連續發生「標籤列印」和「標籤標記」操作
print_open_stag
(或 print_close_stag
):然後該標籤列印函式可以將任何常規內容列印到格式化器(以便此內容像往常一樣在格式化器佇列中排隊,以進行進一步的行分割計算)。mark_open_stag
(或 mark_close_stag
):然後該標籤標記函式可以傳回「標籤開啟標記」(或「標籤關閉標記」),以便直接輸出到格式化器的輸出裝置。由於直接寫入格式化器的輸出裝置,因此語意標籤標記字串不被視為驅動行分割的列印內容的一部分(換句話說,對行分割而言,對應於標籤標記的字串長度視為零)。
因此,語意標籤處理在某種意義上對於美化列印是透明的,並且不會干擾正常的縮排。因此,單一美化列印常式可以根據標籤的處理方式,輸出簡單的「逐字」內容或更豐富的裝飾輸出。預設情況下,標籤不啟用,因此輸出不會使用標籤資訊進行裝飾。一旦將 set_tags
設定為 true
,美化列印器引擎就會遵循標籤並相應地裝飾輸出。
預設標籤標記函式的行為與 HTML 相同:字串標籤會以 "<" 和 ">" 包圍,而其他標籤會被忽略;因此,標籤字串 "t"
的開啟標記是 "<t>"
,而關閉標記是 "</t>"
。
預設標籤列印函式不會執行任何操作。
標籤標記和標籤列印函式是使用者可定義的,可以透過呼叫 Format.set_formatter_stag_functions
來設定。
可以使用 Format.set_tags
開啟或關閉語意標籤操作。可以使用 Format.set_mark_tags
開啟或關閉標籤標記操作。可以使用 Format.set_print_tags
開啟或關閉標籤列印操作。
typetag =
string
type
stag +=
| |
String_tag of |
(* |
| *) |
val pp_open_stag : formatter -> stag -> unit
val open_stag : stag -> unit
pp_open_stag ppf t
開啟名為 t
的語意標籤。
格式化器的 print_open_stag
標籤列印函式會以 t
作為引數呼叫;然後,mark_open_stag t
提供的 t
的開啟標籤標記會寫入格式化器的輸出裝置。
val pp_close_stag : formatter -> unit -> unit
val close_stag : unit -> unit
pp_close_stag ppf ()
關閉最近開啟的語意標籤 t
。
由 mark_close_stag t
提供的關閉標籤標記會寫入格式化器的輸出裝置;然後,格式化器的 print_close_stag
標籤列印函式會以 t
作為引數呼叫。
formatter -> bool -> unit
: bool -> unit
: pp_set_tags ppf b
開啟或關閉語意標籤的處理(預設為關閉)。
formatter -> bool -> unit
: bool -> unit
: pp_set_print_tags ppf b
開啟或關閉標籤列印操作。
formatter -> bool -> unit
: bool -> unit
: pp_set_mark_tags ppf b
開啟或關閉標籤標記操作。
formatter -> unit -> bool
: unit -> bool
: 傳回標籤列印操作的目前狀態。
formatter -> unit -> bool
: unit -> bool
: 傳回標籤標記操作的目前狀態。
val pp_set_formatter_out_channel : formatter -> out_channel -> unit
val set_formatter_out_channel : out_channel -> unit
將標準美化列印器輸出重新導向至給定的通道。(標準格式化器的所有輸出函式都會設定為列印到給定通道的預設輸出函式。)
set_formatter_out_channel
等同於 Format.pp_set_formatter_out_channel
std_formatter
。
val pp_set_formatter_output_functions : formatter -> (string -> int -> int -> unit) -> (unit -> unit) -> unit
val set_formatter_output_functions : (string -> int -> int -> unit) -> (unit -> unit) -> unit
pp_set_formatter_output_functions ppf out flush
將標準美化列印器的輸出函式重新導向至函式 out
和 flush
。
out
函式會執行所有美化列印器的字串輸出。它會使用字串 s
、起始位置 p
和字元數 n
來呼叫;它應該輸出 s
的字元 p
到 p + n - 1
。
每當美化列印器被刷新時(透過轉換 %!
,或美化列印指示 @?
或 @.
,或使用低階函式 print_flush
或 print_newline
)都會呼叫 flush
函式。
val pp_get_formatter_output_functions : formatter -> unit -> (string -> int -> int -> unit) * (unit -> unit)
val get_formatter_output_functions : unit -> (string -> int -> int -> unit) * (unit -> unit)
傳回標準美化列印器的目前輸出函式。
Format
模組功能非常強大,可讓您完全重新定義美化列印輸出的意義:您可以提供自己的函式來定義如何處理縮排、行分割,甚至是必須列印的所有字元的列印!
type
formatter_out_functions = {
|
out_string : |
|||
|
out_flush : |
|||
|
out_newline : |
|||
|
out_spaces : |
|||
|
out_indent : |
(* |
| *) |
}
特定於格式化器的輸出函式集
out_string
函式會執行所有美化列印器的字串輸出。它會使用字串 s
、起始位置 p
和字元數 n
來呼叫;它應該輸出 s
的字元 p
到 p + n - 1
。out_flush
函式會刷新美化列印器輸出裝置。out_newline
來開啟新行。out_spaces
函式會輸出空格。它會使用要輸出的空格數來呼叫。out_indent
函式會執行新行縮排。它會使用新行的縮排值來呼叫。預設情況下
out_string
和 out_flush
是特定於輸出裝置的;(例如,output_string
和 flush
用於 out_channel
裝置,或 Buffer.add_substring
和 ignore
用於 Buffer.t
輸出裝置),out_newline
等同於 out_string "\n" 0 1
;out_spaces
和 out_indent
等同於 out_string (String.make n ' ') 0 n
。val pp_set_formatter_out_functions : formatter -> formatter_out_functions -> unit
val set_formatter_out_functions : formatter_out_functions -> unit
pp_set_formatter_out_functions ppf out_funs
將 ppf
的所有美化列印器輸出函式設定為引數 out_funs
的函式,
這樣,您可以變更縮排的意義(可以是除了僅列印空格字元以外的其他內容)和開啟新行的意義(可以連接到應用程式手邊需要的任何其他動作)。
函式 out_spaces
和 out_newline
的合理預設值分別為 out_funs.out_string (String.make n ' ') 0 n
和 out_funs.out_string "\n" 0 1
。
val pp_get_formatter_out_functions : formatter -> unit -> formatter_out_functions
val get_formatter_out_functions : unit -> formatter_out_functions
傳回美化列印器的目前輸出函式,包括行分割和縮排函式。用於記錄目前設定並在之後還原它。
type
formatter_stag_functions = {
|
mark_open_stag : |
|
mark_close_stag : |
|
print_open_stag : |
|
print_close_stag : |
}
格式器特定的語義標籤處理函數:mark
版本是「標籤標記」函數,它將字串標記與標籤關聯,以便美化列印引擎將這些標記作為長度為 0 的符號寫入格式器的輸出裝置。print
版本是「標籤列印」函數,可以在標籤關閉或開啟時執行常規列印。
val pp_set_formatter_stag_functions : formatter -> formatter_stag_functions -> unit
val set_formatter_stag_functions : formatter_stag_functions -> unit
pp_set_formatter_stag_functions ppf tag_funs
變更開啟和關閉語義標籤操作的含義,以便在 ppf
上列印時使用 tag_funs
中的函數。
當開啟名稱為 t
的語義標籤時,字串 t
會傳遞給開啟標籤標記函數(tag_funs
記錄的 mark_open_stag
欄位),該函數必須傳回該名稱的開啟標籤標記。當下一次呼叫 close_stag ()
時,語義標籤名稱 t
會傳回給關閉標籤標記函數(tag_funs
記錄的 mark_close_stag
欄位),該函數必須傳回該名稱的關閉標籤標記。
記錄的 print_
欄位包含標籤列印函數,這些函數在標籤開啟和標籤關閉時呼叫,以便在美化列印佇列中輸出常規資料。
val pp_get_formatter_stag_functions : formatter -> unit -> formatter_stag_functions
val get_formatter_stag_functions : unit -> formatter_stag_functions
傳回標準美化列印器的目前語義標籤操作函數。
定義新的格式器允許在多個輸出裝置上並行輸出不相關的資料。格式器的所有參數都是格式器本機的:右邊距、最大縮排限制、同時開啟的美化列印方塊的最大數量、省略符號等等,都專屬於每個格式器,並且可以獨立固定。
例如,假設有一個 Buffer.t
緩衝區 b
,Format.formatter_of_buffer
b
會傳回一個新的格式器,使用緩衝區 b
作為其輸出裝置。類似地,假設有一個 out_channel
輸出通道 oc
,Format.formatter_of_out_channel
oc
會傳回一個新的格式器,使用通道 oc
作為其輸出裝置。
或者,假設給定 out_funs
,格式器的一組完整輸出函數,則 Format.formatter_of_out_functions
out_funs
會使用這些函數進行輸出,計算出一個新的格式器。
val formatter_of_out_channel : out_channel -> formatter
formatter_of_out_channel oc
會傳回一個新的格式器,該格式器會寫入對應的輸出通道 oc
。
val synchronized_formatter_of_out_channel : out_channel -> formatter Domain.DLS.key
synchronized_formatter_of_out_channel oc
會傳回域本機狀態的索引鍵,該狀態會保留寫入對應輸出通道 oc
的域本機格式器。
當格式器與多個域一起使用時,來自域的輸出將在格式器刷新的點上相互交錯,例如使用 Format.print_flush
時。
val std_formatter : formatter
初始域的標準格式器,用於寫入標準輸出。
val get_std_formatter : unit -> formatter
get_std_formatter ()
會傳回目前域的標準格式器,該格式器用於寫入標準輸出。
val err_formatter : formatter
初始域的格式器,用於寫入標準錯誤。
val get_err_formatter : unit -> formatter
get_err_formatter ()
會傳回目前域的格式器,該格式器用於寫入標準錯誤。
val formatter_of_buffer : Buffer.t -> formatter
formatter_of_buffer b
會傳回一個新的格式器,該格式器會寫入緩衝區 b
。在美化列印結束時,必須使用 Format.pp_print_flush
或 Format.pp_print_newline
刷新格式器,才能將所有擱置的資料列印到緩衝區中。
val stdbuf : Buffer.t
初始域的字串緩衝區,其中 str_formatter
會寫入。
val get_stdbuf : unit -> Buffer.t
get_stdbuf ()
會傳回目前域的字串緩衝區,其中目前域的字串格式器會寫入。
val str_formatter : formatter
初始域的格式器,用於輸出到 Format.stdbuf
字串緩衝區。
str_formatter
定義為 Format.formatter_of_buffer
Format.stdbuf
。
val get_str_formatter : unit -> formatter
目前域的格式器,用於輸出到目前域的字串緩衝區。
val flush_str_formatter : unit -> string
傳回使用目前域的 str_formatter
列印的資料,刷新格式器並重設對應的緩衝區。
val make_formatter : (string -> int -> int -> unit) -> (unit -> unit) -> formatter
make_formatter out flush
會傳回一個新的格式器,該格式器會使用函數 out
進行輸出,並使用函數 flush
進行刷新。
例如,
make_formatter
(Stdlib.output_substring oc)
(fun () -> Stdlib.flush oc)
傳回寫入 out_channel
oc
的格式器。
val make_synchronized_formatter : (string -> int -> int -> unit) ->
(unit -> unit) -> formatter Domain.DLS.key
make_synchronized_formatter out flush
會傳回域本機狀態的索引鍵,該狀態會保留域本機格式器,該格式器會使用函數 out
進行輸出,並使用函數 flush
進行刷新。
當格式器與多個域一起使用時,來自域的輸出將在格式器刷新的點上相互交錯,例如使用 Format.print_flush
時。
val formatter_of_out_functions : formatter_out_functions -> formatter
formatter_of_out_functions out_funs
會傳回一個新的格式器,該格式器會使用一組輸出函數 out_funs
進行寫入。
如需引數 out_funs
的含義,請參閱類型 Format.formatter_out_functions
的定義。
符號美化列印是使用符號格式器進行的美化列印,也就是說,格式器會輸出符號美化列印項目。
當使用符號格式器時,所有常規美化列印活動都會發生,但輸出資料是符號的,並且儲存在輸出項目的緩衝區中。在美化列印結束時,刷新輸出緩衝區允許在執行低階輸出操作之前,對符號輸出進行後處理。
實際上,首先使用
let sob = make_symbolic_output_buffer ()
定義符號輸出緩衝區 b
。然後使用let ppf = formatter_of_symbolic_output_buffer sob
定義符號格式器。像平常一樣使用符號格式器 ppf
,並在美化列印結束時,透過使用
flush_symbolic_output_buffer sob
.type
symbolic_output_item =
| |
刷新符號輸出緩衝區 |
(* | Output_flush | *) |
| |
符號刷新命令 |
(* | Output_newline | *) |
| |
符號換行命令 |
(* | Output_string of | *) |
| |
|
(* | Output_spaces of | *) |
| |
|
(* | Output_indent of | *) |
Output_indent i
:大小為 i
的符號縮排
type
symbolic_output_buffer
符號美化列印器產生的項目
val make_symbolic_output_buffer : unit -> symbolic_output_buffer
符號美化列印器的輸出緩衝區。
val clear_symbolic_output_buffer : symbolic_output_buffer -> unit
make_symbolic_output_buffer ()
會傳回新的符號輸出緩衝區。
val get_symbolic_output_buffer : symbolic_output_buffer -> symbolic_output_item list
clear_symbolic_output_buffer sob
會重設緩衝區 sob
。
val flush_symbolic_output_buffer : symbolic_output_buffer -> symbolic_output_item list
get_symbolic_output_buffer sob
會傳回緩衝區 sob
的內容。
val add_symbolic_output_item : symbolic_output_buffer -> symbolic_output_item -> unit
flush_symbolic_output_buffer sob
會傳回緩衝區 sob
的內容,並重設緩衝區 sob
。flush_symbolic_output_buffer sob
等同於 let items = get_symbolic_output_buffer sob in
clear_symbolic_output_buffer sob; items
val formatter_of_symbolic_output_buffer : symbolic_output_buffer -> formatter
add_symbolic_output_item sob itm
會將項目 itm
新增至緩衝區 sob
。
val pp_print_iter : ?pp_sep:(formatter -> unit -> unit) ->
(('a -> unit) -> 'b -> unit) ->
(formatter -> 'a -> unit) -> formatter -> 'b -> unit
formatter_of_symbolic_output_buffer sob
會傳回將輸出寫入 symbolic_output_buffer
sob
的符號格式器。
val pp_print_list : ?pp_sep:(formatter -> unit -> unit) ->
(formatter -> 'a -> unit) -> formatter -> 'a list -> unit
pp_print_iter ~pp_sep iter pp_v ppf v
會使用 pp_v
在 ppf
上格式化 iter
對值集合 v
的反覆運算。反覆運算會以 pp_sep
分隔(預設為 Format.pp_print_cut
)。
val pp_print_array : ?pp_sep:(formatter -> unit -> unit) ->
(formatter -> 'a -> unit) -> formatter -> 'a array -> unit
pp_print_list ?pp_sep pp_v ppf l
會列印清單 l
的項目,使用 pp_v
列印每個項目,並在項目之間呼叫 pp_sep
(pp_sep
預設為 Format.pp_print_cut
)。在空清單上不做任何動作。
pp_print_array ?pp_sep pp_v ppf a
會列印陣列 a
的項目,使用 pp_v
列印每個項目,並在項目之間呼叫 pp_sep
(pp_sep
預設為 Format.pp_print_cut
)。在空陣列上不做任何動作。
val pp_print_seq : ?pp_sep:(formatter -> unit -> unit) ->
(formatter -> 'a -> unit) ->
formatter -> 'a Seq.t -> unit
如果在呼叫 pp_print_array
後修改了 a
,列印的值可能不是預期的值,因為 Format
可以延遲列印。可以透過刷新 ppf
來避免這種情況。
pp_print_seq ?pp_sep pp_v ppf s
會列印序列 s
的項目,使用 pp_v
列印每個項目,並在項目之間呼叫 pp_sep
(pp_sep
預設為 Format.pp_print_cut
)。在空序列上不做任何動作。
val pp_print_text : formatter -> string -> unit
此函數不會在無限序列上終止。
val pp_print_option : ?none:(formatter -> unit -> unit) ->
(formatter -> 'a -> unit) -> formatter -> 'a option -> unit
pp_print_text ppf s
會列印 s
,並分別使用 Format.pp_print_space
和 Format.pp_force_newline
列印空格和換行符號。
val pp_print_result : ok:(formatter -> 'a -> unit) ->
error:(formatter -> 'e -> unit) ->
formatter -> ('a, 'e) result -> unit
pp_print_result ~ok ~error ppf r
會在 ppf
上印出 r
,如果 r
是 Ok _
,則使用 ok
,如果 r
是 Error _
,則使用 error
。
val pp_print_either : left:(formatter -> 'a -> unit) ->
right:(formatter -> 'b -> unit) ->
formatter -> ('a, 'b) Either.t -> unit
pp_print_either ~left ~right ppf e
會在 ppf
上印出 e
,如果 e
是 Either.Left _
,則使用 left
,如果 e
是 Either.Right _
,則使用 right
。
模組 Format
提供了一整套類似 printf
的函數,用於使用格式字串規範進行美化列印。
可以在格式字串中新增特定的註解,以向美化列印引擎發出美化列印命令。
這些註解在格式字串中使用 @
字元引入。例如,@
表示空格分隔符,@,
表示斷點,@[
開啟一個新的方塊,而 @]
關閉最後一個開啟的方塊。
val fprintf : formatter -> ('a, formatter, unit) format -> 'a
fprintf ff fmt arg1 ... argN
根據格式字串 fmt
格式化引數 arg1
到 argN
,並將結果字串輸出到格式化器 ff
。
格式字串 fmt
是一個字元字串,其中包含三種類型的物件:純文字字元和 Printf
模組中指定的轉換規範,以及 Format
模組特有的美化列印指示。
美化列印指示字元以 @
字元引入,其含義如下:
@[
:開啟一個美化列印方塊。方塊的類型和偏移量可以選擇使用以下語法指定:<
字元,後跟一個可選的方塊類型指示,然後是一個可選的整數偏移量,以及結尾的 >
字元。美化列印方塊類型為 h
、v
、hv
、b
或 hov
。'h
' 代表「水平」美化列印方塊,'v
' 代表「垂直」美化列印方塊,'hv
' 代表「水平/垂直」美化列印方塊,'b
' 代表展示縮排的「水平或垂直」美化列印方塊,'hov
' 代表簡單的「水平或垂直」美化列印方塊。例如,@[<hov 2>
開啟一個帶有縮排 2 的「水平或垂直」美化列印方塊,這與使用 open_hovbox 2
獲得的結果相同。有關美化列印方塊的更多詳細資訊,請參閱各種方塊開啟函數 open_*box
。@]
:關閉最近開啟的美化列印方塊。@,
:輸出「斷點」提示,與 print_cut ()
相同。@
:輸出「空格」斷點提示,與 print_space ()
相同。@;
:輸出「完整」斷點提示,與 print_break
相同。斷點提示的 nspaces
和 offset
參數可以選擇使用以下語法指定:<
字元,後跟一個整數 nspaces
值,然後是一個整數 offset
,以及結尾的 >
字元。如果未提供任何參數,則完整斷點預設為「空格」斷點提示。@.
:刷新美化列印器並拆分行,與 print_newline ()
相同。@<n>
:將以下項目列印為長度為 n
。因此,printf "@<0>%s" arg
將 arg
列印為零長度字串。如果 @<n>
後面沒有跟隨轉換規範,則將格式的下一個字元列印為長度為 n
。@{
:開啟一個語意標籤。標籤的名稱可以選擇使用以下語法指定:<
字元,後跟一個可選的字串規範,以及結尾的 >
字元。字串規範是不包含結尾字元 '>'
的任何字元字串。如果省略,則標籤名稱預設為空字串。有關語意標籤的更多詳細資訊,請參閱函數 Format.open_stag
和 Format.close_stag
。@}
:關閉最近開啟的語意標籤。@?
:刷新美化列印器,與 print_flush ()
相同。這等同於轉換 %!
。@\n
:強制換行,與 force_newline ()
相同,這不是美化列印的正常方式,您應該優先在垂直美化列印方塊內使用斷點提示。注意:為了防止將 @
字元解釋為美化列印指示,請使用 %
字元將其跳脫。舊的引號模式 @@
已被棄用,因為它與字元 '@'
的格式化輸入解釋不相容。
範例:printf "@[%s@ %d@]@." "x =" 1
等效於 open_box (); print_string "x ="; print_space ();
。它在美化列印的「水平或垂直」方塊內列印
print_int 1; close_box (); print_newline ()x = 1
。
val printf : ('a, formatter, unit) format -> 'a
與上面的 fprintf
相同,但輸出到 get_std_formatter ()
。
它與 fun fmt -> fprintf (get_std_formatter ()) fmt
的定義類似,但會延遲呼叫 get_std_formatter
,直到收到 format
所需的最後一個引數。當與多個域一起使用時,來自這些域的輸出將在格式化器被刷新的點(例如使用 Format.print_flush
時)相互交錯。
val eprintf : ('a, formatter, unit) format -> 'a
與上面的 fprintf
相同,但輸出到 get_err_formatter ()
。
它與 fun fmt -> fprintf (get_err_formatter ()) fmt
的定義類似,但會延遲呼叫 get_err_formatter
,直到收到 format
所需的最後一個引數。當與多個域一起使用時,來自這些域的輸出將在格式化器被刷新的點(例如使用 Format.print_flush
時)相互交錯。
val sprintf : ('a, unit, string) format -> 'a
與上面的 printf
相同,但不是列印到格式化器,而是傳回一個包含引數格式化結果的字串。請注意,美化列印器佇列會在每次呼叫 sprintf
結束時刷新。請注意,如果您的格式字串包含 %a
,您應該使用 asprintf
。
如果在單個字串上輸出資料的多個相關呼叫 sprintf
的情況下,您應該考慮使用帶有預定義格式化器 str_formatter
的 fprintf
,並呼叫 flush_str_formatter ()
以取得最終結果。
或者,您可以使用 Format.fprintf
與一個寫入您自己的緩衝區的格式化器:在美化列印結束時刷新格式化器和緩衝區會傳回所需的字串。
val asprintf : ('a, formatter, unit, string) format4 -> 'a
與上面的 printf
相同,但不是列印到格式化器,而是傳回一個包含引數格式化結果的字串。asprintf
的類型非常通用,可以很好地與 %a
轉換互動。
val dprintf : ('a, formatter, unit, formatter -> unit) format4 -> 'a
與 Format.fprintf
相同,只是格式化器是最後一個引數。dprintf "..." a b c
是一個類型為 formatter -> unit
的函數,可以將其提供給格式規範符 %t
。
這可以用來替代 Format.asprintf
以延遲格式化決策。在格式化上下文中使用 Format.asprintf
傳回的字串會強制隔離進行格式化決策,並可能過早建立最終字串。Format.dprintf
允許延遲格式化決策,直到知道最終的格式化上下文。例如
let t = Format.dprintf "%i@ %i@ %i" 1 2 3 in
...
Format.printf "@[<v>%t@]" t
val ifprintf : formatter -> ('a, formatter, unit) format -> 'a
與上面的 fprintf
相同,但不列印任何內容。在有條件列印時忽略某些資料很有用。
使用續體的格式化美化列印。
val kfprintf : (formatter -> 'a) ->
formatter -> ('b, formatter, unit, 'a) format4 -> 'b
與上面的 fprintf
相同,但不會立即傳回,而是在列印結束時將格式化器傳遞給其第一個引數。
val kdprintf : ((formatter -> unit) -> 'a) ->
('b, formatter, unit, 'a) format4 -> 'b
與上面的 Format.dprintf
相同,但不會立即傳回,而是在列印結束時將暫停的列印器傳遞給其第一個引數。
val ikfprintf : (formatter -> 'a) ->
formatter -> ('b, formatter, unit, 'a) format4 -> 'b
與上面的 kfprintf
相同,但不列印任何內容。在有條件列印時忽略某些資料很有用。
val ksprintf : (string -> 'a) -> ('b, unit, string, 'a) format4 -> 'b
與上面的 sprintf
相同,但不是傳回字串,而是將字串傳遞給第一個引數。
val kasprintf : (string -> 'a) -> ('b, formatter, unit, 'a) format4 -> 'b
與上面的 asprintf
相同,但不是傳回字串,而是將字串傳遞給第一個引數。
一些熱身範例,以了解如何使用 Format。
我們有一個配對 (int * bool)
的列表 l
,頂層會為我們列印出來
# let l = List.init 20 (fun n -> n, n mod 2 = 0)
val l : (int * bool) list =
[(0, true); (1, false); (2, true); (3, false); (4, true); (5, false);
(6, true); (7, false); (8, true); (9, false); (10, true); (11, false);
(12, true); (13, false); (14, true); (15, false); (16, true); (17, false);
(18, true); (19, false)]
如果我們想自己列印,而不需要頂層的魔法,我們可以嘗試這樣做
# let pp_pair out (x,y) = Format.fprintf out "(%d, %b)" x y
val pp_pair : Format.formatter -> int * bool -> unit = <fun>
# Format.printf "l: [@[<hov>%a@]]@."
Format.(pp_print_list ~pp_sep:(fun out () -> fprintf out ";@ ") pp_pair) l
l: [(0, true); (1, false); (2, true); (3, false); (4, true); (5, false);
(6, true); (7, false); (8, true); (9, false); (10, true); (11, false);
(12, true); (13, false); (14, true); (15, false); (16, true);
(17, false); (18, true); (19, false)]
簡而言之,這樣做是
pp_pair
列印一個用 "(" ")" 包圍的配對 bool*int
。它會取得一個格式化器(發生格式化的位置)和配對本身。列印完成後,它會傳回 ()
。Format.printf "l = [@[<hov>%a@]]@." ... l
類似於 printf
,但具有額外的格式化指示(以 "@" 表示)。配對 "@[<hov>
" 和 "@]
" 是一個「水平或垂直方塊」。Format.formatter
的狀態。請勿將 "\n" 與 Format
一起使用。printf
的 "%d" 或 "%s"。但是,當 "%d" 列印一個整數,而 "%s" 列印一個字串時,"%a" 會取得一個列印器(類型為 Format.formatter -> 'a -> unit
)和一個值(類型為 'a
),並將列印器應用於該值。這是列印器組成的關鍵。Format.pp_print_list ~pp_sep:(...) pp_pair
來建構一個列表印表機。pp_print_list
接收一個元素印表機並返回一個列表印表機。如果提供可選參數 ?pp_sep
,則會在每個元素之間調用它來印出分隔符號。(fun out () -> Format.fprintf out ";@ ")
。它會印出 ";",然後印出 "@ ",這是一個可斷行的空白(它會印出 " ",如果方塊即將溢出,則會印出換行符號)。這個 "@ " 負責將列表印成多行。如果我們省略 "@ ",我們會得到一個醜陋的單行印出結果
# Format.printf "l: [@[<hov>%a@]]@."
Format.(pp_print_list ~pp_sep:(fun out () -> fprintf out "; ") pp_pair) l
l: [(0, true); (1, false); (2, true); (* ... *); (18, true); (19, false)]
- : unit = ()
一般來說,為你的程式中的重要類型定義自訂印表機是一個好習慣。例如,如果你要定義像這樣的基本幾何類型
type point = {
x: float;
y: float;
}
type rectangle = {
ll: point; (* lower left *)
ur: point; (* upper right *)
}
為了除錯目的,或在日誌或主控台上顯示資訊,為這些類型定義印表機將會很方便。以下是如何做到的一個例子。請注意,"%.3f" 是一個 float
印表機,在小數點後保留 3 位數的精度;"%f" 將會印出所有需要的位數,這有點冗長;"%h" 是一個十六進位的浮點數印表機。
let pp_point out (p:point) =
Format.fprintf out "{ @[x=%.3f;@ y=%.3f@] }" p.x p.y
let pp_rectangle out (r:rectangle) =
Format.fprintf out "{ @[ll=%a;@ ur=%a@] }"
pp_point r.ll pp_point r.ur
在 .mli
檔案中,我們可以有
val pp_point : Format.formatter -> point -> unit
val pp_rectangle : Format.formatter -> rectangle -> unit
這些印表機現在可以在其他印表機中使用 "%a"。
# Format.printf "some rectangle: %a@."
(Format.pp_print_option pp_rectangle)
(Some {ll={x=1.; y=2.}; ur={x=42.; y=500.12345}})
some rectangle: { l={ x=1.000; y=2.000 }; ur={ x=42.000; y=500.123 } }
# Format.printf "no rectangle: %a@."
(Format.pp_option pp_rectangle)
None
no rectangle:
看看我們如何結合 pp_print_option
(option 印表機) 和我們新定義的矩形印表機,就像我們之前使用 pp_print_list
一樣。
如需更詳細的教學,請參閱 "使用 Format 模組"。
最後一點:Format
模組是一個起點。OCaml 生態系統擁有許多函式庫,可以讓格式化更容易且更具表達力,並提供更多的組合器、更簡潔的名稱等等。這樣的一個函式庫的例子是 Fmt。
也可以使用 https://github.com/ocaml-ppx/ppx_deriving 或類似的 ppx deriver 從類型定義自動衍生出漂亮的印表機。