Re: Unexpected variable scoping rules if #include is used within a #macro

Daniel Dekany <[email protected]>
Newsgroups gmane.comp.web.freemarker.user
Message-ID <[email protected]>
Friday, May 1, 2009, 10:46:33 PM, Newman, John W wrote:
> Hello,
>  
> We are using FM 2.3, and we’ve spotted a strange bug with our code.
> I’ve been wading through the docs for a bit here but haven’t found
> the answer as to why this is happening.  Perhaps a simple test is the best way to explain it:
>  
> Main template:
> [#ftl]
> [#import "scopeTest.ftl" as test /]
> [@test.runTest /]
>  
> scopeTest.ftl:
> [#ftl]
> [#macro runTest]
>       [#list 1..30 as i]
>             [#include "strangeScope.ftl" /]
>       [/#list]
> [/#macro]
>  
> strangeScope.ftl:
> [#ftl]
> [#if i % 10 == 0]
>       [#assign someLocal = i + 2 /]
> [/#if]
> ${i} ${someLocal!'not defined'}<br />
>  
> Produces this output:
>  
> 1 not defined
> 2 not defined
> 3 not defined
> 4 not defined
> 5 not defined
> 6 not defined
> 7 not defined
> 8 not defined
> 9 not defined
> 10 12
> 11 12  < What?
> 12 12  < Why is this still here
> 13 12  < shouldn’t it say not defined, since, once the include
> reaches EOF the someLocal is out of scope and destroyed?
> 14 12
> 15 12
> 16 12
> 17 12
> 18 12
> 19 12
> 20 22 < correct
> 21 22 < this should say undefined??
> 22 22
> 23 22
> 24 22
> 25 22
> 26 22
> 27 22
> 28 22
> 29 22
> 30 32
>  
> Is this expected behavior?

Yes... frankly, I don't quite get what's odd about it.

> Why does a variable that is not declared in a macro remain in scope
> for the entire macro?

[#include ] has copy-paste-like semantic regarding variable scoping.
It's a bit like #include in C, you see. Also, #assign creates the
variable on the top-level, which is yet another reason it won't go out
of scope. BTW, the variable scoping rules are described here:
http://freemarker.org/docs/dgui_misc_var.html

> [#local sounds like what I want but that is not permitted in the
> include.

That indeed won't work there since the included file is parsed without
assuming that it will be used inside a macro (and that indeed can't be
find that out), and #local works only inside #macro or #function. But
even if #local worked there the output would be the same, as the
#local variable is created in the scope of the nearest enclosing
#macro/#function.

> If the someLocal var was declared within the macro itself this is
> what I would expect, however in this case, I’m expecting it to be
> declared, destroyed, re-declared within the include.  The macro
> shouldn’t even know it is there.  Right?

Well, #assign creates kind of global variables. Well, it's not
absolutely global (that's why we also have #global) if you look into
the topic of #import-s... but it doesn't mater now. What you have
expected is maybe rather like #var in FreeMarker 2.4
(http://freemarker.org/docs-24pre1/dgui_misc_var.html), which is not
released yet (and it won't be in the foreseeable future).

> Is this a bug or a feature? If it’s the latter, please explain the
> reasoning here and what the best practice is if any.

Code snippets that meant to be black-boxes are usually implemented as
macros. They can also have parameters and nested content, which is a
huge advantage over includes.

> Is it more correct to ditch the include, convert it to a second
> macro and use local?

I guess... without seeing the concrete application of course.

> I’m a bit confused on this and concerned that we could have several
> other instances of include within macro…

I don't think the behavior of #include is surprising regarding
variables, as this how "include" works in most languages that has it.
Also the documentation
(http://freemarker.org/docs/ref_directive_include.html) says: "The
included file shares the variables with the including template,
similarly like if it was copy-pased into it."

> Thanks as always.  

-- 
Best regards,
 Daniel Dekany


------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations 
Conference from O'Reilly Media. Velocity features a full day of 
expert-led, hands-on workshops and two days of sessions from industry 
leaders in dedicated Performance & Operations tracks. Use code vel09scf 
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
FreeMarker-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freemarker-user
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.