OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

tamie message

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]


Subject: Updating variables for the next loop iteration


Title: Updating variables for the next loop iteration

In application use case 2 (http://wiki.oasis-open.org/tamie/UC2-Proposal1), Jacques proposed a <nextloop> construct.  It's a more sophisticated way for updating loop variables before the next loop iteration than the <nextval> constructs that were originally proposed for loops on the wiki (http://wiki.oasis-open.org/tamie/Iterations), because it allows the reassignment statements to appear at deeper levels where they only occur when they are needed.  However, I'm not sure that it is a good idea.

In eTSM, we are using immutable variables.  This makes debugging easier, because when you see a variable used in an expression, you can find out what it contains just by scanning for its declaration, which is always in scope.  You don't have to worry about scanning all of the code between the declaration and the expression that uses it deeply to see if any of this code changed the variable.

In loops, the loop variables are declared and initialized at beginning of the loop, but they may have other values in subsequent loop iterations.  I think that in keeping with the principle that you shouldn't have to scan deeply to see what the value of a variable is, we should only allow reassignment for the next iteration at the end of the loop.

On the last telecon, I agreed to propose some alternative solutions for use case 2 that use nextval.

First, here is the original snippet from use case 2:

      <etsm:nextloop>
        <etsm:if expr="$responseStatus//@result = 'pass'">
          <etsm:loopvar name="allresptime" expr="op:add-dayTimeDurations($allresptime, $responseStatus/etsm:exit[@result = 'pass']/uc2:responsetime)" />

          <etsm:loopvar name="allpototal" expr="$allpototal + xs:double($responseStatus/etsm:exit[@result = 'pass']/uc2:poamount )"/>

          <etsm:loopvar name="allnbr" expr="$allnbr + 1" />
          <etsm:loopvar name="avgresptime" expr="op:divide-dayTimeDuration($allresptime, xs:double($allnbr))  " />
        </etsm:if>
        <etsm:if expr="$responseStatus//@result = 'fail-2'">
          <etsm:loopvar name="timeoutnbr" expr="$timeoutnbr + 1"/>
        </etsm:if>
      </etsm:nextloop>

One way to redo this would be to create an XML variable that contains the values:

      <etsm:var name="next">
        <etsm:if expr="$responseStatus//@result = 'pass'">
          <etsm:var name="nextRespTime expr="op:add-dayTimeDurations($allresptime, $responseStatus/etsm:exit[@result = 'pass']/uc2:responsetime)"/>

          <allresptime><etsm:eval expr="$nextRespTime"/></allresptime>
          <allpototal><etsm:eval expr="$allpototal + xs:double($responseStatus/etsm:exit[@result = 'pass']/uc2:poamount )"/></allpototal>

          <allnbr><etsm:eval expr="$allnbr + 1"/></allnbr>
          <avgresptime><etsm:eval expr="op:divide-dayTimeDuration($nextRespTime, $allnbr + 1)"/></avgresptime>
          <timeoutnbr><etsm:eval expr="$timeoutnbr"/></timeoutnbr>
        </etsm:if>
        <etsm:if expr="$responseStatus//@result = 'fail-2'">
          <allresptime><etsm:eval expr="$allresptime"/></allresptime>
          <allpototal><etsm:eval expr="$allpototal"/></allpototal>
          <allnbr><etsm:eval expr="$allnbr"/></allnbr>
          <avgresptime><etsm:eval expr="$avgresptime"/></avgresptime>
          <timeoutnbr><etsm:eval expr="$timeoutnbr + 1"/></timeoutnbr>
        </etsm:if>
      </etsm:nextloop>

      <etsm:nextval name="allresptime" expr="xsd:daytimeduration($next/allresptime)"/>
      <etsm:nextval name="allpototal" expr="xsd:daytimeduration($next/allpototal)"/>
      <etsm:nextval name="allnbr" expr="xsd:double($next/allnbr)"/>
      <etsm:nextval name="avgresptime" expr="xsd:int($next/avgresptime)"/>
      <etsm:nextval name="timeoutnbr" expr="xsd:int($next/timeoutnbr)"/>

Another way would be to put if blocks in the <nextval> instructions:

      <etsm:nextval name="allresptime">
          <etsm:if expr="$responseStatus//@result = 'pass'">
            <etsm:eval expr="op:add-dayTimeDurations($allresptime, $responseStatus/etsm:exit[@result = 'pass']/uc2:responsetime)"/>

          </etsm:if>
          <etsm:if expr="$responseStatus//@result = 'fail-2'">
            <etsm:eval expr="$allresptime"/>
          </etsm:if>
      </etsm:nextval>
      <etsm:nextval name="allpototal">
          <etsm:if expr="$responseStatus//@result = 'pass'">
            <etsm:eval expr="$allpototal + xs:double($responseStatus/etsm:exit[@result = 'pass']/uc2:poamount)"/>
          </etsm:if>
          <etsm:if expr="$responseStatus//@result = 'fail-2'">
            <etsm:eval expr="$allpototal"/>
          </etsm:if>
      </etsm:nextval>
      etc.

A similar approach that would be less verbose would be to use a conditional function (like the if function in excel or the iif function in visual basic):

    <etsm:var type="boolean" name="pass" select="$responseStatus//@result = 'pass'"/>
    <etsm:nextval name="allresptime" select=iif($pass, op:add-dayTimeDurations($allresptime, $responseStatus/etsm:exit[@result = 'pass']/uc2:responsetime), $allresptime)"/>

    <etsm:nextval name="allpototal" expr="iif($pass, $allpototal + xs:double($responseStatus/etsm:exit[@result = 'pass']/uc2:poamount), allpototal)"/>

    etc.

Other approaches are also possible, but I think that is enough to demonstrate that a deep option for updating variables isn't necessary.

- Chuck



[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]