Nevertheless, tuples are a lighter-weight data structure than records, and lighter-weight solutions are easier to write and often easier to read. Positional function arguments are here to stay.
Because the order of arguments isn't always particularly relevant, the order can seem arbitrary. As the designer of a procedure, it's sometimes hard to know what order to choose. Here's one criterion: think about currying. It can be useful to put the arguments expected to be known earlier before the arguments expected to be known later.
For example, in Syntactic Abstraction in Scheme, the heart of the definition of the macro expansion algorithm is the rule for macro applications:
expand(e, r) =This is pretty hard to read. Without getting too much into the specific details of the algorithm, the idea of this rule is that to expand a macro application, you mark the expression with a fresh mark, apply the macro transformer t to the marked expression, then mark the output of that transformer again with the same mark, and finally expand the result.
case parse(e, r) of
macro-application(i, e) → expand(mark(t(mark(e, m)), m), r)
where t = r(resolve(i)) and m is fresh
There's a functional pipeline buried in that rule, but it's obscured by the order of arguments. This is actually a good candidate for point-free style. Since we expect the environment argument r for expand to be known before the expression, and the mark argument m for mark to be known before the expression argument, let's swap the order of arguments to both those functions. Now we get the new rule
macro-application(i, e) → ((expand r) ⋅ (mark m) ⋅ t ⋅ (mark m)) e