How to prevent propagation of arguments in recursive calls?

Poster Content
nk4um Moderator
Posts: 485
May 20, 2010 11:07Fixed
Ok, I''ve got a solution. It was an interesting corner case, one that the implementation didn''t consider. Now arguments can only be resolved in the script that they were passed too. We''ll post a fix for this on the repository tomorrow.

Thank you for finding this and your patience for a fix.

Cheers, Tony
nk4um Moderator
Posts: 485
May 19, 2010 21:22
Yes, sorry for not being clear. I''ll get back to you soon. I''m tending to think that we need to limit the scope of resolution for the arguments. Reading up about clojures:

http://en.wikipedia.org/wiki/Closure_%28computer_science%29

I think that scope for the arguments should be limited to the lexical scope, i.e. within the same script.

Tony
nk4um User
Posts: 111
May 19, 2010 21:14
Let me think about them and get back to you.


Oh, you mean none of these solutions are possible right now? Sorry about the previous message then! I felt like a newbie in need of more explanations... :)

Gregoire
nk4um User
Posts: 111
May 19, 2010 15:48
Hi Tony!

1) set a <null> value for the argument and test for that rather than existence


Yes it would solve the problem. But how do you define a default value for the arguments, in "module.xml"? And on the DPML side, how do you test for a given value?

Thank you,
Gregoire
nk4um Moderator
Posts: 485
May 19, 2010 14:25
Thank you for the visualizer trace. I understand that you are recursively calling the DPML script from inside xquery. The problem is as I suspected: that the arguments passed to the outer DPML are being resolved inside the inner. This is because they are being aliased with same underlying identifier and so both inner and outer are looking for the same resource and it is in scope from the inner script too.

This situation was anticipated but not considered a problem - until now. We thought that it was useful to have these outer "variables" available. But the problem is there is no way to hide them. There are a number of solutions to this. These include:

1) set a <null> value for the argument and test for that rather than existence
2) change the resolution for arguments in DPML to that they can only be resolved inside the script in which they were defined.

Let me think about them and get back to you.

Cheers, Tony
nk4um Moderator
Posts: 485
May 18, 2010 20:32
Hi gregoire, I think I see what you are doing but I''m not quite following how
the recursion is happening. Can you email me a visualizer trace (tab at 1060research.com) and I''ll take a look and get back to you. DPML does
use more a closure style approach rather than functions, i.e. whatever is in the scope can be found including arguments but it looks like you are leaving DPML and going into XQuery?

Send me the visualiser trace and I should understand then.

Cheers, Tony
nk4um User
Posts: 111
May 18, 2010 19:57How to prevent propagation of arguments in recursive calls?
Hi,

I''ve set up a webservice with all the towns of France, which can be used to display all towns whose names begin with a given set of letters.

To benefit from NetKernel''s ability to cache resources, I made this webservice recursive. So when you call it with the letters "Carca", it calls itself with the parameter "Carc", and so on, until the parameter is only 3 characters long ("Car"). Then the webservice reads the data and returns the list. The idea is that if the user is typing a town name, it will first type "Car", then "Carc", then "Carca", and the new result is always a subset of the previous one. So using recursivity ensures that the more characters are typed, the fastest the result is displayed. This initial version of the algorithm works very good.

However with the letters "Saint", the magic stops because there are around 3000 towns and villages whose names begin like this. That''s too much data for a simple autocompletion mechanism. So my idea is to keep the original recursive webservice, but to send its output to a simple XSLT script which would strip everything but a given number of towns.

In order to do this, I modified my module.xml so that I could use two optional arguments "indiceMin" and "indiceMax". The initial call would be:

res:/services/towns/Marsei/1-10


Then all the recursive calls would not use the optional /1-10 parameter. They would be:
res:/services/towns/Marse

then
res:/services/towns/Mars

then
res:/services/towns/Mar


So the algorithm should be very simple:

if (the "1-10" parameter exists) then
        (call WS)
        (cut the returned list)
      else
        (call WS)


I wrote this DPML script to do this job:

<sequence>
  <if assignment="response">
    <cond>
      <request>
        <identifier>arg:indiceMin</identifier>
        <verb>EXISTS</verb>
      </request>
    </cond>
    <then>
      <sequence>
        <request assignment="towns">
          <identifier>active:xquery</identifier>
          <argument name="operator">res:/resources/scripts/towns.xql</argument>
          <argument name="lieu">arg:townName</argument>
        </request>
        <request assignment="response">
          <identifier>active:xslt</identifier>
          <argument name="operator">res:/resources/scripts/cut.xsl</argument>
          <argument name="operand">this:towns</argument>
          <argument name="indiceMin">arg:indiceMin</argument>
          <argument name="indiceMax">arg:indiceMax</argument>
        </request>
      </sequence>
    </then>
    <else>
      <request>
        <identifier>active:xquery</identifier>
        <argument name="operator">res:/resources/scripts/towns.xql</argument>
        <argument name="townName">arg:townName</argument>
      </request>
    </else>
  </if>
</sequence>


As you can see, the decision to call the "cut.xsl" script is based upon the existence of the "arg:indiceMin" parameter.

The problem is : the recursive calls (which don''t use the optional parameter "/<indiceMin>-<indiceMax>"), still sees the "arg:indiceMin" defined by the first call (the one with the parameter "/1-10"). So the returned list is truncated after each recursion. This is obviously very wrong and completely breaks the recursive algorithm.

The question is: is it possible to say that the "arg:indiceMin" argument should be "local" (viewable only by the current call) and not "global" (viewable by all the subsequent calls)? So that only the initial call comes in the "then" block and all the recursive calls go through the "else".

Thanks for your help,
Gregoire
[/xml]