janestreet / ppx_accessor

[@@deriving] plugin to generate accessors for use with the Accessor libraries

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

This extension provides two features:

  • Generate Accessor isomorphisms, fields, variants, and optionals from types.
  • Eta expand Accessor-defining expressions to avoid the value restriction.

Syntax

Type definitions
[@@deriving accessors]
Expressions
[%accessor EXPR]

Usage

Polymorphizing accessors

Wrap an expression defining an accessor like this:

[%accessor Accessor.field ~get ~set]

This causes the expression to be as polymorphic as possible via eta expansion. The generated code in the above example would be something like this:

{ Accessor.f =
    (fun selector mapping ->
      (Accessor.field ~get ~set).f selector mapping)
}

Deriving accessors

Annotate a type definition like this:

type t =
  { foo : int
  ; bar : string
  }
[@@deriving accessors]

This generates different accessors depending on the type definition.

You can optionally specify to generate the accessors in a submodule, like this:

type t =
  { foo : int
  ; bar : string
  }
[@@deriving accessors ~submodule:My_submodule]

This can be useful to avoid name clashes with [@@deriving fields]. If you want to derive both accessors and fields, you have three options, but only two are useful:

Derive accessors before fields
[@@deriving accessors, fields] The getter functions generated by fields will shadow the accessors, so there is little point in this arrangement.
Derive fields before accessors
[@@deriving fields, accessors] The accessors will shadow the getter functions generated by fields, but you still get the Fields module.
Provide a submodule for accessors values
[@@deriving accessors ~submodule:Some_submodule, fields] Nothing will be shadowed, but the accessors will be stuffed into a submodule, which makes using them more verbose.

Records

ppx_accessor generates one accessor per record field.

Multiple fields

Records with multiple fields result in field accessors.

type t =
  { foo : int
  ; bar : string
  }
[@@deriving accessors]

For the above type, these accessors would be generated:

let foo =
  [%accessor Accessor.field ~get:(fun t -> t.foo) ~set:(fun t foo -> { t with foo })

let bar =
  [%accessor Accessor.field ~get:(fun t -> t.bar) ~set:(fun t bar -> { t with bar })

One field

Records with one field result in an isomorphism accessor.

type t = { foo : int } [@@deriving accessors]

For the above type, this accessor would be generated:

let foo =
  [%accessor
      Accessor.isomorphism ~get:(fun t -> t.foo) ~construct:(fun foo -> { foo })

Variants

ppx_accessor generates one accessor per constructor that doesn’t use inline record syntax. Inline records result in a submodule named after the constructor which contains one accessor per field of the inline record.

Multiple constructors

Variants with multiple constructors result in variant and optional accessors.

type t =
  | Foo
  | Bar of int * string
  | Baz of { a : float }
  | Quux of { a : int; b : string }
[@@deriving accessors]

For the above type, these accessors would be generated:

let foo =
  [%accessor
    Accessor.variant
      ~match_:(function
        | Foo -> First ()
        | (Bar _ | Baz _ | Quux _) as r -> Second r)
      ~construct:(fun () -> Foo)]

let bar =
  [%accessor
    Accessor.variant
      ~match_:(function
        | Bar (x, y) -> First (x, y)
        | (Foo | Baz _ | Quux _) as r -> Second r)
      ~construct:(fun (x, y) -> Bar (x, y)]

module Baz = struct
  let a =
    [%accessor
      Accessor.variant
        ~match_:(function
          | Baz t -> First t.a
          | (Foo | Bar _ | Quux _) as r -> Second r)
        ~construct:(fun a -> Baz { a })]
end

module Quux = struct
  let a =
    [%accessor
      Accessor.optional
        ~match_:(function
          | Quux t -> First t.a
          | (Foo | Bar _ | Baz _) as r -> Second r)
        ~set:(fun t a ->
          match t with
          | Quux t -> Quux { t with a }
          | (Foo | Bar _ | Baz _) as r -> r)]

  let b =
    [%accessor
      Accessor.optional
        ~match_:(function
          | Quux t -> First t.b
          | (Foo | Bar _ | Baz _) as r -> Second r)
        ~set:(fun t b ->
          match t with
          | Quux t -> Quux { t with b }
          | (Foo | Bar _ | Baz _) as r -> r)]
end

Single constructors

Variants with one constructor result in either an isomorphism or field accessor.

Constructors without inline record syntax

A singleton variant that does not use inline record syntax results in an isomorphism.

type t = Foo of int [@@deriving accessors]

For the above type, this accessor would be generated:

let foo =
  [%accessor Accessor.isomorphism ~get:(fun (Foo n) -> n) ~construct:(fun n -> Foo n)]
Constructors with inline record syntax

A singleton variant using inline record syntax is treated like a normal record, but the accessors live in a submodule named after the constructor.

Multiple fields

Records with multiple fields result in field accessors.

type t =
  Foo of
    { foo : int
    ; bar : string
    }
[@@deriving accessors]

For the above type, these accessors would be generated:

module Foo = struct
  let foo =
    [%accessor
      Accessor.field
        ~get:(fun (Foo t) -> t.foo)
        ~set:(fun (Foo t) foo -> Foo { t with foo })

  let bar =
    [%accessor
      Accessor.field
        ~get:(fun (Foo t) -> t.bar)
        ~set:(fun (Foo t) bar -> Foo { t with bar })
end
One field

Records with one field result in an isomorphism accessor.

type t = A of { foo : int } [@@deriving accessors]

For the above type, this accessor would be generated:

module A = struct
  let foo =
    [%accessor
        Accessor.isomorphism
          ~get:(fun (A t) -> t.foo)
          ~construct:(fun foo -> A { foo })
end

Polymorphic variants

ppx_accessor generates one variant accessor per constructor in a polymorphic variant. If there is only one constructor, it generates an isomorphism instead. If the type definition inherits from another polymorphic variant, it generates a variant accessor for converting to and from the inherited type.

About

[@@deriving] plugin to generate accessors for use with the Accessor libraries

License:MIT License


Languages

Language:OCaml 99.0%Language:Makefile 1.0%