Mike Gerwitz
7fd1618390
This introduces support for partial applications on dynamic functions. The test cases are comprehensive and the implementation should be quite stable. Even though the base higher-order function implementation was based on the work of Dimitre Novatchev[0], I have chosen a different route for partial application: Novatchev's method relies on storing partially applied arguments as nodes, together with their types. The types are detected the best they can be, with accuracy varying wildly depending on whether a schema-aware processor is present. But regardless, that method would not retain node context. Sequences, however, do. By using sequences, we allow the processor to retain all type and context information perfectly without any additional work that is inaccurate, adds complexity, and likely to cause subtle problems. It will also support any types that we are unaware of. As Novatchev mentions: The argument type-detection that f:curry() uses has been implemented only for the builtin XML Schema datatypes. It will not recognize the user-defined type of an argument, which can be created by an user of a Schema-Aware (SA) XSLT 2.0 processor.[0] This is not a problem with hoxsl. [0]: http://conferences.idealliance.org/extreme/html/2006/Novatchev01/EML2006Novatchev01.html |
||
---|---|---|
src | ||
test | ||
tools | ||
.gitignore | ||
.gitmodules | ||
COPYING | ||
COPYING.FDL | ||
Makefile | ||
README.md |
README.md
Higher-Order XSL
hoxsl is a library for XSLT 2.0, written in pure XSLT, introducing various types of higher-order logic; this includes higher-order functions and XSLT templates that take XSLT as input and produce XSLT as output.
The system is fully tested---see the test cases for additional documentation as this project gets under way. This README will serve as an informal manual until official documentation is produced.
Higher-Order Functions
Higher-order functions are a part of XSLT 3.0, but implementations that support them (such as Saxon) hide it behind proprietary versions of their software. Others still may wish to continue using XSLT 2.0.
There are various approaches/kluges for this problem in earlier versions of XSLT; the basis of this implementation is motivated by Dimitre Novatchev's work on higher-order functions in FXSL.
For example, consider an implementation of a filter function that accepts a node set and a predicate:
<xsl:function name="my:filter" as="xs:element()*">
<xsl:param name="nodes" as="xs:element()*" />
<xsl:param name="pred" />
<xsl:for-each select="$nodes">
<xsl:if test="f:apply( $pred, . )">
<xsl:sequence select="." />
</xsl:if>
</xsl:for-each>
</xsl:function>
<xsl:function name="my:pred" as="xs:boolean">
<xsl:param name="node" as="element()" />
<xsl:sequence select="$node/@foo = 'true'" />
</xsl:function>
We could then apply a filter using this predicate like so:
<sequence select="my:filter( $nodes, my:pred() )" />
hoxsl takes this a step further by providing a stylesheet to generate
the boilerplate necessary for functions to be able to be applied using
f:apply
, as shown above. Applying tranform/apply-gen.xsl
to the
XSL stylesheet containing the above function definitions would produce
output that can be directly imported (as a stylesheet); no additional
work is needed. This can be included as part of a build process, and
the output included within a distribution.
Partial Applications
Dynamic function applications using f:apply
are partially applied if
the number of arguments provided is less than the arity of the target
function.
<!-- produces a new dynamic function of arity 5 - 3 = 2 -->
<variable name="partial"
select="f:apply( my:arity5(), 1, 2, 3 )" />
<!-- consequently, currying is supported -->
<variable name="result"
select="f:apply( f:apply( $partial, 4 ), 5 )" />
<!-- equiv = true() -->
<variable name="equiv"
select="$result
= f:apply( my:arity5(), 1, 2, 3, 4, 5 )
= my:arity5( 1, 2, 3, 4, 5 )" />
The implementation of partial function applications avoids the complexity and inaccuracies of Novatchev's approach by using only sequences, allowing arguments to retain their type and context.
License
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.