Another ('nother) parameters proposal

What's wrong with the status quo?

1. Having every step inherit every in-scope parameter is too coarse.
   It requires the least syntax (i.e., nearly none) but invites users
   to pass parameters that they didn't intend to steps that may change
   behavior on that basis.

2. The inability to group parameters means it's very difficult to
   select which parameters go to which steps. Using QNames avoids name
   collisions, but using the namespace name as a grouping mechanism
   interferes with steps that can accept parameters with arbitrary
   QNames

3. It's not possible to compute parameters dynamically.

Personally, I consider solving problems 1 and 2 critical. Solving 3
would be nice, but I could live without it in V1.

What's "the simplest thing that could possibly work?"

1. No more automatic inheritance. That was easy :-) It no longer makes
   any sense to allow p:parameter on compound steps.

2. Add a grouping mechanism. What do parameter groups remind me of?
   XSLT attribute sets:

   <p:parameter-set
     name = NCName>
    (p:parameter*)
   </p:parameter-set>

   For V1, I propose that p:parameter-set be allowed only as a child
   of p:pipeline.

   Having sets isn't very useful if you can't use them, so we also
   need @use-parameter-sets on steps. (For steps not in the pipeline
   namespace, that's spelled @p:use-parameter-sets.)

   The ability to group parameters gives the pipeline author control
   over all the parameters *except* those that are passed to the
   pipeline (either by the application, e.g., from the command line
   or by the invocation of the pipeline from some other pipeline).

   There are a few ways we could address this, the simplest that
   occurs to me is to allow "#default" as a parameter set name. It
   means "all the parameters passed to the p:pipeline", which might be
   the empty set.

   Now I suppose a user might want to merge parameter-sets, just like
   they can merge attribute-sets, so perhaps we could allow
   @use-parameter-sets on p:parameter-set. If we do, then I think
   the priority (for determining what to do with name collisions) should
   be that the *used sets* have higher priority. That's possibly
   counter-intuitive, but it means that in:

   <p:parameter-set use-parameter-sets="#default">
     <p:parameter name="output-method" value="html"/>
   </p:parameter-set>

   The output-method parameter passed to the pipeline, if there was
   one, gets priority over the local one. Otherwise, merging with
   #default isn't very useful.

   If several names are listed in @use-parameter-sets, then they're
   merged in the order given with the last definition having
   priority. In a step, local, explicit p:parameter elements take
   priority.

3. We could allow (p:empty|p:inline|p:pipe|p:document)* as a child of
   p:parameter-set. It would be an error if any documents read inside
   a p:parameter-set were not empty and not c:parameters containing
   c:parameter elements.

   If we do this, we also need to make it a dynamic error if a p:pipe
   points to a step that (directly or indirectly) uses the parameter
   set being defined. But that's no harder than the existing
   circularity detection that implementations already have to do.

What does this mean?

Consider the simplest case:

  <p:pipeline>
    ...
    <p:xslt>
      <p:input port="source">...</p:input>
      <p:input port="stylesheet">...</p:input>
    </p:xslt>
  </p:pipeline>

Today, any parameters passed to the pipeline are automatically
available to the XSLT step. To obtain that behavior under this
proposal, the pipeline would have to be changed as follows:

  <p:pipeline>
    ...
    <p:xslt use-parameter-sets="#default">
      <p:input port="source">...</p:input>
      <p:input port="stylesheet">...</p:input>
    </p:xslt>
  </p:pipeline>

If there were any legacy pipelines, and those legacy pipelines relied
on parameters set on p:group elements scoping the parameters used inside
the group, they'd have to be changed from:

  <p:pipeline>
    ...
    <p:group>
      <p:option name="baz" select="concat($moo,'-1')"/>
      <p:parameter name="foo" value="bar"/>

      <p:xslt>
        <p:input port="source">...</p:input>
        <p:input port="stylesheet">...</p:input>
        <p:parameter name="base-name" select="$baz"/>
      </p:xslt>
      <px:something-else/>
    </p:group>
  </p:pipeline>

to something like this:

  <p:pipeline>
    <p:parameter-set name="group1" use-parameter-sets="#default">
      <p:parameter name="foo" value="bar"/>
    </p:parameter-set>
    ...
    <p:group>
      <p:option name="baz" select="concat($moo,'-1')"/>

      <p:xslt use-parameter-sets="group1">
        <p:input port="source">...</p:input>
        <p:input port="stylesheet">...</p:input>
        <p:parameter name="base-name" select="$baz"/>
      </p:xslt>
      <px:something-else p:use-parameter-sets="group1"/>
    </p:group>
  </p:pipeline>

If we allow parameter sets to be computed, then we can also say:

  <p:pipeline>
    <p:parameter-set name="global">
      <p:pipe port="load-global" step="result"/>
    </p:parameter-set>

    <p:try name="load-global">
      <p:group>
        <p:output port="result"/>
        <p:load>
          <p:option name="href" value="~/.globals.xml"/>
        </p:load>
      </p:group>
      <p:catch>
        <p:output port="result"/>
        <p:identity>
          <p:input port="source">
            <p:inline>
              <c:parameters/>
            </p:inline>
          </p:input>
        </p:identity>
      </p:catch>
    </p:try>

    <p:xslt use-parameter-sets="global #default">
      ...
    </p:xslt>
  </p:pipeline>

It seems to me that with this proposal, the semantics of parameter
passing are much more explicit (and much less risky) and the syntactic
overhead is low.

                                        Be seeing you,
                                          norm

-- 
Norman Walsh <ndw@nwalsh.com> | A wonder is often expressed that the
http://nwalsh.com/            | greatest criminals look like other men.
                              | The reason is that *they are like other
                              | men in many respects.*-- Hazlitt

Received on Friday, 25 May 2007 09:50:55 UTC