package tablecloth-base

  1. Overview
  2. Docs

Module Tablecloth.FunSource

Functions for working with functions.

Functions for working with functions.

While the functions in this module can often make code more concise, this often imposes a readability burden on future readers.

Sourceval identity : 'a -> 'a

Given a value, returns exactly the same value. This may seem pointless at first glance but it can often be useful when an api offers you more control than you actually need.

Perhaps you want to create an array of integers

Array.initialize 6 ~f:Fun.identity = [|0; 1; 2; 3; 4; 5|]

(In this particular case you probably want to use Array.range.)

Or maybe you need to register a callback, but dont want to do anything:

  let http_middleware =
    HttpLibrary.create_middleware
      ~on_event_you_do_care_about:transform_and_return
      ~on_event_you_dont_care_about:Fun.identity
Sourceval ignore : _ -> unit

Discards the value it is given and returns ()

This is primarily useful when working with imperative side-effecting code or to avoid unused value compiler warnings when you really meant it, and haven't just made a mistake.

Examples

  (* Pretend we have a module with the following signature:
      module PretendMutableQueue : sig
        type 'a t

        (** Adds an element to the queue, returning the new length of the queue *)
        val push_returning_length : 'a t -> 'a -> int
      end
  *)

  let add_list_to_queue queue list =
    List.for_each list ~f:(fun element ->
      Fun.ignore (PretendMutableQueue.push_returning_length queue element)
    )
  in ()
Sourceval constant : 'a -> 'b -> 'a

Create a function that always returns the same value.

Useful with functions like List.map or Array.initialize.

Examples

List.map ~f:(Fun.constant 0) [1;2;3;4;5] = [0;0;0;0;0]
Array.initialize 6 ~f:(Fun.constant 0) = [|0;0;0;0;0;0|]
Sourceval sequence : 'a -> 'b -> 'b

A function which always returns its second argument.

Sourceval flip : ('a -> 'b -> 'c) -> 'b -> 'a -> 'c

Reverses the argument order of a function.

For any arguments x and y, (flip f) x y is the same as f y x.

Perhaps you want to fold something, but the arguments of a function you already have access to are in the wrong order.

Sourceval negate : ('a -> bool) -> 'a -> bool

Negate a function.

This can be useful in combination with List.filter / Array.filter or List.find / Array.find.

Examples

  let is_less_than_twelve = Fun.negate (fun n -> n >= 12) in
  is_less_than_twelve 12 = false
Sourceval apply : ('a -> 'b) -> 'a -> 'b
Sourceval (<|) : ('a -> 'b) -> 'a -> 'b

Like (|>) but in the opposite direction.

f <| x is exactly the same as f x.

Maybe you want to apply a function to a match expression? That sort of thing.

Sourceval pipe : 'a -> ('a -> 'b) -> 'b
Sourceval (|>) : 'a -> ('a -> 'b) -> 'b

Saying x |> f is exactly the same as f x, just a bit longer.

It is called the "pipe" operator because it lets you write "pipelined" code.

It can make nested function calls more readable.

For example, say we have a sanitize function for turning user input into integers:

  (* Before *)
  let sanitize (input: string) : int option =
    Int.from_string (String.trim input)

We can rewrite it like this:

  (* After *)
  let sanitize (input: string) : int option =
    input
    |> String.trim
    |> Int.from_string

This can be overused! When you have three or four steps, the code often gets clearer if you break things out into some smaller piplines assigned to variables. Now the transformation has a name, maybe it could have a type annotation.

It can often be more self-documenting that way!

Sourceval compose : ('b -> 'c) -> ('a -> 'b) -> 'a -> 'c

Function composition, passing results along in the suggested direction.

For example, the following code (in a very roundabout way) checks if a number divided by two is odd:

let is_half_odd = Fun.(not << Int.is_even << Int.divide ~by:2)

You can think of this operator as equivalent to the following:

(g << f) = (fun x -> g (f x))

So our example expands out to something like this:

let is_half_odd = fun n -> not (Int.is_even (Int.divide ~by:2 n))
Sourceval (<<) : ('b -> 'c) -> ('a -> 'b) -> 'a -> 'c
Sourceval compose_right : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c

Function composition, passing results along in the suggested direction.

For example, the following code checks if the square root of a number is odd:

Int.square_root >> Int.is_even >> not
Sourceval (>>) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c
Sourceval tap : 'a -> f:('a -> unit) -> 'a

Useful for performing some side affect in Fun.pipe-lined code.

Most commonly used to log a value in the middle of a pipeline of function calls.

Examples

  let sanitize (input: string) : int option =
    input
    |> String.trim
    |> Fun.tap ~f:(fun trimmed_string -> print_endline trimmed_string)
    |> Int.from_string
  Array.filter [|1;3;2;5;4;|] ~f:Int.is_even
  |> Fun.tap ~f:(fun numbers -> numbers.(0) <- 0)
  |> Fun.tap ~f:Array.reverse_in_ilace
  = [|4;0|]
Sourceval forever : (unit -> unit) -> exn

Runs the provided function, forever.

If an exception is thrown, returns the exception.

Sourceval times : int -> f:(unit -> unit) -> unit

Runs a function repeatedly.

Examples

  let count = ref 0 in
  times 10 (fun () -> count <- !count + 1);
  !count = 10
Sourceval curry : (('a * 'b) -> 'c) -> 'a -> 'b -> 'c

Takes a function f which takes a single argument of a tuple 'a * 'b and returns a function which takes two arguments that can be partially applied.

Examples

  let square_area (width, height) = width * height in
  let curried_area : int -> int -> int = Fun.curry square_area in
  let sizes = [3; 4; 5] in
  List.map sizes ~f:(curried_area 4) = [12; 16; 20]
Sourceval uncurry : ('a -> 'b -> 'c) -> ('a * 'b) -> 'c

Takes a function which takes two arguments and returns a function which takes a single argument of a tuple.

Examples

  let sum (a : int) (b: int) : int = a + b in
  let uncurried_sum : (int * int) -> int = Fun.uncurry sum in
  uncurried_sum (3, 4) = 7
Sourceval curry3 : (('a * 'b * 'c) -> 'd) -> 'a -> 'b -> 'c -> 'd

Like curry but for a Tuple3.

Sourceval uncurry3 : ('a -> 'b -> 'c -> 'd) -> ('a * 'b * 'c) -> 'd

Like uncurry but for a Tuple3.

OCaml

Innovation. Community. Security.