Best way to pass options to functions


#1

Is there a best practice for how to pass options to functions that take multiple options in ReasonML?

Two approaches:

  • bs-clean-deep, takes all options as optional arguments and data in last:
    CleanDeep.cleanDeep(
      ~emptyStrings=false,
      ~emptyArrays=false,
      someJsObject
    )
    
  • bs-marky-markdown, takes a record with options:
    MarkyMarkdown.marky(
      "# My Markdown String", 
      ~options=MarkyMarkdown.options(
          ~highlightSyntax=false, 
          ()
      ), 
      ()
    )
    

Is any of these preferred, does it depend, or is it other preferred ways of doing this in ReasonML?


#2

The first approach is preferred :slight_smile: in a function with optional parameters, the compiler needs a final, non-optional parameter to be able to decide when the function is syntactically ‘fully applied’. See https://reasonml.github.io/docs/en/function#optional-labeled-arguments for more details.


#3

So the first approach would be preferred even if MarkyMarkdown would have taken the option-record as the first argument (and data in last)? E.g.

MarkyMarkdown.marky(
  ~options=MarkyMarkdown.options(
      ~highlightSyntax=false, 
      ()
  ),
  "# My Markdown String"
)

As I understand, this pattern of creating an options-record is not the ReasonML way of doing optional arguments to functions.


#4

For MarkyMarkdown, the best approach would be:

MarkyMarkdown.marky(~highlightSyntax=false, "# My Markdown String")

To achieve that signature, we would want to wrap it similarly to what you did for bs-clean-deep.

Edit: JavaScripters often use options-object parameters as a way to simulate passing ‘named arguments’ to the function, e.g. marky("my string", {highlightSyntax: false}). In OCaml/Reason we want to convert from this JavaScript idiom into the OCaml idiom, which is optional labelled parameters as the first parameters of the function.