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.
2 Answers
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.
6 Comments
$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.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.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.
xsl:functionyou can do it easily, in pure XPath uselet.