How about the same support as languages like Ruby and Smalltalk provide ? On Sat, Jul 22, 2017 at 5:17 PM MG <mg...@arscreat.com> wrote:
> Hi, > > having recently explained why Groovy is my language of choice got me > thinking about the few areas of Groovy where I personally wish for / see > the potential for improvement during my daily development tasks. > > I will start off with named paramters support, a topic that has been > moving more into my consciousness as the framework I develop at work > grew larger over time: I feel that the current named parameter support I > am aware of > (http://groovy-lang.org/objectorientation.html#_named_argument_constructor > / http://groovy-lang.org/objectorientation.html#_named_arguments ) is a > limited feature that fit relatively well with a purely dynamic language, > but is not nearly as well rounded / powerful as in other languages. > > Do you have any plans to support named parameters such as they exist > e.g. in PL/SQL (to be honest, I never expected I would ever quote PL/SQL > as a language that is superior to Groovy in any aspect before I thought > about this ;-) ), where named paramters are just a convenient (and > safer) way to call a callable, without loosing type safety, which works > in a purely static manner, and without requiring a method to explicitely > deal with a Map as its argument. > In short, a way to call any Groovy method/ctor with a syntax like: > > class Processor { > Processor(String name, boolean writeableQ = false, boolean > extendableQ = true, Number id = null, Worker defaultWorker = null, > Closure logCls = { println it }) { ... } > work(Worker worker = null, boolean dryRunQ = false, int > maxNrRetries = 10, boolean overwriteQ = false) { ... } > } > > final processor= new Processor(name:"Task 1", id:1234) { log.debug "T1: > $it" } // Closure as last argument can still be given outside of brackets > processor.work(maxNrRetries:99) > > > The grooviest thing of all would be, if there would be a way to keep the > flexibility of the map argument, and combine it with the named > arguments, to be able to e.g. define a different default set of default > values for a method/ctor. E.g. > > static ParametersMap getDebugWorkParams() { > return [ worker:dummyWorker, dryRunQ:true, maxNrRetries:0, > overwriteQ:true ] > } > > processor.work(*(debugWorkParams + [worker:logOnlyWorker, > maxNrRetries:3])) // dryRunQ=true and overwriteQ=true comes from > debugWorkParams; worker and maxNrRetries are give explicitly in call > > > In my case such a feature would have two benefits: > 1a) Make it easy to quickly add a final field to a root base class, > without having to do some a major ctor refactoring on all the child > classes (for which I typically don't have the time, meaning that I am > forced to add the field as non-final "for now", so I can modify it after > object creation where needed). > Note that this can, even if IntelliJ would not sometimes not get the > refactoring wrong (which can lead to hard to track bugs), not be covered > by better refactoring support: Not having to give all the values for the > parameters before the newly added parameter (but instead having them > take their default value) is not something a refactoring engine can supply. > 1b) Similar to 1a), for adding parameters to method calls > 2) Make the calling of ctors/methods safer in certain cases > a) When a ctor/method takes a lot of parameters of the same type, e.g. > boolean: createPackageSql(String name, boolean trimQ, boolean > indentLinesQ, boolean keepEmptyLinesIndentationQ, boolean > seperateFunctionsQ, boolean uppercaseKeywordsQ, boolean uppercaseNamesQ) > { ... } * > b) When a framework function is called by a framework user, e.g. from a > script, or generally in an environment where there is little or no test > coverage, and the paramter order can easily be confused: e.g. method > which retrieves a DB item through 2 IDs, and getting an empty result set > is not an error - which ID has to be given first ? Easy, when calling > with named paramters is supported pe.retrieveTreeNodeRow(orgUnit:123, > orgItem:456) . > > mg > > *Here a parameter object might be the better choice. But typically the > number of paramters was small at the beginning, and grew over time, so > initially no need for a paramater object existed. Again the refactoring > time needed to introduce a parameter object, the fact that your class > namespace gets cluttered with helper structures, external framework > users will have to adapt their code (or you must maintain a backward > compatibility facade), etc make this less practical than it might > initially seem... > > > > -- Charles A. Monteiro www.monteirosfusion.com sent from the road