Quantcast
Channel: ReScript Forum - Latest posts
Viewing all articles
Browse latest Browse all 2592

Module functors vs. records-of-functions for interface/implementation separation

$
0
0

At least somewhat related, but you can also use ReScript objects if you want to leverage full inference for DI. Here’s an example that uses %typeof, which does not exist yet (but there’s a PoC of):

// The installed NodeJs bindings
module Node = {
  module Fs = {
    @module("node:fs")
    external readFileSync: (string, string) => string = "readFileSync"
  }
}

// This is our fn that uses DI via the `ctx` arg
let processFile = (filename, ~ctx) => {
  let readfile: %typeof(Node.Fs.readFileSync) = ctx["readfile"]
  let content = readfile(filename, "utf8")
  content->String.split("\n")->Array.map(line => line->String.trim)
}

// Inject the real thing in prod
let inProd = () => {
  let processed = processFile("file.txt", ~ctx={"readfile": Node.Fs.readFileSync})

  processed
}

// Mock in test
let inTest = () => {
  let processed = processFile(
    "file.txt",
    ~ctx={
      "readfile": (_filename, _encoding) => "<mocked>",
    },
  )

  processed
}

You could use first class modules together with ReScript objects to get inferred DI as well:

module Fs = {
  external readFileSync: string => string = "readFileSync"
}

module type Fs = module type of Fs

module Other = {
  external log: string => unit = "console.log"
}

module type Other = module type of Other

let logContents = (contents, ~ctx) => {
  let log: string => unit = ctx["log"]
  log(contents)
}

let readAndReturnFile = (~ctx) => {
  let module(Fs: Fs) = ctx["fs"]
  let readFile: string => string = ctx["readFileSync"]
  switch readFile("test.txt") {
  | exception _ => Error(#ReadFileError)
  | fileContents => Ok(fileContents ++ " hello")
  }
}

let main = () => {
  let ctx = {
    "readFileSync": s => s,
    "log": Console.log,
    "fs": module(Other: Other),
  }

  switch readAndReturnFile(~ctx) {
  | Ok(contents) => contents->logContents(~ctx)
  | Error(#ReadFileError) => ()
  }
}

Viewing all articles
Browse latest Browse all 2592

Trending Articles