34324


XSLT 2.0はxsl:functionで２乗を求める関数を次のように書くことができます．

[code]

    <?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" xmlns:ahf="urn:ahf" exclude-result-prefixes="xs"
        version="2.0">
        <xsl:function name="ahf:powerOf2" as="xs:integer">
            <xsl:param name="prmX" as="xs:integer"/>
            <xsl:sequence select="$prmX * $prmX"/>
        </xsl:function>
        <xsl:template match="/">
            <xsl:variable name="x" as="xs:integer" select="3"/>
            <!-- ここでxの2乗を求め、xの値、結果の値をxsl:messageで表示します-->
            <xsl:message select="'x=', $x, ' xの2乗=', ahf:powerOf2($x)"/>
        </xsl:template>
    </xsl:stylesheet>
    
[/code]

これはXSLT 3.0ではインラインの無名関数を使って次のように書くことができます．

[code]

    <?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" xmlns:ahf="urn:ahf" exclude-result-prefixes="xs"
        version="3.0">
        <xsl:variable name="powerOf2" as="function(*)" select="function($x as xs:integer) as xs:integer {$x * $x}"/>
        <xsl:template match="/">
            <xsl:variable name="x" as="xs:integer" select="3"/>
            <!-- ここでxの2乗を求め、xの値、結果の値をxsl:messageで表示します-->
            <xsl:message select="'x=', $x, ' xの2乗=', $powerOf2($x)"/>
        </xsl:template>
    </xsl:stylesheet>
    
[/code]

xのy乗を求めるような次の例では再帰を使用します．

[code]

    <?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" xmlns:ahf="urn:ahf" exclude-result-prefixes="xs"
        version="2.0">
        <xsl:function name="ahf:powerOfY" as="xs:integer">
            <xsl:param name="prmX" as="xs:integer"/>
            <xsl:param name="prmY" as="xs:integer"/>
            <xsl:choose>
                <xsl:when test="0 lt $prmY -1">
                    <xsl:sequence select="$prmX * ahf:powerOfY($prmX, $prmY - 1)"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:sequence select="$prmX"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:function>
        <xsl:template match="/">
            <xsl:variable name="x" as="xs:integer" select="3"/>
            <xsl:variable name="y" as="xs:integer" select="5"/>
            <!-- ここでxのy乗を求め、xの値、yの値、結果の値をxsl:messageで表示します-->
            <xsl:message select="'x=', $x, ' y=', $y, 'xのy乗=', ahf:powerOfY($x,$y)"/>
        </xsl:template>
    </xsl:stylesheet>
    
[/code]

ではこのxのy乗を求める関数をインラインで書くにはどうしたらできるのでしょうか？無名関数なので、自分自身に再帰することはできるのでしょうか？

よろしくお願いします．


CC BY-SA 3.0
2017-04-26T15:56:39.450
34300
2017-04-27T15:05:53.267
9503
question
xpath xslt
XSLT 3.0で無名関数での再帰はどうのように記述するのでしょうか？


[Yコンビネータ](https://ja.wikipedia.org/wiki/%E4%B8%8D%E5%8B%95%E7%82%B9%E3%82%B3%E3%83%B3%E3%83%93%E3%83%8D%E3%83%BC%E3%82%BF#Y.E3.82.B3.E3.83.B3.E3.83.93.E3.83.8D.E3.83.BC.E3.82.BF)と呼ばれる高階関数（"別の関数"を引数にとる／戻り値として返す関数）を使うと、無名関数の再帰呼出のようなことができます。下記実装は厳密には"Zコンビネータ"と呼ぶそうです。

[code]

    <?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">
    <!-- (Python)
    F = lambda f: lambda a, b: 1 if b < 1 else f(a, b - 1) * a
    Y = lambda f: (lambda x: lambda a, b: f(x(x))(a, b))(lambda x: lambda a, b: f(x(x))(a, b))
    -->
        <xsl:variable name="F" as="function(*)"
            select="function($f){ function($a, $b){ if ($b) then ($f($a, $b - 1) * $a) else 1 } }"/>
        <xsl:variable name="Y" as="function(*)"
            select="function($f){ (function($x){ function($a, $b){ $f($x($x))($a, $b) } })
              (function($x){ function($a, $b){ $f($x($x))($a, $b) } }) }"/>
        <xsl:template match="/">
            <xsl:variable name="x" as="xs:integer" select="3"/>
            <xsl:variable name="y" as="xs:integer" select="5"/>
            <xsl:value-of select="'result=',$Y($F)($x, $y)"/>
        </xsl:template>
    </xsl:stylesheet>
    
[/code]

上記実装では <http://blog.livedoor.jp/kikwai/archives/51587001.html>
を参考にしました。（私自身では説明できないので、解説はリンク先に譲ります）


CC BY-SA 3.0
2017-04-27T10:04:03.977
34324
2017-04-27T15:05:53.267
2017-04-27T15:05:53.267
49
49
34300
answer