groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From emmanuel r <>
Subject RE: Required named parameters in constructor?
Date Tue, 19 Apr 2016 03:21:05 GMT
You know, I bet that could be done with an ast transformation. Using it
could look like this:

@RequiredConstructorParameters(parameters = ['a'])
class Foo {
    String a
    String b
On Apr 18, 2016 2:33 PM, "Winnebeck, Jason" <>

> I think Groovy is limited here to the JVM's features. It is not possible
> to implement named parameters properly since you don't know the method
> names (except when using an optional compiler param in Java 1.8+), so there
> is not truly named parameters in Groovy. Instead, all of the named
> parameters are converted into a Map. And Groovy does allow positional and
> named parameters in the same call, where all of the named parameters are
> collected into a single map.
> As far as I know the best solution for enforcing the named parameters is
> just to check for their presence in the map manually in the function itself.
> The only place I see in Groovy where "named parameters" actually works
> well is when constructing an object -- the names parameters all turn into
> setter calls. It is possible to abuse this so that Groovy code would fail
> when trying to set non-existant parameters, but it doesn't solve the
> required parameters issue without manual code. It also has the benefit of
> code completion in IDE and type checking. Specifically I am talking about:
> class FooCall {
>   String a
>   String b
>   void call() {
>     if (!a || !b)
>       throw new IllegalArgumentException("a and b are required");
>     println "call $a $b"
>   }
> }
> new FooCall(a:"a", b:"b")()
> However, the code is very awkward. That's not much better than:
> REQ_PARAMS = ['a', 'b'] as Set
> ALL_PARAMS = REQ_PARAMS + ['c'] as Set
> void foo(Map params) {
>   params = params ?: [:]
>   if (!params.keySet().containsAll(REQ_PARAMS))
>     throw new IllegalArgumentException("Missing required parameters
> ${REQ_PARAMS - params.keySet()}")
>   if (params.keySet() - ALL_PARAMS)
>     throw new IllegalArgumentException("Extra parameters ${params.keySet()
>   println "foo $params"
> }
> foo(a:1, b:1, c:1)
> Jason
> -----Original Message-----
> From: David M. Karr []
> Sent: Monday, April 18, 2016 1:50 PM
> To:
> Subject: Required named parameters in constructor?
> First of all, I'm not attempting a "Groovy vs. anything else" argument, so
> put away the flamethrowers.  I find myself defending Groovy when I have the
> chance.
> I was, however, reading a Ruby book, as I've never looked at it before, as
> I found I had to learn about Puppet, and I concluded that you can't work
> effectively with robust Puppet modules without understanding Ruby.
> As a result, I found myself paying attention to to how Ruby features map
> to Groovy.  I'm not talking about syntax, just functional features.
> I got to the point in the Ruby book where it mentioned that you could set
> particular keyword parameters (like Groovy Named Parameters) to be
> required.  I can't think of a "direct" way to map this to Groovy.  I
> suppose you could implement an "ad hoc" strategy that throws if particular
> values aren't set.  Is there a more concise way?
> Just as an observation, I also note that Ruby allows mixing both
> "positional" and "named" parameters in the same constructor call.
> ----------------------------------------------------------------------
> This email message and any attachments are for the sole use of the
> intended recipient(s). Any unauthorized review, use, disclosure or
> distribution is prohibited. If you are not the intended recipient, please
> contact the sender by reply email and destroy all copies of the original
> message and any attachments.

View raw message