If you practice typeful programming, which is the idea that a lot of the semantic content of programs can be reflected statically in the type system, you will find out that in many (but not all) cases, named arguments are not necessary for readability.
Consider the following examples in the List
standard library of OCaml. By knowing that they operate on lists, and with the (hopefully clear: we're all for good name choices) name of the function, you will find that you don't need explanations for what the arguments do.
val append : α list -> α list
val flatten : α list list -> α list
val exists: (α -> α bool) -> α list -> bool
val map: (α -> β) -> α list -> β list
val combine : α list -> β list -> (α * β) list
Note that the last example is interesting because it is not exactly clear what the code will do. There would in fact be several interpretations. combine [1;2] [3;4]
returns [(1,3); (2,4)]
and not, for example, [(1,3); (1,4); (2,3); (2,4)]
. It is also not clear what happens when the two lists are not of the same length (the failure mode is unclear).
Functions that are not total, that may raise an exception or not terminate, usually need more documentation about what the failure cases are and how they will behave. This is one strong argument in favor of what we call pure programming, where all the behavior of a function is expressed in terms of returning a value (no exceptions, observable state mutation, or non-termination), and can therefore be statically captured by the type system.
Of course this only works really well for functions that are parametric enough; they have a type that make it very clear what they do. This is not the case of all functions, consider for example the blit
function of the String
module (I'm sure your favorite language has such examples as well):
val blit : string -> int -> string -> int -> int -> unit
huh?
Programming languages add support named parameters for this reason. In OCaml for example we have "labels" that allow to name parameters. The same function is exported in the StringLabels
module as:
val blit : src:string -> src_pos:int -> dst:string -> dst_pos:int -> len:int -> unit
That's better. Yes, named parameters are useful in some cases.
Note however that named arguments can be used to hide bad API design (maybe the example above is targe to this criticism as well). Consider:
val add : float -> float -> float -> float -> float -> float -> float * float * float
obscure, huh? But then:
type coord = {x:float; y:float; z:float}
val add : coord -> coord -> coord
That's much better, and I didn't need any parameter labeling (arguably record labels provide naming, but in fact I could equally use float * float * float
here; the fact that value records may subsume named (and optionals?) parameters is also an interesting remark).
David M. Barbour develops the argument that named parameters are a "crutch" of language design, that is used to tamper over the lazyness of API designers, and that not having them encourages better design. I am not sure I agree that named parameters can be profitably avoided in all situations, but he certainly has a point that agrees with the typeful propaganda at the beginning of my post. By raising the level of abstraction (through more polymorphic/parametric types or better problem domain abstractions), you'll find you decrease the need for parameter naming.
let f x y = x + y + 1
into F# interactive gives me:val f : x:int -> y:int -> int
(and IntelliSense gives me the same thing in the editor). – kvbfoo Nothing = bar; foo (Just []) = baz; foo (Just (x:xs)) = quux
. What should the IDE make of that? Also,foldl' :: (a -> b -> a) -> a -> [b] -> a; foldl' f z = go z where go ...
, only some arguments are explicitly provided in the definition. – Daniel FischeraddThree :: Int -> Int -> Int -> Int
is a function taking anInt
and returning (a function taking anInt
and returning (a function taking anInt
and returning anInt
)). [Of course that's cumbersome, so one normally speaks of a function taking three arguments, but occasionally, the difference is important.] – Daniel Fischer