[stringtemplate-interest] List comprehensions Was Re: Working with filtered list

John Snyders jjsnyders at rcn.com
Tue Jun 26 19:11:06 PDT 2007


The key thing here is that you want the iteration variable i to count 
the filtered items not the original items. In both the templates below 
$i$ is going to count the original items.

What you need is to filter first and then invoke the template that will 
optionally count the filtered items.

But this can't be done with string template. A template once invoked 
always returns a string never a list and so once you have filtered the 
list it is a string and can't be iterated over any more.

The solution, as you found, is to do the filtering in the program.

In a recent message on indexing lists 
(http://www.antlr.org:8080/pipermail/stringtemplate-interest/2007-June/001090.html)
I proposed the slice function. I wrote: "I think the request for 
indexing is mostly about wanting to iterate over a list differently. 
Just the first five, all but the last 2, every third one, etc.". The 
proposed slice function doesn't even handle the last example (every 
third one) and I specifically did not include other examples such as 
just the smart ones although that is a reasonable thing to want to do.

What would be really powerful is the Python list comprehension 
functionality. The question is does it break separation? StringTemplate 
already has the ability to construct new literal lists. I mention some 
problems with it here 
(http://hardlikesoftware.com/weblog/2007/06/01/thoughts-on-stringtemplate-part-1/) 
but adding list comprehensions like in Python could make it even better.
(see this for a quick intro to list comprehensions in Python: 
http://docs.python.org/tut/node7.html#SECTION007140000000000000000)

Here is what it might look like
$[x for x in data if x.IsSmart]:{ $it.CustomerName$ }$

No comparison expressions have been introduced. The program is still 
responsible for implementing the logic by setting the IsSmart property. 
It is just a combination of list iteration, if evaluation (the same if 
already supported), and list construction.

But the syntax is very Python. Is there something that may feel more ST 
like.

List construction already allows a comma separated list of expressions. 
So something like this is possible:
$[items, decorate("foo"), "bar"]: { x | ($x$)};separator="; "$

If it allowed templatesExpresson (this includes the syntax for 
iterating) then something like this would be allowed:
$[items:decorate(it), decorate("foo"), "bar"]: { x | ($x$)};separator="; "$
What this says is for each item in attribute items call the decorate 
template and add the string returned to the list being constructed then 
call the decorate template with string argument foo and add the result 
to the list then add plain old "bar" to the list. With the list just 
constructed iterate over it wrapping each item in ( ) and putting a "; " 
separator between each one.

By wrapping the iteration syntax in $[ ]$ it says rather than 
concatenate these into a string put them in a list.

Now this syntax may have some problems with figuring out where commas go 
if parallel lists or alternating lists are allowed. I'm not sure what to 
do about that. I already find it unfair that I can't combine parallel 
lists with alternating lists.

All that would be needed to have the power of Python list comprehensions 
is fitting in the "if" expression. Perhaps:
$items if it.isFancy :decorate(it)$
or
$items : { x | x.isFancy | Fancy: $x$. }$

On the other hand I wonder if the Python list comprehension syntax is 
more power full.

I'm sure there are more details to figure out.

Thats if for now. What do you think would list comprehensions be helpful 
for StringTemplate?
-John


Grzegorz Danowski wrote:
>
> Hi,
>
> I would like to filter list of customers and simultanously if output 
> list contains more customers then one I’d like to add sequence number.
>
> I have found template that filter data:
>
> StringTemplate template = new StringTemplate("$data:{" +
>
> "$if(it.IsSmart)$$it.CustomerName$$endif$}$");
>
> And have found template that add sequence number if customers number 
> is greater then one:
>
> StringTemplate template = new StringTemplate(
>
> "$if(rest(data))$$data:{$i$. $it.CustomerName$}$" +
>
> "$else$$data.CustomerName$$endif$");
>
> But I don’t know how connect both functionalities in one tempate.
>
> Regards,
>
> Gregory
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> stringtemplate-interest mailing list
> stringtemplate-interest at antlr.org
> http://www.antlr.org:8080/mailman/listinfo/stringtemplate-interest
>   


More information about the stringtemplate-interest mailing list