''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 I''''nStrRev function, as documented in MSDN: I''''nStrRev(string1, string2[, start[, compare]]) OK, let's consider... * Which parameter is the big string you're searching through, and which is the small string you wish to find? ''(Why "#1" is the string being searched, and "#2" is the string I wish to find -- of course!)'' * Both 'start' and 'compare' are optional, but 'start' is required if I wish to pass 'compare'. I wish to do a text comparison (compare=vbTextCompare), which is not the default, but I wish to search the whole string... * 'I''''nStrRev(s1,s2,,vbTextCompare)' is not valid syntax. * 'I''''nStrRev(s1,s2,-1,vbTextCompare)' hard codes the internal implementation knowledge that the function uses -1, an invalid value, to represent the default value for a missing parameter. * 'I''''nStrRev(s1,s2,len(s1),vbTextCompare)' is required, icky, redundant, and needs to be tested to make sure it's right. Why can't I say 'I''''nStrRev( search => s1, find => s2, comparison => vbTextCompare )'? * Too verbose in my opinion. Named parameters are best for optional parameters. I prefer languages that have fixed parameters on the left, and named params on the right. Thus: 'I''''nStrRev(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 I''''''nStrRev() 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: false Now 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 MagicNumber''''''s. E.g. "parameter 1 is the string to be searched, parameter 2 the string to search for". It is commonly accepted that MagicNumber''''''s 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 HolyWar''''''s. ---- Languages that support KeywordParameterPassing: * AdaLanguage * CommonLisp * PythonLanguage * PerlLanguage * NiceLanguage * RubyLanguage * ToolCommandLanguage (by convention) * VisualBasic * ... * EeLanguage * SmalltalkLanguage (in a different way) * ObjectiveCee (similar to Smalltalk) ---- 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. * What about reading the code? An IDE may reduce keystrokes by typing repetative stuff for you, but it is still bulk that one has to read when reading code. Being reader-friendly is more important than being writer-friendly in my opinion. * The APL/J/K style of lumping entire paragraph's worth of semantic content into a single character is not conducive to maintenance. Indeed, a rule of thumb in the J community is that it's always easier to rewrite the procedure you're maintaining than it is to recover its original intent. Where I work, long, descriptive names are not only a good idea, ''it's the law.'' I just ''love'' it when you see people argue about Unix commands, for example, which are often short and terse. But, then, you need to pass --long_options to them in order to figure out what the heck the parameters are for. That's what keyword arguments are -- they're --long_options for your functions. I speak from experience when I say that long, self-describing names actually ''enhance'' readability. WriteYourCodeLikeProse, and let your program explain itself. It actually lessens ''your'' mental load big-time. Static typing only helps when ''all'' the arguments have different types. This is not always the case. KeywordParameterPassing is therefore ''not'' redundant in languages with static typing. KeywordParameterPassing has other advantages, that are valid in a static typing context: * the semantics of the call is more obvious, because the keywords document the usage parameters, provided the names are well chosen * one does not need to remember the order of the arguments * if parameters can be given a default value, they allow you to only specify the parameters for which you don't want to use the default. ---- 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." * It does not simplify writing of the calling function, one must still reference the definition of the desired function to determine the parameter keywords. * It is arguable whether it improves the accuracy of the initial writing of the calling function. Misordered parameters tend to be a fairly rare problem. * It does significantly increase the execution cost of a function. Stack pushes are a primitive operation in almost all microprocessors, parsing text string is not. [MacReiter - "parsing text strings" is a moot point for any language that has a "compilation" stage, even if it is bytecode or JIT compilation, because you're doing a symbol lookup inside the compiler. You don't do runtime text searches to decide which function to call (not even in SmalltalkLanguage which uses DuckTyping), so why would you use runtime text lookups for KeywordParameterPassing? Separate compilation units don't affect this, because you must provide the interface, which is all the compiler needs -- the implementation can use the symbols in the interface to decide the order to push elements on the stack (sorry, I'm thinking of a simple KeywordParameterPassing extension to something like C++, where the language and function call implementation itself wouldn't be changed, only the code generation path would be changed). Final execution speed would be completely unaffected.] 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. * Keyword parameter passing permits method overloading in interfaces. With stack based parameter passing, method overloading is accomplished by evaluating the parameters being passed, with keyword parameter passing, method overloading is accomplished at runtime by having the called function evaluate the parameters being passed. This capability can be valuable in maintaining compatibility between different revisions of software. * When memory based parameter passing is not used, the additional cost of parameter parsing may be hidden by the cost of parameter passing. The time spent parsing parameters may be insignificant compared to reading the parameters from a file, a database, or across a network. * Especially for bulk retrieval of sparsely populated data, keyword parameter passing may provide reduction in data transmission size compared to fixed size data structures. The added size of the keywords may be offset by the elimination of null data fields. ---- 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 ---- CategoryLanguageFeature