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