The core principles of functional programming are immutability and separation of code and data.
The most common and idiomatic way to apply this in rescript is with the following module architecture: a main type t
that ‘tracks’ the state and that can be abstract in its interface file and functions to interact with this type that return a new state instead of mutating their input:
module Terminal: {
type t
type direction = Up | Down | Reset
let make: (~height: int=?) => t
let clear: t => t
let echo: t => t
let move: (t, ~direction: direction) => t
let updateCurrentCommand: (t, string) => t
let getCurrentCommand: t => string
let getDisplayedLines: t => array<string>
} = {
type t = {
content: array<string>,
currentCommand: string,
position?: int,
height: int,
}
type direction = Up | Down | Reset
let make = (~height=10) => {
content: [],
currentCommand: "",
height,
}
let clear = t => {...t, content: [], position: ?None}
let echo = t => {
...t,
content: [...t.content, t.currentCommand],
currentCommand: "",
position: ?None,
}
let move = (t, ~direction) => {
...t,
position: ?{
let length = Array.length(t.content)
let position = t.position->Option.getOr(length)
switch direction {
| Up => Int.clamp(~min=t.height, position - 1)->Some
| Down =>
let position = position + 1
position > length ? None : Some(position)
| Reset => None
}
},
}
let updateCurrentCommand = (t, currentCommand) => {...t, currentCommand}
let getDisplayedLines = ({content, height, ?position}) => {
let length = Array.length(content)
let position = position->Option.getOr(length)
content->Array.slice(
~start=Int.clamp(~min=0, position - height),
~end=Int.clamp(~min=position, height),
)
}
let getCurrentCommand = ({currentCommand}) => currentCommand
}
Playground link (do not forget to enable Auto-run to try it live)
There should be more posts and books around how to architect your code idiomatically in rescript, meanwhile you can read books that focus on functional programming in general and especially the ones that use “pragmatic” functional programming languages like OCaml/F#.