Something from the first mail of this thread that I want to emphasize
is that which parameter needs to be passed by position and which by
name is decided when the directive or function is defined. It's not
decided by the caller (see reasons below).
For example, the 1st parameter of #include can only be passed by
position, as in `<#include "foo.ftl">`. You can't write
`<#include template="foo.ftl">`. However, the `ignoreMissing`
parameter (and in FM2 we also had `encoding` and `parse` parameters)
can only be passed by name, as in
`<#include "foo.ftl" ignoreMissing=true>`. You can't write
`<#include "foo.ftl", true>`.
Some may have used languages where the caller decides what is passed
by position and what by name, but IMO it just leads to chaos in our
case. I also realize and accept that everybody has different taste,
but people read/edit other people's code a lot, so the taste of the
original author often doesn't matter much. Plus if someone overuses
positional parameters (laziness/rushing and C/Java habits may make
people do that...), the template becomes less readable, especially for
someone less experienced with writing templates. Consistency regarding
how core directives are called is even more valuable, as people
copy-paste it from StackOverflow etc. Imagine if in some cases you see
`<#if test=foo>`, while in others <#if foo>... confusing or annoying.
Now, we don't yet have a syntax in #macro and #function calls to
declare if a parameter passed by positional or by named. How should it
look?
My idea is that for directives by-name will be the default, and for
functions by-positional will be the default. To deviate from the
defaults, you add the proper option after the parameter name inside
`{}`, where `{}` is also a new thing, which will be later useful for
specifying other parameter related options as well (like, with a
totally fictional example, `myParam{byName, allowNull, max=100}`).
So here `x` and `y` are passed by position, and `color` and `id` by
name (and `id` defaults to `null`):
<#macro message text{byPosition}, color id=null>...</#macro>
<#function message(text, color{byName}, id{byName}=null)>...</#function>
So you can call these as:
<@message 'Hello World' color='red' id='test' />
and
message('Hello World', color='red', id='test')
Wednesday, July 5, 2017, 5:19:56 PM, Woonsan Ko wrote:
> On Tue, Jul 4, 2017 at 10:15 AM, Daniel Dekany <[email protected]> wrote:
>> Tuesday, July 4, 2017, 7:57:18 AM, Woonsan Ko wrote:
>>
>>> On Wed, Jun 21, 2017 at 2:30 PM, Daniel Dekany <[email protected]> wrote:
>>>> Friday, June 16, 2017, 8:41:37 PM, Daniel Dekany wrote:
>>>>
>>>>> A problem in FM2 is that when calling a directive (as a macro), either
>>>>> all parameters are positional (`<@message "Hi" 2 />`), or all
>>>>> parameters are named (`<@message content="Hi" height=2 />`); you can't
>>>>> mix the two (`<@message "Hi" height=2 />`). Also you can't use named
>>>>> parameters for functions/methods, only for directives. Worse, core
>>>>> directives don't even use named parameters, but some keyword like
>>>>> `as`, `using`... their syntax is hard coded into the parser, which is
>>>>> not nice, and will be a problem for the custom dialects feature.
>>>>>
>>>>> I think that with the exception of a few core directives (see them
>>>>> later) all directive calls should be like this, if for now (in this
>>>>> thread) we ignore loop variables:
>>>>>
>>>>> <#name posPar1 posPar2 namedPar1Name=namedPar1Value
>>>>> namedPar2=namedPar2Value>
>>>>
>>>> An adjustment to the above... I think that we should require comma
>>>> between positional arguments (but not between positional and named
>>>> arguments and between named arguments):
>>>
>>> "but not between ..." means that a comma can be *optionally* placed
>>> between named arguments or between a positioned argument and a named
>>> argument, right?
>>
>> I wouldn't allow that. If we do, then where to put comma becomes a
>> matter of taste, and the taste of individuals in the same project
>> differ, or for OS projects, whoever bumps into the templates might has
>> a different taste. So overall, you just end up with chaos, and if some
>> cares much, it's just unnecessary struggle (which of the 3
>> combinations is the Right Way). So I believe it's better overall if we
>> decide what's the right way for everyone... Especially as our taste is
>> based on more knowledge. FTL tags have this HTML-ish look-and-feel, so
>> naturally you write `<#foo n1=v1 n2=v2 m3=v3>`, and not
>> `<#foo n1=v1, n2=v2, m3=v3>`. So now, if we add a single positional
>> parameter, I think most will find it consistent like this:
>> `<#foo v0 n1=v1 n2=v2 m3=v3>` (like in `<@message "Hi" height=2 />`).
>> Still no comas anywhere. In the hopefully rare case when you have
>> multiple positional parameters, we unfortunately ran into ambiguity
>> issues, so then, and only then, and only between the positional
>> parameters you add commas. I think that's also matches common
>> conventions, where if you list something, you put commas *between* the
>> listed items, but not after the last one. Named parameters aren't
>> really listed (their order doesn't mater). So it's more logical to
>> only use comma where you must, not just a matter of taste.
>
> I concur with you now! Indeed, listing (positional args) requires
> comma delimiter, but non-listing (named args) doesn't.
>
>>
>> BTW, I was never a fan of this HTML-ish look-and-feel, because of the
>> confusing differences; people keep writing `foo="${x}"` instead of
>> `foo=x`. But that's the FM tradition, so I try to remain consistent
>> with the original idea. (When we manage to separate the expression
>> syntax from the top-level syntax, I think I will try to introduce an
>> officially supported alternative, something like `#foo(v0, n1=v1,
>> n2=v2, m3=v3)`.)
>
> That sounds great, too!
>
> Thanks again for the thorough thoughts and clarifications!
>
> Cheers,
>
> Woonsan
>
>>
>>> In other words, it is allowed to omit a comma between positional arg
>>> and named arg or between named args.
>>>
>>> Woonsan
>>>
>>>>
>>>> <#name posPar1, posPar2 namedPar1Name=namedPar1Value
>>>> namedPar2=namedPar2Value>
>>>
>>
>> --
>> Thanks,
>> Daniel Dekany
>>
>
--
Thanks,
Daniel Dekany