[
https://issues.apache.org/jira/browse/FREEMARKER-107?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16949448#comment-16949448
]
Dániel Dékány edited comment on FREEMARKER-107 at 10/11/19 1:31 PM:
--------------------------------------------------------------------
Aha, I see. That seems to be something that increases the value of
{{spread_args}} significantly. I will see if there are any major technical
gotchas with implementing {{.args}}.
As you are saying, {{.args}} has to contain the catch-all parameters
"exploded". One problematic edge case is, what if the call to {{m2}} passed
arguments by positional, as in {{<@m2 1 2 3 4/>}}, and {{m2}} has a catch-all
arguments. While repeating the positional call on {{m3}} is possible
technically, people could burn themselves too easily (not expecting that
arguments are sometimes aren't matched by name, but by order, when
{{?spread_args(.args)}} is applied). So, I think that inside a macro, {{.args}}
will always return an "FTL hash" (a map really), and so using it for a
positional call that has non-empty catch-all argument is always an error,
because we can't associate names to the catch-all arguments then. We could just
return a sequence for the whole {{.args}} in that case, and it's even logical
to do as the call was positional, but I think it's too dangerous/surprising in
practice to do so. Inside functions, however, {{.args}} will always return an
"FTL sequnce" (a list).
was (Author: ddekany):
Aha, I see. That seems to be something that increases the value of
{{spread_args}} significantly. I will see if there are any major technical
gotchas in implement {{.args}}.
As you are saying, {{.args}} has to contain the catch-all parameters
"exploded". One problematic edge case is, what if the call to {{m2}} passed
arguments by positional, as in {{<@m2 1 2 3 4/>}}, and {{m2}} has a catch-all
arguments. While repeating the positional call on {{m3}} is possible
technically, people could burn themselves too easily (not expecting that
arguments are sometimes aren't matched by name, but by order, when
{{?spread_args(.args)}} is applied). So, I think that inside a macro, {{.args}}
will always return an "FTL hash" (a map really), and so using it for a
positional call that has non-empty catch-all argument is always an error,
because we can't associate names to the catch-all arguments then. We could just
return a sequence for the whole {{.args}} in that case, and it's even logical
to do as the call was positional, but I think it's too dangerous/surprising in
practice to do so. Inside functions, however, {{.args}} will always return an
"FTL sequnce" (a list).
> 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)