@munroec One way to understand that Alan Perlis quote ("If you have a procedure with ten parameters, you probably forgot some"): Functions should take fewer parameters, and you should compose them.
He has another quote ~= "100 functions on 1 data structure are better than 20 on 20".
Seems he's a fan defining many, more-specific functions.
Which is good advice. But sometimes it's hard to avoid a function or data structure taking a big "duffel bag" of a dozen values.
[Maybe some real-world spec determines that, and you're modeling it. Or maybe you want to supply a convenience function for people who don't want to learn how to compose a bazillion functions exactly perfectly. Or maybe you want to de-duplicate code from various simple "flavor" functions into a core, private, helper function. Or some other scenario.]
Then you have the classic choice of "by position" or "by name". Do you call the function (or init the data structure) by position: (foo 0 1 2)
? With three values, it's not too bad, but if you have a dozen, you're likely make a mistake. So by name is "safer": (foo #:a 0 #:b 1 #:c 2)
is clear; (foo #:c 2 #:b 1 #:a 0)
is identical (order doesn't matter).
There's also the choice of default values. Often, if you have a dozen parameters, some will have reasonable defaults most of the time (like 0
or #false
or whatever). So it can be nice for functions to have optional parameters -- if you don't supply a value, a default value will be used. But these much "safer" as named, keyword arguments.
Finally, it might be OK or preferable for a function to take one or two "obvious" required parameters by-position, and the rest are named and/or optional.
TL;DR: In Racket you can say (define (foo a #:b b #:c [c 42]) ___)
to define a function foo
that takes
- a required by-position argument bound to
a
inside the function
- a required keyword argument
#:b
(value bound to b
inside the function)
- an optional keyword argument
#:c
(c
defaulting to 42
if not supplied)
This can be called as (foo "hello")
, (foo "hello" #:b "world")
, or (foo "hello" #:b "world" #:c 999)
.
plot
is an example of using this technique.