You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@groovy.apache.org by Michael Rüegg <ru...@gmail.com> on 2016/11/23 07:50:22 UTC
Named function arguments in Groovy
Hi,
I have a DSL where I want to pass named arguments like follows:
def foo(String a, String b, String c, Closure d) {
}
foo(a=“a”, c=“c”, b=“b”) {
}
I’m aware that named arguments are supported by receiving the arguments with a map:
def foo(Map<String, String> obj, Closure c) {
}
foo(a:"a", c:”c", b:”b") {
}
The problem with this approach is that for a user of this DSL, it is not obvious which parameters are expected and what their names are (beside documenting it, but who is going to read that ;-)).
How can I achieve named function arguments with “real" syntax in Groovy? Is there an alternative to using maps for this?
By the way, I think it is kind of misleading for a beginner that the following compiles but does not pass the arguments in the intended order:
foo(a="a", c=“c", b=“b") {
// a == a, b == c, c==b
}
Is this intended behaviour?
Thanks in advance,
Michael
Re: Named function arguments in Groovy
Posted by Michael Rüegg <ru...@gmail.com>.
Hi Krzysztof, Hi OC,
Thanks for your suggestions. I think the approach of GROOVY-7956 would be a great addition towards making DSL’s better readable. I would prefer
Sql.newInstance(url: "jdbc:mysql://localhost:3306/words", user: "words”, password: "words", driver:"com.mysql.jdbc.Driver”)
anytime over the less readable
Sql.newInstance("jdbc:mysql://localhost:3306/words", "words", "words", "com.mysql.jdbc.Driver”)
with the additional benefit compared to the "Map trick" that the IDE could help me when I make a mistake.
@OC: yes, you’re right, I did it in a script which led to this confusion. Inside a “normal” class the behaviour makes sense.
Best regards,
Michael
> On 23 Nov 2016, at 22:35, Krzysztof Kowalczyk <ko...@gmail.com> wrote:
>
> Hi Michael,
>
> Have you flowing feature request?
> https://issues.apache.org/jira/browse/GROOVY-7956
>
> Check links in the comments.
>
> Regards,
> Krzysztof
>
> On 23 November 2016 at 20:01, OC <oc...@ocs.cz> wrote:
> Michael,
>
> On 23. 11. 2016, at 8:50, Michael Rüegg <ru...@gmail.com> wrote:
>
> > The problem with this approach is that for a user of this DSL, it is not obvious which parameters are expected and what their names are (beside documenting it, but who is going to read that ;-)).
>
> Well, if someone is too sexy to read documentation, serves him right, does it not?
>
> That said, some way of checking argument names would be nice.
>
> > How can I achieve named function arguments with “real" syntax in Groovy? Is there an alternative to using maps for this?
>
> It does not need to be an alternative to map; just perhaps adding a way to inform the compiler which names (and types) are allowed and which are not.
>
> I believe you could DIY through ASTTs, but aside of that, far as I can say, there's currently no way compile-time. Runtime, of course, you can DIY much easier :)
>
> > By the way, I think it is kind of misleading for a beginner that the following compiles
>
> I would rather think it would be highly suspicious if it did not compile, for beginner or experienced programmer just as well.
>
> > but does not pass the arguments in the intended order:
>
> It does. The order is as declared.
>
> > foo(a="a", c=“c", b=“b") {
> > // a == a, b == c, c==b
> > }
> >
> > Is this intended behaviour?
>
> Definitely, since it is nothing Groovy-specific: three very plain positional arguments, whose values happen to be given using expressions. In this case, assignment expressions.
>
> There are two a's (two b's, two c's) -- one outside the method (and that's the one you assign the value to by the expression); another inside (and it gets the result of the appropriate expression, positionally).
>
> Possibly you have tested that in a script, which might get confusing for it (sort of) creates those outside a, b and c for you automatically without you having to declare it. Try it in a normal class, and you'll see the trick.
>
> All the best,
> OC
>
>
Re: Named function arguments in Groovy
Posted by Krzysztof Kowalczyk <ko...@gmail.com>.
Hi Michael,
Have you flowing feature request?
https://issues.apache.org/jira/browse/GROOVY-7956
Check links in the comments.
Regards,
Krzysztof
On 23 November 2016 at 20:01, OC <oc...@ocs.cz> wrote:
> Michael,
>
> On 23. 11. 2016, at 8:50, Michael Rüegg <ru...@gmail.com> wrote:
>
> > The problem with this approach is that for a user of this DSL, it is not
> obvious which parameters are expected and what their names are (beside
> documenting it, but who is going to read that ;-)).
>
> Well, if someone is too sexy to read documentation, serves him right, does
> it not?
>
> That said, some way of checking argument names would be nice.
>
> > How can I achieve named function arguments with “real" syntax in Groovy?
> Is there an alternative to using maps for this?
>
> It does not need to be an alternative to map; just perhaps adding a way to
> inform the compiler which names (and types) are allowed and which are not.
>
> I believe you could DIY through ASTTs, but aside of that, far as I can
> say, there's currently no way compile-time. Runtime, of course, you can DIY
> much easier :)
>
> > By the way, I think it is kind of misleading for a beginner that the
> following compiles
>
> I would rather think it would be highly suspicious if it did not compile,
> for beginner or experienced programmer just as well.
>
> > but does not pass the arguments in the intended order:
>
> It does. The order is as declared.
>
> > foo(a="a", c=“c", b=“b") {
> > // a == a, b == c, c==b
> > }
> >
> > Is this intended behaviour?
>
> Definitely, since it is nothing Groovy-specific: three very plain
> positional arguments, whose values happen to be given using expressions. In
> this case, assignment expressions.
>
> There are two a's (two b's, two c's) -- one outside the method (and that's
> the one you assign the value to by the expression); another inside (and it
> gets the result of the appropriate expression, positionally).
>
> Possibly you have tested that in a script, which might get confusing for
> it (sort of) creates those outside a, b and c for you automatically without
> you having to declare it. Try it in a normal class, and you'll see the
> trick.
>
> All the best,
> OC
>
>
Re: Named function arguments in Groovy
Posted by OC <oc...@ocs.cz>.
Michael,
On 23. 11. 2016, at 8:50, Michael Rüegg <ru...@gmail.com> wrote:
> The problem with this approach is that for a user of this DSL, it is not obvious which parameters are expected and what their names are (beside documenting it, but who is going to read that ;-)).
Well, if someone is too sexy to read documentation, serves him right, does it not?
That said, some way of checking argument names would be nice.
> How can I achieve named function arguments with “real" syntax in Groovy? Is there an alternative to using maps for this?
It does not need to be an alternative to map; just perhaps adding a way to inform the compiler which names (and types) are allowed and which are not.
I believe you could DIY through ASTTs, but aside of that, far as I can say, there's currently no way compile-time. Runtime, of course, you can DIY much easier :)
> By the way, I think it is kind of misleading for a beginner that the following compiles
I would rather think it would be highly suspicious if it did not compile, for beginner or experienced programmer just as well.
> but does not pass the arguments in the intended order:
It does. The order is as declared.
> foo(a="a", c=“c", b=“b") {
> // a == a, b == c, c==b
> }
>
> Is this intended behaviour?
Definitely, since it is nothing Groovy-specific: three very plain positional arguments, whose values happen to be given using expressions. In this case, assignment expressions.
There are two a's (two b's, two c's) -- one outside the method (and that's the one you assign the value to by the expression); another inside (and it gets the result of the appropriate expression, positionally).
Possibly you have tested that in a script, which might get confusing for it (sort of) creates those outside a, b and c for you automatically without you having to declare it. Try it in a normal class, and you'll see the trick.
All the best,
OC