Re: "While"-like structure in Velocity?

Sergiu Dumitriu <[email protected]>
Newsgroups gmane.comp.jakarta.velocity.user
Message-ID <[email protected]>
On 05/16/2013 11:23 AM, Christopher Schultz wrote:
> Sergiu,
> 
> On 5/15/13 3:04 PM, Sergiu Dumitriu wrote:
>> On 05/15/2013 12:11 PM, Christopher Schultz wrote:
>>> All,
>>>
>>> I've searched the archives for "while" capabilities in Velocity, and
>>> mostly the answers have been things like "that's beyond the scope of
>>> Velocity... you want a real programming language for that".
>>>
>>> I'd like to do something that naturally would use a while loop, but
>>> perhaps someone can offer an alternative suggestion.
>>>
>>> I need to traverse a queue, but that queue needs to be able to modify
>>> itself during the processing. Basically, something like this:
>>>
>>> while (!queue.empty) {
>>>   // do something with the head element
>>>   // possible enqueue some more items at the back
>>> }
>>>
>>> #foreach would be the way to do it if the queue didn't have to be
>>> modified, but I'll get an exception if I try to traverse an iterator
>>> over the queue and then modify it mid-flight.
>>>
>>> Right now, I have this written as a JSP but I'd rather have it as a
>>> Velocity template.
>>>
>>> My only thought is to create an ugly class that implements Iterator and
>>> wraps the queue but is much less strict than a standard iterator. Any
>>> suggestions?
>>>
>>> -chris
>>>
>>
>> While not a very clean solution, you can use a very large foreach and
>> manually work with the queue inside the loop, and #break($foreach) once
>> the queue is empty:
>>
>> #foreach($i in [0..100000])
>>   #if ($queue.isEmpty())
>>     #break($foreach)
>>   #end
>>   #set ($item = $queue.pop())
>>   ## Do stuff with $item
>>   #if (should add more things)
>>     #set ($discard = $queue.add(new things))
>>   #end
>> #end
> 
> That's actually a great suggestion. I've never used "break" in a foreach
> loop before. $foreach becomes the loop-control identifier for #break?

$foreach is an automatically defined scope variable, it is more than
just a target for #break.

http://velocity.apache.org/engine/devel/velocity-engine-core/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html

http://velocity.apache.org/engine/releases/velocity-1.7/user-guide.html#Break
has more information about the optional scope you can pass to #break.
Actually it's not needed to pass $foreach to it if it is the innermost
scope, but it is useful for example if you want to break out of nested
scopes, like:

#break($foreach.parent)
#break($foreach.topmost)

> I'll give that a try. 10,000 seems completely reasonable given that (for
> now) I'll never really have a queue that grows to a size more than about
> 5000, even in the most pathological case.

-- 
Sergiu Dumitriu
http://purl.org/net/sergiu
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.