第 12 章 語言擴展

12 屬性

(在 OCaml 4.02 中引入,4.03 中為表達式以外的建構新增了中綴表示法)

屬性是語法樹的「裝飾」,主要被類型檢查器忽略,但可以被外部工具使用。屬性由識別符和有效負載組成,有效負載可以是結構、類型表達式(以:為前綴)、簽名(以:為前綴)或模式(以?為前綴),可選地後面跟著 when 子句

attr-id::= lowercase-ident
   capitalized-ident
   attr-id.attr-id
 
attr-payload::=[ module-items ]
   :typexpr
   : [ specification ]
   ?pattern [whenexpr]
 

第一種形式的屬性附加在「代數」類別的後綴表示法上

attribute::= [@attr-idattr-payload]
 
expr::= ...
 exprattribute
 
typexpr::= ...
 typexprattribute
 
pattern::= ...
 patternattribute
 
module-expr::= ...
 module-exprattribute
 
module-type::= ...
 module-typeattribute
 
class-expr::= ...
 class-exprattribute
 
class-type::= ...
 class-typeattribute
 

這種形式的屬性也可以插入在多態變體類型表達式(tag-spec-firsttag-spectag-spec-full)中的`tag-name之後,或在method-type中的method-name之後。

相同的語法形式也用於將屬性附加到類型宣告中的標籤和建構子

field-decl::=[mutable] field-name:poly-typexpr { attribute }
 
constr-decl::=(constr-name ∣ ()) [ ofconstr-args ] { attribute }
 

注意:當標籤宣告後面跟著分號時,屬性也可以放在分號之後(在這種情況下,它們會與之前指定的屬性合併)。

第二種形式的屬性附加到「區塊」,例如類型宣告、類別欄位等

item-attribute::= [@@attr-idattr-payload]
 
typedef::= ...
 typedefitem-attribute
 
exception-definition::= exceptionconstr-decl
 exceptionconstr-name=constr
 
module-items::=[;;] ( definition ∣ expr { item-attribute } ) { [;;] definition ∣ ;;expr { item-attribute } } [;;]
 
class-binding::= ...
 class-bindingitem-attribute
 
class-spec::= ...
 class-specitem-attribute
 
classtype-def::= ...
 classtype-defitem-attribute
 
definition::= let [rec] let-binding { andlet-binding }
 externalvalue-name:typexpr=external-declaration { item-attribute }
 type-definition
 exception-definition { item-attribute }
 class-definition
 classtype-definition
 modulemodule-name { (module-name:module-type) } [ :module-type ]  =module-expr { item-attribute }
 moduletypemodtype-name=module-type { item-attribute }
 openmodule-path { item-attribute }
 includemodule-expr { item-attribute }
 modulerecmodule-name:module-type=module-expr { item-attribute }  { andmodule-name:module-type=module-expr  { item-attribute } }
 
specification::= valvalue-name:typexpr { item-attribute }
 externalvalue-name:typexpr=external-declaration { item-attribute }
 type-definition
 exceptionconstr-decl { item-attribute }
 class-specification
 classtype-definition
 modulemodule-name:module-type { item-attribute }
 modulemodule-name { (module-name:module-type) } :module-type { item-attribute }
 moduletypemodtype-name { item-attribute }
 moduletypemodtype-name=module-type { item-attribute }
 openmodule-path { item-attribute }
 includemodule-type { item-attribute }
 
class-field-spec::= ...
 class-field-specitem-attribute
 
class-field::= ...
 class-fielditem-attribute
 

第三種形式的屬性以獨立結構或簽名項目的形式出現在模組或類別子語言中。它們沒有附加到語法樹中的任何特定節點

floating-attribute::= [@@@attr-idattr-payload]
 
definition::= ...
 floating-attribute
 
specification::= ...
 floating-attribute
 
class-field-spec::= ...
 floating-attribute
 
class-field::= ...
 floating-attribute
 

(注意:與上面文法描述的相反,item-attributes 不能附加到 class-field-specclass-field 中的這些浮動屬性。)

也可以使用中綴語法來指定屬性。例如

let[@foo] x = 2 in x + 1          === (let x = 2 [@@foo] in x + 1)
begin[@foo][@bar x] ... end       === (begin ... end)[@foo][@bar x]
module[@foo] M = ...              === module M = ... [@@foo]
type[@foo] t = T                  === type t = T [@@foo]
method[@foo] m = ...              === method m = ... [@@foo]

對於 let,屬性會應用於每個綁定

let[@foo] x = 2 and y = 3 in x + y === (let x = 2 [@@foo] and y = 3 in x + y)
let[@foo] x = 2
and[@bar] y = 3 in x + y           === (let x = 2 [@@foo] and y = 3 [@@bar] in x + y)

12.1 內建屬性

有些屬性可以被類型檢查器理解。

module X = struct [@@@warning "+9"] (* 在此結構中本地啟用警告 9 *)end [@@deprecated "請改用模組 'Y'。"] let x = begin[@warning "+9"] […] end type t = A | B [@@deprecated "請改用類型 's'。"]
let fires_warning_22 x = assert (x >= 0) [@ppwarning "TODO:稍後移除此項目"]
Warning 22 [預處理器]:TODO:稍後移除此項目
let rec is_a_tail_call = function | [] -> () | _ :: q -> (is_a_tail_call[@tailcall]) q let rec not_a_tail_call = function | [] -> [] | x :: q -> x :: (not_a_tail_call[@tailcall]) q
Warning 51 [錯誤的尾呼叫預期]:預期尾呼叫
let f x = x [@@inline] let () = (f[@inlined]) ()
type fragile = | Int of int [@warn_on_literal_pattern] | String of string [@warn_on_literal_pattern]
let fragile_match_1 = function | Int 0 -> () | _ -> ()
Warning 52 [脆弱的常值模式]:程式碼不應依賴此建構子參數的實際值。它們僅供參考,並且可能會在未來的版本中變更。(請參閱手冊第 13.5.3 節)val fragile_match_1 : fragile -> unit = <fun>
let fragile_match_2 = function | String "constant" -> () | _ -> ()
Warning 52 [脆弱的常值模式]:程式碼不應依賴此建構子參數的實際值。它們僅供參考,並且可能會在未來的版本中變更。(請參閱手冊第 13.5.3 節)val fragile_match_2 : fragile -> unit = <fun>
module Immediate: sig type t [@@immediate] val x: t ref end = struct type t = A | B let x = ref A end
module Int_or_int64 : sig type t [@@immediate64] val zero : t val one : t val add : t -> t -> t end = struct include Sys.Immediate64.Make(Int)(Int64) module type S = sig val zero : t val one : t val add : t -> t -> t end let impl : (module S) = match repr with | Immediate -> (module Int : S) | Non_immediate -> (module Int64 : S) include (val impl : S) end