yohhoyの日記

技術的メモをしていきたい日記

不動点コンビネータ with XSLT 3.0

XSL Transformations(XSLT) 3.0にて関数型がファーストクラスになり、高階関数(higher-order function)がサポートされた。

W3C XSLT 3.0勧告, §1.2より該当箇所を引用:

XSLT 3.0 also delivers enhancements made to the XPath language and to the standard function library, including the following:

  • (snip)
  • Functions are now first class values, and can be passed as arguments to other (higher-order) functions, making XSLT a fully-fledged functional programming language.
  • (snip)

wikipedia:不動点コンビネータ(Z Combinator)+無名関数による階乗計算の実装:*1

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" version="3.0">
  <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
  <!-- Z = λf. (λx. f (λy. x x y)) (λx. f (λy. x x y)) -->
  <xsl:variable name="Z" as="function(*)"
    select="function($f){ (function($x){ function($y){ $f($x($x))($y) }})
              (function($x){ function($y){ $f($x($x))($y) }}) }"/>
  <xsl:variable name="fact" as="function(*)"
    select="function($f){ function($x){ if ($x) then ($f($x - 1) * $x) else 1 }}"/>
  <xsl:template match="/value">
    <xsl:value-of select="format-number($Z($fact)(.), '#')"/>
  </xsl:template>
</xsl:stylesheet>

入力XML

<?xml version="1.0" encoding="UTF-8"?>
<value>5</value>

出力テキスト:

120

関連URL

*1:XSLプログラムの動作確認は http://xslttest.appspot.com/ で行った。