Thanks Daniel for your feedback. See my answers below

Am So., 11. Nov. 2018 um 19:14 Uhr schrieb Daniel Dekany <[email protected]
>:

> Sunday, November 11, 2018, 11:40:50 AM, Christoph Rüger wrote:
>
> > Am So., 11. Nov. 2018 um 09:25 Uhr schrieb Daniel Dekany <
> [email protected]
> >>:
> >
> >> Saturday, November 10, 2018, 3:08:14 PM, Denis Bredelet wrote:
> >>
> >> > Hi,
> >> >
> >> > Le 9 novembre 2018 à 22:36, Christoph Rüger <[email protected]> a
> >> écrit :
> >> >
> >> > Am Fr., 9. Nov. 2018 um 22:55 Uhr schrieb Daniel Dekany <
> >> [email protected]
> >> > :
> >> >
> >> > It's certainly tricky, but as far as I see possible (but then, who
> >> >
> >> > knows what will one find when actually working on it). It's also a
> >> > feature missing a lot. It's especially missing for #list (I know that
> >> > you need it for something else), because if you filter the items
> >> > inside #list with #if-s, then #sep, ?hasNext, etc. will not be usable.
> >> >
> >> > Let me say that I disagree here.
> >> >
> >> > I do not think that closures are required for FreeMarker, nor that
> they
> >> are a good idea.
> >> >
> >> > If we add new features to the FreeMarker *tempate engine* I would
> >> > rather we focus on multi-part macro body rather than an advanced
> >> language feature like closures.
> >> >
> >> > You can add ?filter and ?map if you want, a simple expression as
> >> parameter should be enough.
> >>
> >> Yes, as I said, we certainly start with only allowing lambdas in
> >> ?filter/?map, also certainly in ?contains.
> >>
> > Would be enough in my opinion and very useful.
> >
> > Is it possiblefor you to give some pointers to the code on how this could
> > be implemented? I would maybe like to wrap my head around this a little
> bit.
>
> Please feel yourself encouraged! (:
>
> > I started looking at seq_containsBI (
> >
> https://github.com/apache/freemarker/blob/a03a1473b65d9819674b285a0538fed824f37478/src/main/java/freemarker/core/BuiltInsForSequences.java#L291
> )
> > and
> > and reverseBI (
> >
> https://github.com/apache/freemarker/blob/a03a1473b65d9819674b285a0538fed824f37478/src/main/java/freemarker/core/BuiltInsForSequences.java#L264
> )
> > just to find something related (seq_containsBI checks something) and
> > reverseBI returns a new sequence.
> > What I haven't found is a function which takes an Expression as a
> > parameter.
> > Is there something similar already or would that be a new thing?
>
> It's a new thing in that it will be part of the expression syntax
> (even if for now we will only allow lambdas as the parameters of a few
> built-ins, so that we can get away without closures). So it's a new
> Expression subclass, and has to be part of the parser (ftl.jj) as
> well.

Hmm, that parser stuff is new for me, it'll take me some time to get into
it.


> As of lazy evaluation of parameters expressions, that's already
> done in the built-ins in BuiltInsWithParseTimeParameters, and you will
> see it's trivial to do, but the situation there is much simpler.
>


>
> In principle, a LambdaExpression should evaluate to a
> TemplateMethodModelEx, and then you pass that TemplateMethodModelEx to
> the called built-in or whatever it is. But with the approach of
> BuiltInsWithParseTimeParameters we can certainly even skip that, and
> just bind to the LambdaExpression directly, add a LocalContext that
> contains the lambda arguments, end evaluate the LambdaExpression right
> there, in the built-in implementation. Or at least at a very quick
> glance I think so.
>
Not sure I can follow completely but that hint with*
BuiltInsWithParseTimeParameters* got me started, but at the moment I'm
stuck as I need to get more familiar with the internals of Freemarker. I am
also not sure I am on the same page regarding the syntax we are aiming for
and why I would need to extend the parser when there is something like
BuiltInsWithParseTimeParameters....

Here is an example what I have in mind:
I started with the ?filter() builtin. I had a syntax like this in mind:

*Example 1: ["a","b","c"]?filter(element, element == "c")*
*Example 2: ["a","b","c"]?filter(element, element == someOtherVariable,
someOtherVariable="c")*
Not sure if that's what you have in mind too, but to me it made sense with
regards to BuiltInsWithParseTimeParameters and I could start without
touching parser stuff.

*1st argument 'element'* would just be the iterator variable similar to
<#list ["a","b","c"] as *element*>
2nd argument is the filter lambda expression... aka our filter condition
3rd+n argument are optional parameters in case used in the lambda expression

So at first I was looking how <#list> works and found IteratorBlock, and
though I could reuse it somehow.

Here is some simple pseudo code I played around for the for Example 1:

static class filter_BI extends BuiltInWithParseTimeParameters {



        TemplateModel _eval(Environment env) throws TemplateException {

            // sequence

        TemplateModel targetValue = target.evalToNonMissing(env);



            List parameters = this.parameters;



            Expression iteratorAlias = (Expression) parameters.get(0);

            Expression conditionExpression = (Expression) parameters.get(1);



            TemplateSequenceModel seq =  (TemplateSequenceModel) target.eval
(env);

            for (int i = 0; i < seq.size(); i++) {

               TemplateModel cur = seq.get(i);


               // this is where I am stuck at the moment

               // I basically want to evaluate conditionExpression
where iteratorAlias
is basically what I passed as 'element'

               // I am not sure if or how LocalContext could come into play
here

               // basically for each iteration I would assign the current
loop element to a context variable with the name 'element'

               // and then evaluate conditionExpression with that context.

               // if conditionExpression is "true" then I would populate
add the current sequence element 'cur'

               // to a new result-List.... and return that.... something

               // I wanted to reuse IteratorBlock here somehow, but didn't
get it to work yet.

               // maybe this is a stupid idea, or we just need something
similar



            }

}



Ok so far for my pseudo code....  Maybe you could give some more pointers
based on that... in case this makes any sense ...



Another similarity to BuiltInsWithParseTimeParameters is that we won't
> allow separating the `?someBI` and `(arg)`. Like, with the example of
> `cond?then(1, 2)`, you aren't allowed to do this:
>
>   <#assign t=cond?then>
>   ${t(1, 2)}
>
> That maybe looks natural, but most other built-ins allow that. Of
> course we can't allow that for ?filter etc., because then we need
> closures again.
>
> >> Multi-part macro body is also planned. Means, I know it definitely
> >> should be added, but who knows when that's done... I mean, it's like
> >> that for what, a decade? (: It's not even decided what it exactly
> >> does, as there are many ways of approaching this. (I have my own idea
> >> about what the right compromise would be, but others has other
> >> ideas...)
> >>
> >> Filtering lists bothers me because the template language should be
> >> (and somewhat indeed is) specialized on listing things on fancy ways
> >> that used to come up when generating document-like output. (If it
> >> doesn't do things like that, you might as well use a general purpose
> >> language.) Thus, that filter is unsolved (filtering with #if is
> >> verbose and spoils #sep etc.) bothers me a lot.
> >>
> >> BTW, ?filter and ?map is also especially handy in our case as
> >> FreeMarker doesn't support building new sequences (sequences are
> >> immutable). Although it has sequence concatenation with `+`, it's not
> >> good for building a sequence one by one, unless the sequence will be
> >> quite short.
> >>
> > Good point.
> >
> >
> >>
> >> > Cheers,
> >> > -- Denis.
> >>
> >> --
> >> Thanks,
> >>  Daniel Dekany
> >>
> >>
> >
>
> --
> Thanks,
>  Daniel Dekany
>
>
Thanks
Christoph

-- 
Synesty GmbH
Moritz-von-Rohr-Str. 1a
07745 Jena
Tel.: +49 3641 5596493Fax.: 
+49 3641 5596499
Internet: https://synesty.com <https://synesty.com>


Geschäftsführer: Christoph Rüger
Unternehmenssitz: Jena
Handelsregister B 
beim Amtsgericht: Jena
Handelsregister-Nummer: HRB 508766
Ust-IdNr.: 
DE287564982

Reply via email to