[stringtemplate-interest] Understanding template recursion
John Snyders
jjsnyders at rcn.com
Wed May 23 20:13:15 PDT 2007
Hi Trevor,
recurse(x) ::= "<x><rest(x):recurse()>"
In this case on the first call x is the whole list so "abcd" is output.
then it loops over the rest of x calling recurse with the x being the
current item it. It is the same as recurse(x=it).
When I try this I get "abcdbcd"
For me this is behaving as you and I would expect. I don't know why it
doesn't work for you. We may have different versions of ST.
recurse2(x) ::= "<x><recurse2(rest(x))>"
I think what might be happening here is infinite recursion. The typical
pattern for recursion is to have a test for the case that is going to
stop the recursion. You might intend something like this (I just happen
to use $$ rather than <>)
recurse2(x) ::= "$x$ $if(x)$$recurse2(rest(x))$$endif$"
Sadly this does not do what I expect. The first time it should output
"abcd" because x is items. Now it calls recurse2 with the rest of x
which is [ b, c, d ] and that is what should be output next "bcd" Now it
recurses again with [ c, d ] and should output "cd" and again resulting
in "d" at which point rest is null and the if would be false. So the
total output I expect is "abcd bcd cd d "
What I get is "abcd bcd "
The reason I believe has to do with how ST uses iterators. On the first
recursive call to recurse2(rest(x)) rest(x) returns an iterator and not
a new list that is a slice of the old list. Now on the recursive call x
is an iterator and as soon as you use it once it is used up. The next
recursive call rest(x) returns null because x was used up in $x$.
This is a very serious bug and I thought I had reported it before in
some way but now I can't find it in the archives.
A very simple way to see this bug is with the following
useItTwice(x) ::= <<
once : $x;separator=", "$
twice: $x;separator=", "$
>>
test() ::= <<
$useItTwice(items)$
$useItTwice(rest(items))$
>>
With your definition of items calling
$useItTwice(items)$
$useItTwice(rest(items))$
it should print
once : a, b, c, d
twice: a, b, c, d
once : b, c, d
twice: b, c, d
but it prints
once : a, b, c, d
twice: a, b, c, d
once : b, c, d
twice:
Iterators should never be passed to templates. This bug will prevent you
from doing anything interesting with recursive templates.
P.S. I went to umass Amherst back in the 80's.
-John
Trevor Strohman wrote:
> I'm having trouble understanding recursion in templates.
>
> Suppose I have a list called "items" that contains Strings: "a", "b",
> "c", "d", and these two templates:
> recurse(x) ::= "<x><rest(x):recurse()>"
> recurse2(x) ::= "<x><recurse2(rest(x))>"
>
> I expect <recurse(items)> to become:
> abcdcdd
> and <recurse2(items)> to become:
> abcd
>
> However, <recurse(items)> becomes "abcd" and <recurse2(items)> throws
> an Exception. What am I misunderstanding?
>
> Also, I notice that functions first, last and rest don't seem to be
> first-class citizens in the language. These expressions throw
> exceptions:
> <if(first(rest(items))>
> <first(items).isEnabled>
> This has been a problem for me this afternoon. I feel like I must be
> misunderstanding the right way to approach recursive template
> invocation.
>
> Trevor
>
> _______________________________________________
> 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