Conventions
t is the main type of a module
In Reason / OCaml it is a convention for the primary type of a module to be named t
.
This means that when you want to refer to a type without open
ing a module you don't end up repeating yourself:
let food: String.string = /* ... *//* compared to */let email: String.t = /* ... */
Since this is pervasive it also means your module can be used with Functors, as they almost always adhere to this convention.
f is for function
Functions which take a function as an argument will almost always be a labelled argument named f
.
Take Array.map
as an example:
let map: (array('a), ~f:('a => 'b)) => array('b);
This means that it's easy to use these functions by either applying all of the arguments:
Array.map([|1,2,3|], ~f=(number) => number * 3);
or by chaining functions together using |>
Array.filter([|1,2,3|], ~f=Int.isOdd)|> Array.map(~f=(number) => number * 3);
exn is for exception
The type for exceptions in OCaml is actually called exn
.
You can read more about exceptions in Real World OCaml or in the OCaml manual.
sep is for separator
Array.intersperse
, Array.join
and their List
counterparts all take an element that will be used
as a separator.
Since this is a bit of a mouthful for a pretty commonly used function it gets shortened to sep
.
Function suffixes
Some functions come in multiple flavors.
Some of these flavors are so common they are distinguished by a really short suffix.
___2 is an alternative behaviour
When a function could behave in slightly different ways, but we want to provide the functionality of both, one of the implementations gets a two stuck on the end.
The best example of this is Float.atan2
___I is for "with index"
Array.map
and Array.mapI
, are almost
the same, except mapI
, which in addition to being called with each element,
also gets called with the elements index.
___Unsafe means "could raise an exception"
Some functions have 'unsafe' versions which instead of returning an Option
or a Result
could raise an exception.
Sometimes this can be for performance, and sometimes you just need an escape hatch.
See Option.get
and Option.getUnsafe
Modules
S is for signature, T is for module type
Functions which accept first class modules or functors need a way to label their arguments, and to avoid this being too long they are usually named S
for the signature a functor returns and T
for the input type.
In a similar way to modules primary type being named t
Data comes first
In almost all of the functions that Standard
provides, the data structure the
function is operating on will be the first positional argument.
This is the opposite the way standard libraries for related languages like Elm or Haskell tend to do things, but for some good reasons:
Better error messages
Compare the error message for data last
let words = ["hi"]let res = List.map(n => n + 1, words)// ^^^^^// This expression has type string list// but an expression was expected of type int list// Type string is not compatible with type int
With the one returned for data first
open Standard;let words = ["hi"];let res = List.map(words, ~f:n => n + 1 );// ^// This expression has type string but an expression// was expected of type int
Better type inference
Say we have a module Book
module Book = {type t = {isbn: string,title: string,};let classics = [{ isbn: "9788460767923", title: "Moby Dick or The Whale" }];}
With a data-last approach we end up needing to provide additional annotations when we use List.map
let isbns = List.map(book => book.isbn, Book.classics);/*The record field isbn can't be found.If it's defined in another module or file, bring it into scope by:- Annotating it with said module name:- Or specifying its type:*/
But with data-first
open Standard;let isbns = List.map(Book.classics, ~f=book => book.isbn);/* 👍 */
More intuitive, consistent APIs
Consider appending one array to another.
With data last
let append = (arrayToAppend, data) => /* ... */;append([|1, 2, 3|], [|4, 5, 6|]) = [|4, 5, 6, 1, 2, 3|]/* The standard library diverges from its usual data-lastconvention and implements this function data-first */
With data first
open StandardArray.append([|1, 2, 3|], [|4, 5, 6|]) = [|1, 2, 3, 4, 5, 6|]
This section was heavily inspired by Javier Chavarri's excellent blog post and the discussions on the Bucklescript and Reason GitHub issue trackers.
Check out the API
Now is a great time to jump straight into the API.
If you want to find out more about why Standard exists and how you can help, read on.