Sylvain Wallez wrote:
Daniel Fagerstrom wrote: <snip/>
When I started working on a attribute template language (ATL) proposal, it was obvious to me that it should be attribute name driven. So why did I end up proposing a content driven one? While the attribute driven is atractive for very simple examples it IMO very soon becomes rather complicated as soon as you try to describe something slightly more complicated. E.g. if we need more than one parameter to the directive, how do we describe that? TAL uses the syntax:
<textarea rows="80" cols="20" tal:attributes="rows request/rows;cols request/cols">
The problem here is not exactly of having multiple parameters for one directive, but more multiple directives with the same name, which clashes with the fact that XML require distinct attribute names.
I chosed the example as I got the impression that TAL never uses more than one argument. So the above was the closest to having more than one argument. The main place where more than one argument i needed is for macro definiton and call, and TAL only have Phyton defined macros. Seeing the example again I realize that I was wrong it actually takes two argument: in tal:attribute="rows request/rows", "rows" is one argument and "request/rows" is another.
Somewhat OT, I also think that the "argument", and "content" directives could be removed. They are used in TAL as they don't have any embeded expressions (${<expr>}), so it is the only way of injecting data, an advantage with their approach is that you see example content instead of content with embeded "${<expr>}" in your WYSIWYG. The disadvantage is that it is much harder to write the template.
What we need that I forgot is a mechanism for selectively inserting attributes like:
<option tl:do="attribute-if(.=$current, name='selected')" selected="selected" ...>
...
that let a named attribute be part of the output if a test is true.
In our annotated-HTML-to-XSL compiler, we avoid this problem by using the following notation for attributes:
<textarea rows="80" cols="20" tal:attribute-rows="request/rows" tal:attribute-cols="request/cols">
The "tal:attribute-*" instruction allows any attribute name to be specified, while still imposing uniqueness of the names of dynamically evaluated attributes.
You instead create the problem that you can't use a scheme for checking your attributes. Sorry, I just don't like the idea about leting part of an attribute name become a parameter for the directive.
<snip/>
<tr t:forEach="cart/item">
or
<tr t:forEach="item in cart/item">
for iterators.
Here is the questions are if we want to work on a implicitly defined context as in XSLT or if we want to define a loop variable and also if we should use synatctic constructs that are close to natural language like "item in cart/item". I prefer the implictely defined context and would also prefer avoiding complicated syntactic conctructs if possible.
JXTemplate provides both approaches, depending if JXPath or Jexl is used [1]. But this is semantically similar to a java.util.Iterator() while the "varStatus" variant provides the feature of an indexed loop (i.e. "for (int i = 0; i < list.size(); i++)").
This varStatus variant is much more complicated but is sometimes invaluable to know where you are in the iteration process.
When do you need that?
Note than rather to use an approach or the other depending on the EL language used or the attribute, we could use different constructs.
Modify the context object: <tr t:foreach="cart/item">
Define an iterator: <tr t:loop="item in cart/item">
Define an indexed loop:
<tr t:indexed-loop="status in cart/item">
I don't get the difference between "loop and indexed-loop".
(hearing Stefano coming behind me, ready to shout "FS!!!" in my ears...)
His new FS detector doesn't seem fully callibrated yet, so I do some community service instead ;)
FS!!!
AFAIK the only reason to defiene a loop variable is that you don't want to affect the context. But you can just save the context in a variable instead:
<tr t:do="let(ctx=.);forEach(cart/item)">
No need to have two constructions.
Concering indexed loops, when do you need them? The idea with a template is to present model data, so in most cases you just iterate over the model data. I've used indexed loops in just a handfull of cases, and that have been in cases where I probably put a little bit to much programing logic in my view.
<snip/>
> Needing to solve the same problem as you solved with JXTG but imposing an extra
>constraint (the template must be able to show in Dreamweaver all the time) cannot
>reasonably simplify the problem can it?
Well, you presented some extreme cases. It's unlikely that a single tag will hold more that, say, two control structures (e.g. loop and if), which keeps the attributes quite readable.
The problem is not the number of directives, it is rather that you need to understand in what order the two directives is going to be applied.
So to sum up, I believe that attribute name based syntax will create more confusion than it is worth. And I'm affraid that the belief that our templates, in some magical way should lose all complexity just by changing their syntax, might be unjustified.
Well finding a consensus between diverging requirements is always difficult, and the opinion of each person regarding one or the other solution is always related to its own skills, experience and work context. People with strong dreamweaver roundtrip requirements will use the attribute syntax even if it sometimes looks awkward, whereas people more XML-centric will prefer clear structures that show up in the outline view of an XML editor.
We know that one size fits all doesn't exist.
Now going back to the annotated-HTML-to-XSL compiler that we (Anyware) wrote many years ago, it allows to mix both syntax, as attributes are simply translated to their XSLT equivalent, and you therefore can write plain XSLT in the HTML file (aargh! I hear Stefano coming!).
There are some user requirements in the (annotated) TAL reference for allowing mixed syntax in TAL just for handling the cases where the predefined attribute order doesn't work. But then you break the main reason for introducing ATL in the first place WYSIWYG friendliness, don't you. With the syntax I proposed there is no need for mixed mode, as you can express exactly the same thing with the ATL as you can with tags (except for chose/when, that needs nested tags, but thats just syntactic sugar for a sequnce of if).
Look, this is to a large part a matter on your taste and your priorities when you design the language. I personally feel rather uneasy with a language where:
<tr t:forEach="cart/item" t:let"current=.">
and
<tr t:let"current=." t:forEach="cart/item">
means the same thing, namely (if we chose the same predefined directives order as in TAL) that "$current" will refer to the surrounding context rather than to the current item. Also you can't express the second meaning without introducing a dummy tag.
Also I think that a syntax that makes the directives look like programming constructs is an advantage rather than an disadvantage. I mean they happen to be programming constructs and are the concern area of a programmer. Furthermore I believe that as the template contains two concern areas: a visual and a more programatic, it is an advantage that they have different visual "style". That makes it much easier for the designer and programmer respectively, to selectively focus precognitive attention on their concern area.
But thats just me, I might have a far to rigid view on language design by requiring language meaning to explicit. Maybe we should instead follow the Perl camp (and Humpty Dumpty) and let everything be implicit ;)
'When *I* use a word,' Humpty Dumpty said, in a rather scornful tone,' it means just what I choose it to mean, neither more nor less.'
A similar approach could be used for the template language with a single engine, by simply converting on the fly directives-as-attributes to directives-as-elements.
We can have a single engine with plugable syntax handling, but thats a implemention issue.
/Daniel