3

I am using XSLT. I know the Inline Function Expressions, Is there some way to declare a named function in xpath expression? because I need the function name to implement a recursive call.

C. M. Sperberg-McQueen
  • 24,596
  • 5
  • 38
  • 65
cmf41013
  • 107
  • 1
  • 9

2 Answers2

3

In XSLT I would simply suggest to use xsl:function as that way your function has a name and you can call it recursively inside of the function body.

As for pure XPath 3, Dimitre explored that path some years ago in https://dnovatchev.wordpress.com/2012/10/15/recursion-with-anonymous-inline-functions-in-xpath-3-0-2/ using let and higher-order functions (a feature not supported unfortunately in Saxon 9 HE), I think his code there uses a function type syntax not quite aligned with the final spec so his example would need to be

let $f := 
    function($n as xs:integer,
             $f1 as function(xs:integer, function(*)) as xs:integer) as xs:integer {
        if ($n eq 0)
        then 1
        else $n * $f1($n -1, $f1)

    },
    $F := function($n as xs:integer) as xs:integer {
        $f($n, $f)
    }
return $F(5)

which could be shortened to

let $f := 
    function($n as xs:integer,
             $f1 as function(xs:integer, function(*)) as xs:integer) as xs:integer {
        if ($n eq 0)
        then 1
        else $n * $f1($n -1, $f1)

    },
    $F := $f(?, $f)
return $F(5)

I think given the latest allowed syntax.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • @cmf41013 For a more recent example see this answer: https://stackoverflow.com/questions/58101443/xpath-recursive-parent-selection-in-a-flat-structure/58174330#58174330 – Dimitre Novatchev Dec 27 '19 at 22:56
  • Martin, the expression `$F := $f(?, $f)` is brilliant! However, this makes the definition of `F()` unreadable -- it isn't obvious for the reader what are the types of the arguments of `F()` and he must study other functions in order to understand what this types are... -- something rather time-consuming and error-prone compared to the explicit definition.Even if we devise a tool that would generate the full signature of F() this will still be time-consuming and difficult to enforce -- in other words, inconvenient. – Dimitre Novatchev Dec 28 '19 at 03:36
  • @DimitreNovatchev, I see your point, but I simply wanted to present an option the latest XPath version offers, it was not my intention to favour that way over your code I cited. In general I think, it depends on the perspective, for instance in C#, when they introduced `var` to declare variables without typing them, my initial thoughts were that I don't need it and would never use it; but nowadays I consider it quite a help when for instance using Saxon in C# and digging through its complex APIs. – Martin Honnen Dec 28 '19 at 10:18
  • @DimitreNovatchev, and the placeholder syntax in XPath can certainly reduce the code you have to write when for instance importing an XQuery module to XSLT and trying to use it. – Martin Honnen Dec 28 '19 at 10:19
  • Yes, but I am writing a function library, where each function must have a well-defined signature -- how otherwise would we be able to explain to the intended audience what type of arguments a function takes and what is their meaning? The "inner" or "worker" functions, on the other side, are intended to stay invisible -- that is, the actual implementation of a published function should be hidden. – Dimitre Novatchev Dec 28 '19 at 17:56
  • I also noticed that in a course / tutorial it is more instructive and useful to use the full type name instead of just `var`. This empasizes the names of the types and helps the reader quickly get accustomed to the new types. – Dimitre Novatchev Dec 29 '19 at 06:02
1

There is no way to declare a named function in XPath; XPath 3.1 only allows anonymous inline functions, and these cannot be recursive. I'm told that there's a way to achieve recursion in anonymous functions using a technique called Y-combinators, but it's fairly mind-boggling and I've never got my head around it. Your best approach, as Martin suggests, is to put this part of the logic at the XSLT level.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • Re: "it's fairly mind-boggling and I've never got my head around it." ... To quote @martin_honnen 's comment above: "you can do it easily, in pure XPath" :) Are you both talking about the same thing? – Dimitre Novatchev Dec 28 '19 at 01:53
  • 1
    When I have tried to understand the Y combinator, I have certainly found it mind-boggling; I find Dimitre's method quite straightforward, and have never quite understood why the one is easy to follow and the other not. (So: I *think* MK and MH are talking about the same thing, but I could be wrong.) – C. M. Sperberg-McQueen Dec 28 '19 at 02:22