Note that it is also called "named parameters" in some languages.
Some professors seem to agree that KeywordParameterPassing is ConsideredHarmful:
"A major tenet of software engineering is modularity and it is desirable to reduce the dependence of a module on other modules. By using keyword parameter passing between modules we are making the caller dependent on the formal parameter names used in the callee. If keyword parameter passing is not possible, then the names of formal parameter names are completely hidden and modularity is enhanced." '' -- CP2003 - Principles of Programming (http://www.cs.jcu.edu.au/ftp/web/teaching/Subjects/cp2003/current/)
On wiki however, experienced software engineers agree that it is not:
{Every interface requires either arbitrary names or numbers/positions. There is no escape. Whether it is a class name, function name, attribute name, parameter name, or parameter position, we have to name or number things in order to have interfaces.}
You'd rather have your calling code dependent on some arbitrary numeric order of argument numbers than names that are meaningful in natural language?!?
Let's look at a real world example. Here's Microsoft's InStrRev function, as documented in MSDN:
InStrRev(string1, string2[, start[, compare]])OK, let's consider...
'InStrRev(s1, s2, comparison => vbTextCompare )'It doesn't bother people that I hard-coded the function name into my calling code, why should formal parameter names be any different? In many modern IDEs, the system displays the formal parameter names to me, the developer, as I type the call.
Transact-SQL stored procedures (Sybase & SQL Server) support sequential and named parameter passing (and a mix, in any call). I've found KeywordParameterPassing to be a very good thing when many of the parameters are optional. -- JeffGrigg
I second this: Keyword parameters reduce the likelihood that changes to a module will require changes to modules that use it, not increase it. Although one should RefactorMercilessly either way, it's still good to reduce the amount of work needed when refactoring. Further, keywords seem likely to be easier to remember than parameter orderings, leading to faster coding; I know they help me in CommonLisp. -- DanielKnapp
I disagree that keywords are more likely to be remembered than parameter orderings. Remembering whether the InStrRev() function's first parameter's keyword is "inputString" or "stringToFind" or "string_to_find" or "string1" or whatever is just extra work. A modern IDE may help with this, but a modern IDE will also make it easy to handle positional parameters. KeywordParameterPassing may be valuable when there are lots of parameters and many are optional, but a function with lots of parameters with many optional is usually a CodeSmell (a good candidate for the IntroduceParameterObject or RefactorParametersToMemberVariables refactorings). If KPP is an optional feature of a language, then I have no problem with it, but using it for all function invocations adds a lot of verbosity/noise to code. -- KrisJohnson
Concur. Modern IDEs make this a moot point. I never have to remember parameter order because every IDE I use shows me the type and name of each parameter on demand. The value of this feature can't be over-emphasized, especially when dealing with Java's GridBagConstraints? constructor! 11 parameters!! -- EricHodges
Ok, but the point is not necessarily to be able to write, but also to be able to read. Now imagine those 11 parameters of GridBagConstraints? (most of them are ints, some are floats), if you see them in a line of code, it is simply ugly !!
Combined with the lack of optional parameters, it is a terrible combination. IntroduceParameterObject helps a little bit and IntroduceParameterObject not that much, but these are not good refactoring or good design patterns, they are simply workarounds to the lack of capability in the language. Take for example the typical parse operation of an XML file. Thanks in part to the complexity of Xml, in the Xerces parser this has more than 20 boolean options.
Now imagine how you'd see a method call:
ParserUtility?.parse(InputStream?, true,false, false, false, true, true, false,...)wouldn't that look cool in the source code ? So thanks to this "feature" of XML, plus the language design, plus JAXP transforms that into:
SAXParserFactory factory= SAXParserFactoryImpl.newInstance(); factory.setNamespaceAware(false); factory.setValidating(false); SAXParser parser; try { factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); parser= factory.newSAXParser(); } catch(Exception ex) { throw new RuntimeException("Exception in parser factory: "+ex);} // now we can call parser.parse()So courtesy of refactorings and some FactoryPattern I ended up with > 6 lines of code where one should have sufficed, plus that ugly dependency on a stupid URL, for which the symbolic name in Xerces was protected.
A designer in a language with KeywordParameterPassing will have no problem to offer the default parameters and named parameters so that I can write:
ParserUtility?.parse inputStream ~namespace:false ~validate:false ~loadExternalDTDs: falseNow isn't this much more elegant than having to go through all the hooplas of refactoring and factories and who knows what else ? Keyword parameter passing and default parameter values are definitely a cool language feature.
You're right. There's no excuse for the GridBagConstraints? constructor. Keywords would definitely help. (Wow. Costin convinced me of something. That's a first!) -- EricHodges
Glad to here that, than maybe the "refactoring" pattern deserves a page on its own. EmulateKeywordAndDefaultParameters.
I think this argument is rather weak. I found myself quite fascinated by the use of keywords in SmallTalk(though a bit different) and PythonLanguage, and suppose it's definitely towards good SE. Modularity can't be enhanced merely by hiding the names of parameters at the expense of code readability/maintainability, and etc. If you think hiding the names of parameters is a good thing, why not hide the names of procedures as well and use something like, procedures[3] to indicate the third procedure from the beginning of the code? Is KeywordParameterPassingConsideredHarmful? widely accepted whether in academia or in the trenches? -- JuneKim
The PerlLanguage supports named parameter passing and I've grown to prefer it. It allows you to set only what you need to set and the rest can default. New parameters can be added without breaking code that doesn't care. It does add more validation/testing. I don't recall a lot of literature on the subject, I guess because most languages don't support it. -- AnonymousDonor
Positional parameters can be considered to be an example of MagicNumbers. E.g. "parameter 1 is the string to be searched, parameter 2 the string to search for". It is commonly accepted that MagicNumbers are a CodeSmell and they should be refactored into constants. KeywordParameterPassing would be that refactoring.
However, it is much harder to refactor a language than it is to refactor code.
Use an ArgumentObject. It provides all the benefits of keyword parameters, plus lets you do other interesting things like share the object among calls - maybe even calls to different functions (could be an interesting use of MultipleInheritance, although I'd have to think it through). -- BillTrost
I think a mix is nice. Some parameters go best as a fixed parameter, and others as a named parameter. If you have only named parameters, then some things become long and hard to read IMO. But one thing about named parameters is that sometimes it is nice to have keywords without sub-parameters. Example:
printImage("foo", forceColor=true) printImage("foo", #forceColor)// short-cut printImage("foo", #forceColor true)In the second one we can have named parameters that serve as commands by defaulting to a value of "true" if no sub-parameter is supplied. It requires a different syntax arrangement than equal signs, though. I like that approach, but don't see it very often.
It is probably a personal choice that sparks HolyWars.
Languages that support KeywordParameterPassing:
KeywordParameterPassing seems redundant in languages with StaticTyping, since the parameter types act as keywords, except when two parameters have the same type. However, KeywordParameterPassing could be very helpful with DynamicTyping.
That completely misses the point, you don't declare the types when calling a method, only when defining it. The types can't act as keywords when calling the method. KeywordParameterPassing is a great pattern in both static and dynamic languages, and if you don't have it, you'll hack up your own version anyway.
Types aren't nearly informative enough. I have to look up the argument order to memcpy or bcopy every time I use it, but I can remember that the prototype is "memcpy(void *, void *, int)", with a "const" thrown in there somewhere.
That's an issue in C, though it helps to remember that the destination pointer comes first...and miss the previous point entirely: memcpy and bcopy have different argument orders, but similar signatures (void*, void*, size_t). The destination pointer is first in memcpy, but the source is first in bcopy.
However, in Java most of the methods have a signature "doSomething(Foo foo, Bar bar)" with distinct types. KeywordParameterPassing, on top of StaticTyping, would require too many keystrokes. But then again, it's also too many keystrokes to constantly have to type in type declarator after type declarator when declaring methods or classes too. For this reason, any industrial-grade development of Java is typically done with an IDE that is Java-aware, so you don't waste those precious keystrokes. I suppose you can apply the same idea to keyword arguments too.
KeywordParameterPassing has other advantages, that are valid in a static typing context:
The following AdaLanguage example is cited from Michael L. Scott's ProgrammingLanguagePragmatics, pp.454-455:
type field is integer range 0..integer'last; type number_base is integer range 2..16; default_width : field := integer'width; default_base : number_base := 10; procedure put (item : in integer; width: in field:= default_width; base : in number_base := default_base);and then, when we call this put procedure,
put (37, 4); put (item => 37, base => 8); put (base => 8, item => 37); put (37, base => 8);Keyword parameters passing has advantages over positional parameters passing when there are a lot of parameters for a function, with default parameters. A LongParameterList is generally considered a CodeSmell.
In CommonLisp, keyword parameters can only come after all the non-keyword parameters, i.e.
(defun foo (a b &key (c 10) (error nil)) ...)foo may be called
(foo 1 2) ; c will have value 10, error will be nil (foo 1 2 :c 12) ; c has value 12, error will be nil (foo 2 3 :error t) ; c has value 10 (foo :c 10) ; Error! a,b missing.Parsing keywords in CommonLisp is expensive, so stylistically, this is only done for top-level, publicly visible functions. They are also considered to be somewhat self-documenting.
Regarding the paragraph quoted above. There is no reason that the names exported to the caller need match the names used internally.
The primary question is "Do the advantages of Keyword Parameter Passing out weigh the costs?"
In code that is upgraded as a unit, such as a single executable or a package of related executables, the answer appears to be "no."
The areas where keyword parameter passing start to become valuable are when software modules can be updated independently and where data passing is done by some means other than stack pushes.
For an alternative approach, see PerliGata.
For me, ItDepends. Whatever seems to be simultaneously clearest, most practical and elegant.
ParserUtility??.parse inputStream ~namespace:false ~validate:false ~loadExternalDTDs: false
is good
max argument1:5 argument2:6
isnt
See also: EmulateKeywordAndDefaultParameters, UniversalStatement, PositionalVersusNamedParameters