Dear BaseX team,
a question concerning the static context used by xquery:eval.
It seems to me that the static context is not inherited from the location of the evaluating call. Therefore arises the question how to call user-defined functions within code evaluated by xquery:eval. Please consider this example:
Attempt #1:
===========================================================
declare namespace f="http://www.foxpath.org/xquery-functions";
declare function f:num2($number) {2 * $number};
let $inlineFunctionText := "function($number) {f:num2($number)}"
let $f := xquery:eval($inlineFunctionText)
return $f(1)
===========================================================
Executing this, an error is raised:
[XPST0081] No namespace declared for 'f:num2'.
Adding a namespace declaration does not help:
Attempt #2:
===========================================================
declare namespace f="http://www.foxpath.org/xquery-functions";
declare function f:num2($number) {2 * $number};
let $inlineFunctionText :=
"declare namespace f='http://www.foxpath.org/xquery-functions';
function($number) {f:num2($number)}"
let $f := xquery:eval($inlineFunctionText)
return $f(1)
===========================================================
Now I get this error:
[XPST0017] Unknown function: Q{http://www.foxpath.org/xquery-functions}num2.
The only (?) way out is pass in the function a parameter:
Attempt #3:
===========================================================
declare namespace f="http://www.foxpath.org/xquery-functions";
declare function f:num2($number) {2 * $number};
let $inlineFunctionText :=
"declare namespace f='http://www.foxpath.org/xquery-functions';
declare variable $num2 external;
function($number) {$num2($number)}"
let $context := map{'num2': f:num2#1}
let $f := xquery:eval($inlineFunctionText, $context)
return $f(1)
===========================================================
Result: 2
Ok!
Fortunately, the passed in function does inherit its own static context (as it should, per spec), so that it may call other functions themselves not known to the inline function expression:
Attempt #4:
===========================================================
declare namespace f="http://www.foxpath.org/xquery-functions";
declare function f:num2($number) {2 * $number + f:num3($number)};
declare function f:num3($number) {3 * $number};
let $inlineFunctionText :=
"declare namespace f='http://www.foxpath.org/xquery-functions';
declare variable $num2 external;
function($number) {$num2($number)}"
let $context := map{'num2': f:num2#1}
let $f := xquery:eval($inlineFunctionText, $context)
return $f(1)
===========================================================
Result: 5
Okissimo!
So my question is whether it is by design or by bug that xquery:eval "forgets" the static context in place where the invocation of xquery:eval occurs.
And I emphasize the great practical relevance of the question as it impacts the possibility of using within the evaluated expression user-defined functions.
Cheers,
Hans-Jürgen