[
https://issues.apache.org/jira/browse/FREEMARKER-107?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16947936#comment-16947936
]
Pascal Proulx commented on FREEMARKER-107:
------------------------------------------
Sounds good to me.
.args would be primarily a documentation clarity feature for me. If you write a
small API for #import and all your macros are like this (because you need
access to all args as a map):
{code:java}
<#macro m1 args...><#-- tons of code -->${args.a!3}<#-- tons of code
--></#macro>
<#macro m2 args...><#-- tons of code -->{args.b!4}<#-- tons of code
--></#macro>{code}
then you have to spend time documenting the interface in comments (in a custom
format), otherwise users have to read through your implementation (which can
get lengthy) to figure out what the arguments and default values are. If the
args are declared in the interface then it's more self-documenting and friendly
to people new to freemarker:
{code:java}
<#macro m1 a=3 b=4><#-- tons of code -->${a}<#-- tons of code
--><@m3?spread_args(.args) e=3/><#-- tons of code --></#macro>
<#macro m2 c=5 d=6><#-- tons of code -->${.args.d}<#-- tons of code
--><@m3?spread_args(.args) e=3/><#-- tons of code --></#macro>
{code}
It also becomes easier to use/write documentation parsing tools in the latter
case since it is more standard.
Of course you could create #locals for all your parameters at the beginning of
the macro, but it is excessively verbose with a lot of parameters and a lot of
the assignments may go unused depending on the code. I did yet another
alternative to this using extra maps to define the parameters and merging it
with the args catch-all, but it is not elegant, and most likely adds more
overhead than if it were provided by a native Freemarker construct. It is an
effort to simplify the code. Note despite what I wrote above I think .locals
did not work for this (.args would be all the macro parameters, including the
catch-all ones - or you could have both, one that includes the catch-all ones,
and one that does not, e.g.: .args_explicit).
Furthermore this would allow me to make better use of the catch-all parameter,
i.e. to restore it to its original purpose, to catch "extra" arguments. That
also was a hindrance that required more workarounds.
Thanks
> Hash expansion to macro arguments (Python **kwargs style)
> ---------------------------------------------------------
>
> Key: FREEMARKER-107
> URL: https://issues.apache.org/jira/browse/FREEMARKER-107
> Project: Apache Freemarker
> Issue Type: New Feature
> Components: engine
> Affects Versions: 2.3.28
> Reporter: Pascal Proulx
> Priority: Major
>
> Hello,
> We heavily rely on Freemarker macros to build a helper template API, but have
> had to make large workarounds for passing contents of hashes as macro
> arguments, for several years. (In truth I should have made this ticket much
> sooner!)
> It would help greatly simplify our work to have hash expansion to macro
> arguments, like this:
> {code:java}
> <#macro myMacro arg1 arg2 arg3="value3">...</#macro>
> <#assign myHash = {"arg1":"value1", "arg2":"value2"}>
> <@myMacro **myHash/><#-- the hash contents are passed as parameters, instead
> of the hash itself -->
> {code}
> This exists in Python:
> {code:java}
> def test_var_args_call(arg1, arg2, arg3):
> pass
> kwargs = {"arg3": 3, "arg2": "two"}
> test_var_args_call(1, **kwargs)
> {code}
> Essentially the hash contents fill in any arguments not explicitly specified.
> For the case where arguments are specified in addition to the hash, you may
> need to decide on a good syntax, e.g.:
> {code:java}
> <@myMacro arg1="value1" **myHash/>{code}
> This example doesn't have much precedent in freemarker syntax but is fairly
> understandable.
> Although we don't need it nearly as much, the same could be done with lists
> and function arguments:
> {code:java}
> <#function myFunc arg1 arg2>...</#function>
> <#assign myList = ["val1", "val2"]>
> ${myFunc(*myList)}
> <#assign myList = ["val2"]>
> ${myFunc("val1", *myList)}
> {code}
> Again similar to Python:
> {code:java}
> def test_var_args_call(arg1, arg2, arg3):
> pass
> args = ("two", 3)
> test_var_args_call(1, *args)
> {code}
> You might want this for consistency, although in practice the hash expansion
> will be many times more useful to us.
> If there's a lack a manpower I could try to see what I can do digging into
> the source, but wanted to bring this up for discussion first. It doesn't
> appear hard to implement to dump a hash into the macro args map, but there is
> defining the syntax.
> We use Freemarker 2.3.28 at the moment.
> Thank you
--
This message was sent by Atlassian Jira
(v8.3.4#803005)