Skip to content

Commit

Permalink
Merge pull request #4 from cryptosense/change_default_representation
Browse files Browse the repository at this point in the history
Prepare for initial release
  • Loading branch information
bbc2 authored Mar 22, 2019
2 parents 5b94a71 + 47106cd commit db42bc1
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 11 deletions.
89 changes: 89 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,92 @@
# ppx_enum

`ppx_enum` is an OCaml preprocessor to derive enum-like modules from variant definitions.

## Overview

Enums are bare variants that are intended to represent a flag that can have more values than just true and false.

`ppx_enum` makes it easier to work with enums, in particular handling the conversion to and from strings. This is useful when (de)serializing values (for example, when serializing to store in a database), and cuts down on repetitive boilerplate code.

Consider the following simple example:

```ocaml
type my_enum =
| Foo
| Bar
| Baz
[@@deriving enum]
```

The use of `[@@deriving enum]` will generate the following functions:

```ocaml
let my_enum_to_string = function
| Foo -> "Foo"
| Bar -> "Bar"
| Baz -> "Baz"
let my_enum_from_string = function
| "Foo" -> Ok Foo
| "Bar" -> Ok Bar
| "Foo" -> Ok Foo
| _ -> Error ...
let my_enum_from_string_exn = function
| "Foo" -> Foo
| "Bar" -> Bar
| "Foo" -> Foo
| _ -> invalid_arg ...
```

### Naming of Generated Functions

Generally, the generated functions for type `mytype` will be `mytype_to_string`, `mytype_from_string` and `mytype_from_string_exn`.

The only exception is when using `type t = ...`, in which case `to_string`, `from_string` and `from_string_exn` will be used.

## Installation and Usage

You can install `ppx_enum` using [opam](https://opam.ocaml.org):
```
$ opam install ppx_enum
```

If you're building your library or app with dune, add the following field to your `library`,
`executable` or `test` stanza:
```
(preprocess (pps ppx_enum))
```
or simply add `ppx_enum` to your `preprocess` field if it's already there.

You can now add the `enum` plugin to `[@@deriving ...]` attributes on variant type definitions.

## Customizing the Generated Functions

### Custom Values for Specific Variants

It is possible to customize the string value that will be used to represent a specific variant by using an `[@value]` attribute. An example is worth 1000 words here:

```ocaml
type myenum =
| Foo [@value "baz"]
| Bar
[@deriving enum]
my_enum_to_string Foo (* "baz" *)
my_enum_to_string Bar (* "bar" *)
my_enum_from_string "foo" (* Error ... *)
my_enum_from_string "bar" (* Ok Bar *)
my_enum_from_string "baz" (* Ok Foo *)
```

The attributes will accept any valid suffix of `ppx_enum.enum.value`, so the following will work:

```ocaml
type myenum =
| Foo [@value "foo-1"]
| Bar [@enum.value "bar-1"]
| Baz [@ppx_enum.enum.value "baz-1"]
[@deriving enum]
```
2 changes: 1 addition & 1 deletion lib/enum.ml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ module Str = struct
let value =
match attribute_value with
| Some value -> value
| None -> String.lowercase_ascii name
| None -> name
in
(name, value)

Expand Down
20 changes: 10 additions & 10 deletions test/deriver/test_enum.expected.ml
Original file line number Diff line number Diff line change
Expand Up @@ -26,39 +26,39 @@ module S :
type t =
| Foo
| Bar [@@deriving enum]
let to_string = function | Foo -> "foo" | Bar -> "bar"
let to_string = function | Foo -> "Foo" | Bar -> "Bar"
let from_string =
function
| "foo" -> Ok Foo
| "bar" -> Ok Bar
| "Foo" -> Ok Foo
| "Bar" -> Ok Bar
| s ->
Error
(Printf.sprintf "Unexpected value for %s.%s: %s" __MODULE__
"from_string" s)
let from_string_exn =
function
| "foo" -> Foo
| "bar" -> Bar
| "Foo" -> Foo
| "Bar" -> Bar
| s ->
invalid_arg
(Printf.sprintf "Unexpected value for %s.%s: %s" __MODULE__
"from_string_exn" s)
type simple_enum =
| Foo
| Bar [@@deriving enum]
let simple_enum_to_string = function | Foo -> "foo" | Bar -> "bar"
let simple_enum_to_string = function | Foo -> "Foo" | Bar -> "Bar"
let simple_enum_from_string =
function
| "foo" -> Ok Foo
| "bar" -> Ok Bar
| "Foo" -> Ok Foo
| "Bar" -> Ok Bar
| s ->
Error
(Printf.sprintf "Unexpected value for %s.%s: %s" __MODULE__
"simple_enum_from_string" s)
let simple_enum_from_string_exn =
function
| "foo" -> Foo
| "bar" -> Bar
| "Foo" -> Foo
| "Bar" -> Bar
| s ->
invalid_arg
(Printf.sprintf "Unexpected value for %s.%s: %s" __MODULE__
Expand Down

0 comments on commit db42bc1

Please sign in to comment.