[stringtemplate-interest] indexed access to lists

John Snyders jjsnyders at rcn.com
Fri Jun 1 21:13:35 PDT 2007


There was a recent discussion on this list about indexing into lists 
from a template

Nate asks:

  Would index access to lists break separation? Eg...
  $tests[0].name$

Terence answers:

  yep because it is like calling a function with an argument from the
  template, not that there aren't similar things.

Calling a function with an argument doesn't bother me much as it is 
already done when accessing
the values of a map. The key is passed as an argument and the key is not 
limited to an identifier it can
be any string.

I have some different reasons for not liking list indexing
1) the index must be a number and a template shouldn't know anything 
about numbers. To me this by itself isn't a very strong argument. I just 
have a feeling that there is no need for numbers as such in a template. 
Still the index could be a string representation of a number.
2) Indexing lists (or arrays) is really begging for the for loop and 
math. This is the main reason why I don't like the list index syntax. I 
think the  StringTemplate list iteration syntax is much nicer than  a 
for loop.  Allowing math would clearly break separation by allowing 
business logic in the template. The indexing syntax could be used to get 
a single specific values from the list but most often it is used in 
conjunction with for loop iteration.

If you just want one item out of the list have the program put it in a 
scalar attribute. If there is truly something special about a single 
element then it probably isn't in a list anyway. 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.

One solution for iterating a subset of a list is to have the program 
either copy the desired subset to a new list or wrap  the list in a new 
list that gives out an iterator that returns the subset and provides the 
length of the subset. Some reusable wrapper classes could be created. 
Example
  List sublist = (List) new SliceListWrapper(0, 5, mylist);
SliceListWrapper implements List and in this case would return 5 for 
length and the iterator would return elements 0 to 4 inclusive from mylist.

If you really really need to provide indexed access to a list then you 
could wrap it in a map. Then you can access item 5 like so $mylist.("5")$.

Another possibility would be to add a slice function to StringTemplate. 
It would return a new list with the given range.
Example
$slice(mylist, "0", "5"): { [$it$] }$
would output the first 5 items in mylist enclosed in [].
I'm thinking it would work like Python list slicing.

I think this is safer than list indexing and more in the spirit of 
trying to iterate over a subset of a list. It is safe because you are 
not calling a method on a user object but a specific string template 
function.

Functions first and last should still be kept as convenient shortcuts 
and for backward compatibility. The trunc function need not be 
implemented now because slice can do it and more.

-John
 


More information about the stringtemplate-interest mailing list