Named and Optional Arguments are Awesome

54 points by jado


giacomo_cavalieri

it makes parameter names part of the public API of the function,

I really like the way gleam (and swift too I believe) goes about this. The public parameter name has to be picked explicitly rather than all arguments being named automatically.

pub fn replace(
  in string: String,
  each value: String,
  with replacement: String,
) -> String {
  // do something with “string”,
  // “value” and “replacement”
}

pub fn main() {
  replace(“Wibble”, each: “i”, with: “o”)
}

I think the best APIs are well thought out rather than happening by accident so using named arguments should be an intentional choice

toastal

OCaml’s labeled & optional arguments using ~ + ? sigils is pretty novel in the functional space. I ended up liking it quite a lot ergonomically since a) you can easily forward along arguments, but also the labels can be alias for the scope meaning you don’t need to come up with argument names! A trivial example:

let add ~x ?(y = 0) () =
	x + y

let print_sum ~x ?y () =
	print_string "Sum: ";
	let sum = add ~x ?y () in
	print_endline (string_of_int sum)

let () =
	let x = 1
	and y = Some 2
	in
	(* using labels from scope *)
	print_sum ~x ?y (); (* Sum: 3 *)
	(* manual + omitted y *)
	print_sum ~x: 4 () (* Sum: 4 *)
pyj

it makes parameter names part of the public API of the function,

After using Python's equivalent (keyword arguments) and Ada's equivalent (named parameter associations) quite a bit, I went from "parameter names being part of the API is bad" to "perhaps this isn't a bad idea." You're forced to think more about clear parameter names, which improves reading intent from the function signature.

It does make library API changes a bit more fragile. Changing parameter names becomes a breakage, since call with named arguments will no longer compile. However, it can detect semantic changes to arguments where the type remains the same.