Labelled arguments without a mandatory call-site constraint
0 reputation · 14 Apr 2024, 13:21 UTC
0 reputation · 14 Apr 2024, 13:21 UTC
Gleam's labelled function arguments let library authors present more descriptive names at the call site than the underlying parameter names. The intended benefit is clearer, more self-documenting client code, particularly for functions with several parameters or boolean flags. However, the compiler currently accepts both labelled and positional forms at the call site without emitting a warning, and there is no documented syntax, compiler flag, or configuration setting to mark labels as mandatory.
This leaves an unresolved boundary for API design: a library author can express preferred call-site conventions but cannot enforce them at compile time. Because labels do not affect function identity, currying, or higher-order function passing, the omission of a label is indistinguishable from a labelled call in every other respect. The behavior is consistent across Erlang and JavaScript targets, though future language versions could introduce stricter rules.
Assuming current stable Gleam behavior, is there any existing mechanism—documented or experimental—to require callers to use labels? If not, what is the recommended pattern for signalling that positional calls are discouraged without relying on external linting or documentation? Could a future compiler version make previously valid positional calls brittle?
32275 reputation · 14 Apr 2024, 22:21 UTC
Short answer: In the current stable Gleam compiler there is no documented or experimental flag that forces callers to use labelled arguments. The language treats a labelled call and a positional call as identical at the type level, so the compiler will accept either form without warning.
Labels in Gleam are syntactic sugar. They only affect the source‑code text; the generated function signature, type, and runtime representation remain unchanged. Consequently:
add(a: Int, b: Int) and add(Int, Int) as the same function.State the preferred style explicitly in the public documentation. Example:
/// Adds two numbers. Prefer labelled arguments for clarity.
/// ```gleam
/// add(a: 5, b: 3)
/// ```
pub fn add(a: Int, b: Int) -> Int { a + b }
Introduce a simple lint rule that flags positional calls to add and any other public function that should be called with labels. The rule can be run as part of your CI pipeline or in the editor via the Gleam extension.
Replace the function signature with a single record argument:
pub fn add(args: { a: Int, b: Int }) -> Int { args.a + args.b }
Now callers must write:
add({ a: 5, b: 3 })
Positional calls are no longer possible, but the API surface changes and may break existing consumers.
There is currently no plan in the issue tracker to deprecate positional calls or introduce a --require-labels flag. However, language evolution could add stricter rules or a dedicated option in a future release. If such a feature appears, existing positional calls compiled with older versions would still work, but new code would need to adapt.
pub fn add(a: Int, b: Int) -> Int { a + b }
add(1, 2)
add(a: 1, b: 2)
gleam build – no warnings or errors appear for either call.
These steps confirm the current compiler behavior and illustrate the impact of the record‑wrapper approach.
Until the compiler itself provides a mandatory‑label feature, library authors should rely on clear documentation, linting, or a record‑wrapper pattern to guide callers toward the desired call‑site style. Keep an eye on the Gleam issue tracker for any future changes that might alter this landscape.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.