plonetemplate-talzpttemplate-metal

Why is a variable defined outside a fill-slot or define-macro element not visible inside this element?


Why is a variable defined outside a fill-slot or define-macro element not visible inside this element?

<body tal:define="a string:a">
    <metal:content-core fill-slot="content-core">
        <metal:content-core define-macro="content-core"
                            tal:define="b string:b">
            <div tal:content="a" />
            <div tal:content="b" />
            <div tal:content="c" />
        </metal:content-core>
    </metal:content-core>
</body>

The tales-expression with the variable a cannot be evaluated. Of course b is visible.

On the other side, if the variable c is defined in the enclosing element of define-slot like the following then it is visible.

<div tal:define="c string:c">
    <metal:text define-slot="content-core"></metal:text>
</div>

It looks like the variables are evaluated only after the slot is inserted.


Solution

  • The context of a TAL macro is only significant if you are viewing the macro in that context. It's interpreted if you're viewing the template containing the macro, but not if you're using the macro. Macros are -- in a sense -- simply copied run time from the template containing the macro to the page using it, then expanded. All the name space comes from the template that uses the macro.

    To think of it another way: macros are not a scoped language. If they were, you wouldn't be able to see the macro at all from another template. TAL would have to be immensely more complicated, and you'd have to be thinking about closures and functions.

    "Macro" languages are called that because macros are expanded when used. They are not functions.

    So, why do containing templates include context for the macros at all? They don't have to. It's usually done so that the macro may be tested in a realistic environment. (Although sometimes macros are inside pages that are independently useful.)