A case against currying
Distinctions: Currying vs Tuples vs Parameter Lists
- Several commenters argue all three are isomorphic in theory, but many languages treat parameter lists and tuples as distinct constructs (you can’t just pass a tuple where a parameter list is expected).
- Some see value in treating all functions as single-argument over tuples (cleaner theory, simpler interpreters). Others prefer explicit multi-arg parameter lists for ergonomics and features like named arguments and defaults.
- There’s debate over whether this third distinction (tuples vs parameter lists) is meaningful or mostly syntactic/ergonomic.
Ergonomics, Readability, and Errors
- Critics of currying emphasize:
- Ambiguity at call sites:
f a bmight be a value or a partially-applied function; you must know the arity from the type. - Missing-argument bugs:
(f 1 2)instead of(f 1 2 3)silently yields a function; errors surface later and far away. - Harder-to-read code in large codebases, especially for newcomers.
- Ambiguity at call sites:
- Supporters value:
- Concise pipelines and composition without lambdas (e.g.,
x |> f a b |> g c d). - Pointfree style and smoother equational reasoning.
- Concise pipelines and composition without lambdas (e.g.,
- Several people favor explicit partial-application syntax (placeholder “holes” like
_,$,%, orit) as clearer than implicit currying, while still ergonomic.
Named Arguments and Business Code
- Some argue named parameters are generally better in “business” code, reducing positional mistakes.
- Counterpoints: redundancy when variable names already match parameter names, and friction when domain-specific names differ; features like name elision and “field punning” help but don’t fully resolve the tension.
Performance and Implementation
- Concerns: extra allocations for tuple-passing, and overhead of currying for every call.
- Others respond that compilers can and do optimize these patterns heavily; performance downsides are often overstated.
Language Design Experiences
- Coalton recently removed currying in favor of fixed-arity functions, citing clearer type errors and simplicity.
- Roc and some others reach similar conclusions: make currying/partial application explicit, not the default.
- Standard ML and some Scheme/Lisp dialects are cited as examples of tuple-based or explicit-partial-application approaches.
- Haskell/OCaml users report both powerful abstractions from currying and real-world pain from confusing types and error messages.