Re: [#list with more than 1 variable and a complex condition, like java's for loop?

Daniel Dekany <[email protected]>
Newsgroups gmane.comp.web.freemarker.user
Message-ID <[email protected]>
Thursday, June 4, 2009, 3:46:41 PM, Newman, John W wrote:

> Yeah that's about right.  My use case is a little different -
> here's an example of what I ended up with:
>
> [#ftl]
>
> [#macro splice list1 list2]
>         [#local n = list1?size /]
>         [#local m = list2?size /]
>         [#local i = 0 /]
>         [#local j = 0 /]
>         [#local nextSortOrder = 1 /]
>         [#list 0..(n + m) as dummy]
>                 [#if i < n]
>                         [#local currentSortOrder = list1[i] /]
>                         [#if currentSortOrder == nextSortOrder]
>                                 [#nested "list1" currentSortOrder /]
>                                 [#local i = i + 1 /]
>                         [#elseif j < m]
>                                 [#local currentSortOrder = list2[j] /]
>                                 [#nested "list2" currentSortOrder /]
>                                 [#local j = j + 1 /]
>                         [/#if]  
>                         [#local nextSortOrder = nextSortOrder + 1 /]
>                 [#else]
>                         [#break /]
>                 [/#if]
>         [/#list]
>         [#list j..m - 1 as k]
>                 [#nested "list2" list2[k] /]
>         [/#list]
> [/#macro]
>
> [@splice [1, 3, 5, 7, 9, 10], [2, 4, 6, 8, 11, 12]; type, val]
>         [#if type == "list1"]
>                 First list: ${val}<br />
>         [#elseif type == "list2"]
>                 Second list: ${val}<br />
>         [/#if]
> [/@]

I'm not sure I captured well what splice meant to do, but
shouldn't it just be:

[#macro splice list1 list2]
  [#local iList1 = 0 /] 
  [#local iList2 = 0 /] 
  [#list 1..1000000 as sortOrder]
    [#if iList1 < list1?size && list1[iList1] == sortOrder]
      [#nested "list1", list1[iList1] /]
      [#local iList1 = iList1 + 1 /]
    [#else]
      [#if iList2 == list2?size]
        [#if iList1 < list1?size]
          [#stop "Not all items of 1st list were consumed when the end of the 2nd list was reached." /]
        [/#if]
        [#break /]
      [/#if]
      [#nested "list2", list2[iList2] /]
      [#local iList2 = iList2 + 1 /]
    [/#if]
  [/#list]
[/#macro]

(If it's what it meant to be, then this one can't even fail with a
cryptic val undefined error but with the [#stop ...].)

> IMO [#continue /], [#stopGracefully /], [#for], & [#while] are
> things worth looking at adding to the language.
> But we can certainly get by fine without them, it is just extra
> code. More important would be nested callbacks from a macro (this
> was discussed on this list at length a long time ago,
> http://osdir.com/ml/web.freemarker.user/2005-09/msg00018.html). That
> is what I need here to get rid of the [#if with the string compare,
> we have this in a few places and it is dirty but it works. If I
> could add one thing to FM, it would be that.

I won't pretend that I plan to implement these in FreeMarker, but for
no good reason (?) I collect the ideas/must-haves (and more) for a new
template language for a long time now, and #continue, *and* support
for labels (like [#break outermostLoop]) was definitely always there.
Means, I agree. As of [#stopGracefully /], that should be called
#stop, and #stop should be called #error, but whatever, because as of
its semantic, #stopGracefully is basically just #return. Only
FreeMarker doesn't consider the calling of a template as a method call
(I would consider it as the calling of method "main" of the template),
so it doesn't work outside macros. (Anyway, poor old FreeMarker can't
gracefully return/break/continue anything, as it forgets to close the
tags and so on.) Now, #for and #while is a tricky question... if the
template language has [#loop]..[/#loop], which means infinite loop,
then technically they are needless. But they can still result in more
readable code, however they are pretty tricky structures too, so if
you care about minimalist and strictly consistent language design, you
may vote against them. For example, [#while condition] apparently just
has a plain parameter that is expected to evaluate to a boolean, but
it's not so, because the parameter is re-evaluated for every
evaluation. And you only need to support [#loop] and [#break if=...],
and you have a very well readable alternative to it that has no
exceptional semantic whatsoever. Now, the C-like "for" statement... I
think it's seldom needed if the range operator is not bungled, which
it is in FTL; 0..-1 will not be an empty sequence in FTL, but [0, -1].
If it hadn't this problem, you could write [#list 0..maxIndex as
i]...[/#list] and like. As of "multiple bodies", yes, they are
absolutely needed IMO too, only getting them right in FTL is at best
tricky (and I'm not talking about the implementation issues). Not that
JSP cared to do it right... and it still covers lot of use-cases in
its limited form there. The most flexible implementation I have seen
so far was the one in ZipScript (but that's still different from my
design).

> Thanks
>
>
> -----Original Message-----
> From: Daniel Dekany [mailto:[email protected]] 
> Sent: Thursday, June 04, 2009 5:33 AM
> To: Newman, John W
> Cc: FreeMarker-user
> Subject: Re: [FreeMarker-user] [#list with more than 1 variable and
> a complex condition, like java's for loop?
>
> Wednesday, June 3, 2009, 11:31:34 PM, Newman, John W wrote:
>
>> Hello,
>>  
>> Is there any way to do this in FM:
>>  
>>  
>>             for (int i = 0, j = 0; i < n || j < m;) {
>> }
>>  
>> Normally I never do things like that, but it works out great here. 
>> And I have to render almost the same thing in FM as what I've done
>> in java using that loop.  I can't seem to get anywhere with [#list
>> and [#break .. any help is appreciated!  Thanks
>
> [#assign i = 0]
> [#assign j = 0]
> [#list 0..1000000 as ignore]
>   [#if !(i < n || j < m)]
>     [#break]
>   [/#if]
>   ...
> [/#list]
>

-- 
Best regards,
 Daniel Dekany


------------------------------------------------------------------------------
OpenSolaris 2009.06 is a cutting edge operating system for enterprises 
looking to deploy the next generation of Solaris that includes the latest 
innovations from Sun and the OpenSource community. Download a copy and 
enjoy capabilities such as Networking, Storage and Virtualization. 
Go to: http://p.sf.net/sfu/opensolaris-get
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.