I have used a lot of languages over the years, but I don't do Puppet in our team, so have not used Ruby myself, and have never programmed in Smalltalk. Could you elaborate on what named parameter features from Ruby/Smalltalk you had in mind ?

On 23.07.2017 01:00, Charles Monteiro wrote:
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 <mailto: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 <http://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 <http://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 <http://www.monteirosfusion.com>
sent from the road

Reply via email to