[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