You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Daniel Fagerstrom <da...@nada.kth.se> on 2005/01/23 16:42:51 UTC

Variable Asignment in JXTG (was: xml languages)

Leszek Gawron wrote:
> Daniel Fagerstrom wrote: 
>> BURGHARD Éric wrote:
<snip/>
>>> Variable nature and scope (kind of non-mutable that you can overwrite 
>>> ?),
>>> but someone could tell me this a feature :-). Perhaps i've miss 
>>> something,
>>> but look what i need to do to retrieve a value incremented inside a 
>>> forEach
>>> loop:
>>>
>>> <jx:set var="globalvars" value="${java.util.HashMap(5)}"/>
>>> <jx:set var="dummy" value="${globalvars.put('a_count', 0)}"/>
>>> ...
>>> <jx:set var="a_count" value="${globalvars.a_count}"/>
>>> <jx:forEach begin="1" end="3" varStatus="i">
>>>    ...
>>>    <jx:if test="#{$node/@path != ''}">
>>>       ...
>>>       <jx:set var="a_count" value="${a_count+1}"/>
>>>       <jx:set var="dummy" value="${globalvars.put('a_count', 
>>> a_count)}"/>
>>>   </jx:if>
>>> </jx:forEach>
>>>
>>> <jx:out>this is my count: ${globalvars.a_count}</jx:out>
>>>
>>> It would be easiest (and efficient) to do
>>> <jx:set var="a_count" value="0"/>
>>> <jx:forEach begin="1" end="3" varStatus="i">
>>>    ...
>>>    <jx:if test="#{$node/@path != ''}">
>>>       ...
>>>       <jx:set var="a_count" value="${a_count+1}"/>
>>> </jx:forEach>
>>>
>>> <jx:out>this is my count: ${a_count}</jx:out>
>>>
>>> the fact that "set" make always a "new define" is quite annoying at 
>>> first
>>> glance (functional programming ?).
>>
>> The expression context is implemented as a stack of maps and the put 
>> instruction on the context is a put on the top map. ForEach is 
>> implemented in such way that the loop is performed in a local map that 
>> is pushed on stack before the loop and poped afterwards. The set 
>> instruction will do a put on the top map and will disapear afterwards 
>> because of that.
>>
>> Ok, that explains the behaviour, the question is what we should do 
>> about the, admitingly, weird behaviour.
>>
>> One possibilty would be to decide that we want JXTG to be more like a 
>> functional language. In that case we should deprecate jx:set and 
>> introduce a jx:let instead that just gives a local name for an 
>> expression and that gives an exception if you try to set the 
>> "variable" to a new value. I think I would prefer this behaviour as I 
>> would prefer having a template language without side effects.
> 
> This proposal does not solve the use case provided.

Could possibly be done with:

<jx:forEach items="#{$node[@path]}">
...

But it wasn't clear to me what the use case does.

> I also had several 
> cases where I wanted the numbering to be consistent across several 
> forEach calls and also had to implement hacks.

Can possibly be done by adding count($node[@path]) to the counter.

I'm certain that you can find cases that not are solved with this. The 
question is how much of a programming language we want our template 
language to be, and my opinion is that we should contain as little 
"programming" constructs as possible while still being usable as a view. 
We must of course discuss where we should draw the line. But I would go 
for less. WDOT?

>> Another possibility is to let set asign the value to the first 
>> variable binding with the same name that it finds when the stack is 
>> searched, instead of creating a new binding at the top of the stack if 
>> the name doesn't exist on the top of the stack. If we go for this we 
>> need two constructions one that declare and possibly gives an intial 
>> value to a variable in the current context and one that binds the 
>> uppermost occurance of the name, a jx:declare and a jx:set e.g.
>>
>> Also we would need to change the API and behaviour of 
>> ExpressionContext so that we both have a declare and a set method. 
>> This should probably be done anyway.
>>
>> WDYT?
>>
>> /Daniel
>>
> I prefer the second solution. The only thing to make the use case work 
> is the ability to set the variable without implicit declaration.
> 
> One more question: should jx:set automatically declare if there is no 
> previous declaration? I think yes.
> 
> When we reach an agreement I can implement it as it looks quite 
> straightforward.

Thinking a little bit more about it, we can't change the current 
behavoiur of jx:set in the indicated dirresction, it will break peoples 
templates and we don't want that.

I suggest that (given that we decide to go the "assignment" way, that we 
introduce two new constructions: jx:define (or declare, let, variable 
etc) and jx:assign. jx:define introduces a new variable in the current 
context and give it an initial value, it is an error to use jx:define 
for the same variable two times in the same context. jx:asign assigns 
the value of a previous declared variable and it is an error to assign 
an undefined variable. I prefer to not have any implicit declaration of 
undefined variable from jx:assign.

 From an implementation POV the ExpressionContext must be extended with 
new methods for assignment and declaration of variables as the put 
instruction supports the current jx:set behaviour.

/Daniel

Re: Variable Asignment in JXTG (was: xml languages)

Posted by BURGHARD Éric <er...@systheo.com>.
Daniel Fagerstrom wrote:

> <jx:forEach items="#{$node[@path]}">
> ...
> 
> But it wasn't clear to me what the use case does.
> 
>> I also had several
>> cases where I wanted the numbering to be consistent across several
>> forEach calls and also had to implement hacks.
>

Couldn't say better :-). That's a good abstract of what this hack is
supposed to do.

> Can possibly be done by adding count($node[@path]) to the counter.
>

I cut off too many as well as too few lines from my "real" use case :-)
sorry. But no i can't do that. ;-(

> I'm certain that you can find cases that not are solved with this. The
> question is how much of a programming language we want our template
> language to be, and my opinion is that we should contain as little
> "programming" constructs as possible while still being usable as a view.
> We must of course discuss where we should draw the line. But I would go
> for less. WDOT?
>

I think that jx:template is already a full featured programming language
(turing's machine). Anyway, what we can't do natively, we can do it with
hacks. For me everything that could potentialy minimizing the need of such
hacks is good for the "language".

>>> Another possibility is to let set asign the value to the first
>>> variable binding with the same name that it finds when the stack is
>>> searched, instead of creating a new binding at the top of the stack if
>>> the name doesn't exist on the top of the stack. If we go for this we
>>> need two constructions one that declare and possibly gives an intial
>>> value to a variable in the current context and one that binds the
>>> uppermost occurance of the name, a jx:declare and a jx:set e.g.
>>>
>>> Also we would need to change the API and behaviour of
>>> ExpressionContext so that we both have a declare and a set method.
>>> This should probably be done anyway.
>>>
>>> WDYT?
>>>
>>> /Daniel
>>>
>> I prefer the second solution. The only thing to make the use case work
>> is the ability to set the variable without implicit declaration.
>>

+1. because i don't feel like facing a functionnal programming language when
i look to jxtemplate, and adding such a declaration could be confusing for
the hardcore ones.

>> One more question: should jx:set automatically declare if there is no
>> previous declaration? I think yes.
>> 
>> When we reach an agreement I can implement it as it looks quite
>> straightforward.
> 
> Thinking a little bit more about it, we can't change the current
> behavoiur of jx:set in the indicated dirresction, it will break peoples
> templates and we don't want that.
>

True ! I see 2 solutions:
- adding an 1.0 compatibility argument to jxtg 2.0
- add the new construction and deprecate jx:set 

> I suggest that (given that we decide to go the "assignment" way, that we
> introduce two new constructions: jx:define (or declare, let, variable
> etc) and jx:assign. jx:define introduces a new variable in the current
> context and give it an initial value, it is an error to use jx:define
> for the same variable two times in the same context. jx:asign assigns
> the value of a previous declared variable and it is an error to assign
> an undefined variable. I prefer to not have any implicit declaration of
> undefined variable from jx:assign.
> 
>  From an implementation POV the ExpressionContext must be extended with
> new methods for assignment and declaration of variables as the put
> instruction supports the current jx:set behaviour.
>

Great (Y).

> /Daniel