Error with function-lookup and static variable
Friday, 9 August 2024 · 15 messages · last reply 21 Sep 2024
AG
Amanda Galtman9 Aug 2024 17:51 #
Hi, all.
I'm seeing an error in BaseX when I use function-lookup in both a global variable and a function, where the function relies on the variable. I reduced the situation to the following small query:
xquery version "3.1";
declare variable $local:lookup := function-lookup(QName("nonexistent", "nonexistent"), 1);
declare function local:myfcn() {
let $f := ($local:lookup, function-lookup(QName('http://www.w3.org/2005/xpath-functions','string'), 1))[1]
return $f('a')
};
local:myfcn()When I run it with BaseX 11.1, I get
[XQDY0054] Static variable depends on itself: $local:lookup
When I run it with Saxon-HE 12, I don't get this error.
Is there anything I can do in my code to avoid this error?
Thanks,
Amanda
CG
Christian Grün12 Aug 2024 10:43 #
Hi Amanda,
It is high time to tackle an existing GitHub issue that most likely relates to the same bug [1].
Thanks for your observation,
Christian
[1] https://github.com/BaseXdb/basex/issues/1095
Quoted text · Amanda Galtman · 27 lines
On Fri, Aug 9, 2024 at 5:51 PM Amanda Galtman <galtmana at proton.me> wrote: > Hi, all. > > I'm seeing an error in BaseX when I use function-lookup in both a global > variable and a function, where the function relies on the variable. I > reduced the situation to the following small query: > > xquery version "3.1"; > declare variable $local:lookup := function-lookup(QName("nonexistent", > "nonexistent"), 1); > declare function local:myfcn() { > let $f := ($local:lookup, function-lookup(QName(' > http://www.w3.org/2005/xpath-functions','string'), 1))[1] > return $f('a') > }; > local:myfcn() > > When I run it with BaseX 11.1, I get > [XQDY0054] Static variable depends on itself: $local:lookup > > When I run it with Saxon-HE 12, I don't get this error. > > Is there anything I can do in my code to avoid this error? > > Thanks, > Amanda >
CG
I managed to fix a part of the dependency problem. Your query should now be executable with the latest snapshot [1].
– Christian
[1] https://files.basex.org/releases/latest/
Quoted text · Amanda Galtman · 27 lines
On Fri, Aug 9, 2024 at 5:51 PM Amanda Galtman <galtmana at proton.me> wrote: > Hi, all. > > I'm seeing an error in BaseX when I use function-lookup in both a global > variable and a function, where the function relies on the variable. I > reduced the situation to the following small query: > > xquery version "3.1"; > declare variable $local:lookup := function-lookup(QName("nonexistent", > "nonexistent"), 1); > declare function local:myfcn() { > let $f := ($local:lookup, function-lookup(QName(' > http://www.w3.org/2005/xpath-functions','string'), 1))[1] > return $f('a') > }; > local:myfcn() > > When I run it with BaseX 11.1, I get > [XQDY0054] Static variable depends on itself: $local:lookup > > When I run it with Saxon-HE 12, I don't get this error. > > Is there anything I can do in my code to avoid this error? > > Thanks, > Amanda >
AG
Thanks, Christian.
By the way, I found a workaround for my immediate need: putting all the function-lookup usage in module functions instead of a global variable.
Regards,
Amanda
Quoted text · Christian Grün · 33 lines
On Monday, August 12th, 2024 at 4:43 AM, Christian Grün <christian.gruen at gmail.com> wrote: > Hi Amanda, > > It is high time to tackle an existing GitHub issue that most likely relates to the same bug [1]. > > Thanks for your observation, > Christian > > [1] https://github.com/BaseXdb/basex/issues/1095 > > On Fri, Aug 9, 2024 at 5:51 PM Amanda Galtman <galtmana at proton.me> wrote: > >> Hi, all. >> >> I'm seeing an error in BaseX when I use function-lookup in both a global variable and a function, where the function relies on the variable. I reduced the situation to the following small query: >> >> xquery version "3.1"; >> declare variable $local:lookup := function-lookup(QName("nonexistent", "nonexistent"), 1); >> declare function local:myfcn() { >> let $f := ($local:lookup, function-lookup(QName('http://www.w3.org/2005/xpath-functions','string'), 1))[1] >> return $f('a') >> }; >> local:myfcn() >> >> When I run it with BaseX 11.1, I get >> [XQDY0054] Static variable depends on itself: $local:lookup >> >> When I run it with Saxon-HE 12, I don't get this error. >> >> Is there anything I can do in my code to avoid this error? >> >> Thanks, >> Amanda
AG
Christian, thanks very much.
I returned to my actual code, and it works with the latest snapshot dated today.
By the way, I also retried the variations I had created when trying to explore workarounds, and one of them still doesn't work with the latest snapshot. It's not blocking me, but in case it is helpful, I reduced it to another small query that reproduces the error with today's snapshot. I know you said you fixed part of the problem, so you might not be surprised that the following code still triggers the error.
xquery version "3.1";
declare variable $variant :=
if (exists(function-lookup(QName('nonexistent','nonexistent'), 0)))
then
( (: not relevant :) )
else
function-lookup(QName('http://www.w3.org/2005/xpath-functions','string'), 1);
declare variable $variant-fcns := $variant;
declare function local:fcn() {
$variant-fcns('abc')
};
local:fcn()The levels of indirection (variable, variable, function, function call) seem to be relevant for the problem. If I make the code more direct, it works.
Regards,
Amanda
Quoted text · Christian Grün · 29 lines
On Monday, August 12th, 2024 at 5:16 AM, Christian Grün <christian.gruen at gmail.com> wrote: > I managed to fix a part of the dependency problem. Your query should now be executable with the latest snapshot [1]. > – Christian > > [1] https://files.basex.org/releases/latest/ > > On Fri, Aug 9, 2024 at 5:51 PM Amanda Galtman <galtmana at proton.me> wrote: > >> Hi, all. >> >> I'm seeing an error in BaseX when I use function-lookup in both a global variable and a function, where the function relies on the variable. I reduced the situation to the following small query: >> >> xquery version "3.1"; >> declare variable $local:lookup := function-lookup(QName("nonexistent", "nonexistent"), 1); >> declare function local:myfcn() { >> let $f := ($local:lookup, function-lookup(QName('http://www.w3.org/2005/xpath-functions','string'), 1))[1] >> return $f('a') >> }; >> local:myfcn() >> >> When I run it with BaseX 11.1, I get >> [XQDY0054] Static variable depends on itself: $local:lookup >> >> When I run it with Saxon-HE 12, I don't get this error. >> >> Is there anything I can do in my code to avoid this error? >> >> Thanks, >> Amanda
CG
Christian Grün14 Aug 2024 15:43 #
…thanks. I already guessed it wasn’t that easy ;) I’ve added it to [1].
In general, I hope we could get completely rid of self-dependency checks. It was only defined for variables, not for functions, and I cannot see why we still need it today. We are currently discussing this topic for version 4.0 [2].
Best,
Christian
[1] https://github.com/BaseXdb/basex/issues/2324
[2] https://github.com/qt4cg/qtspecs/issues/1379
Quoted text · Amanda Galtman · 80 lines
On Wed, Aug 14, 2024 at 1:02 PM Amanda Galtman <galtmana at proton.me> wrote: > Christian, thanks very much. > > I returned to my actual code, and it works with the latest snapshot dated > today. > > By the way, I also retried the variations I had created when trying to > explore workarounds, and one of them still doesn't work with the latest > snapshot. It's not blocking me, but in case it is helpful, I reduced it to > another small query that reproduces the error with today's snapshot. I know > you said you fixed part of the problem, so you might not be surprised that > the following code still triggers the error. > > xquery version "3.1"; > > declare variable $variant := > if (exists(function-lookup(QName('nonexistent','nonexistent'), 0))) > then > ( (: not relevant :) ) > else > function-lookup(QName('http://www.w3.org/2005/xpath-functions','string'), > 1); > > declare variable $variant-fcns := $variant; > > declare function local:fcn() { > $variant-fcns('abc') > }; > > local:fcn() > > > The levels of indirection (variable, variable, function, function call) > seem to be relevant for the problem. If I make the code more direct, it > works. > > Regards, > Amanda > > On Monday, August 12th, 2024 at 5:16 AM, Christian Grün < > christian.gruen at gmail.com> wrote: > > I managed to fix a part of the dependency problem. Your query should now > be executable with the latest snapshot [1]. > – Christian > > [1] https://files.basex.org/releases/latest/ > > > > On Fri, Aug 9, 2024 at 5:51 PM Amanda Galtman <galtmana at proton.me> wrote: > >> Hi, all. >> >> I'm seeing an error in BaseX when I use function-lookup in both a global >> variable and a function, where the function relies on the variable. I >> reduced the situation to the following small query: >> >> xquery version "3.1"; >> declare variable $local:lookup := function-lookup(QName("nonexistent", >> "nonexistent"), 1); >> declare function local:myfcn() { >> let $f := ($local:lookup, function-lookup(QName(' >> http://www.w3.org/2005/xpath-functions','string'), 1))[1] >> return $f('a') >> }; >> local:myfcn() >> >> When I run it with BaseX 11.1, I get >> [XQDY0054] Static variable depends on itself: $local:lookup >> >> When I run it with Saxon-HE 12, I don't get this error. >> >> Is there anything I can do in my code to avoid this error? >> >> Thanks, >> Amanda >> > >
CG
Christian Grün18 Sep 2024 13:08 #
Hi Amanda,
The last query you reported back to us is now evaluated successfully [1].
In addition, XQuery 4 will allow all of us to write self-referencing variable declarations (it’s already supported by the latest snapshot):
declare variable $factorial := fn($x) {
if($x > 1) then $x + $factorial($x - 1) else $x
};
$factorial(5)All the best,
Christian
[1] https://github.com/BaseXdb/basex/issues/2324#issuecomment-2288790599
Quoted text · Christian Grün · 98 lines
On Wed, Aug 14, 2024 at 3:43 PM Christian Grün <christian.gruen at gmail.com> wrote: > …thanks. I already guessed it wasn’t that easy ;) I’ve added it to [1]. > > In general, I hope we could get completely rid of self-dependency checks. > It was only defined for variables, not for functions, and I cannot see why > we still need it today. We are currently discussing this topic for version > 4.0 [2]. > > Best, > Christian > > [1] https://github.com/BaseXdb/basex/issues/2324 > [2] https://github.com/qt4cg/qtspecs/issues/1379 > > > > On Wed, Aug 14, 2024 at 1:02 PM Amanda Galtman <galtmana at proton.me> wrote: > >> Christian, thanks very much. >> >> I returned to my actual code, and it works with the latest snapshot dated >> today. >> >> By the way, I also retried the variations I had created when trying to >> explore workarounds, and one of them still doesn't work with the latest >> snapshot. It's not blocking me, but in case it is helpful, I reduced it to >> another small query that reproduces the error with today's snapshot. I know >> you said you fixed part of the problem, so you might not be surprised that >> the following code still triggers the error. >> >> xquery version "3.1"; >> >> declare variable $variant := >> if (exists(function-lookup(QName('nonexistent','nonexistent'), 0))) >> then >> ( (: not relevant :) ) >> else >> function-lookup(QName(' >> http://www.w3.org/2005/xpath-functions','string'), 1); >> >> declare variable $variant-fcns := $variant; >> >> declare function local:fcn() { >> $variant-fcns('abc') >> }; >> >> local:fcn() >> >> >> The levels of indirection (variable, variable, function, function call) >> seem to be relevant for the problem. If I make the code more direct, it >> works. >> >> Regards, >> Amanda >> >> On Monday, August 12th, 2024 at 5:16 AM, Christian Grün < >> christian.gruen at gmail.com> wrote: >> >> I managed to fix a part of the dependency problem. Your query should now >> be executable with the latest snapshot [1]. >> – Christian >> >> [1] https://files.basex.org/releases/latest/ >> >> >> >> On Fri, Aug 9, 2024 at 5:51 PM Amanda Galtman <galtmana at proton.me> wrote: >> >>> Hi, all. >>> >>> I'm seeing an error in BaseX when I use function-lookup in both a global >>> variable and a function, where the function relies on the variable. I >>> reduced the situation to the following small query: >>> >>> xquery version "3.1"; >>> declare variable $local:lookup := function-lookup(QName("nonexistent", >>> "nonexistent"), 1); >>> declare function local:myfcn() { >>> let $f := ($local:lookup, function-lookup(QName(' >>> http://www.w3.org/2005/xpath-functions','string'), 1))[1] >>> return $f('a') >>> }; >>> local:myfcn() >>> >>> When I run it with BaseX 11.1, I get >>> [XQDY0054] Static variable depends on itself: $local:lookup >>> >>> When I run it with Saxon-HE 12, I don't get this error. >>> >>> Is there anything I can do in my code to avoid this error? >>> >>> Thanks, >>> Amanda >>> >> >>
AG
Amanda Galtman18 Sep 2024 21:34 #
Christian, thanks for the fix and the follow-up!
Best regards,
Amanda
Quoted text · Christian Grün · 89 lines
On Wednesday, September 18th, 2024 at 7:08 AM, Christian Grün <christian.gruen at gmail.com> wrote: > Hi Amanda, > > The last query you reported back to us is now evaluated successfully [1]. > > In addition, XQuery 4 will allow all of us to write self-referencing variable declarations (it’s already supported by the latest snapshot): > > declare variable $factorial := fn($x) { > if($x > 1) then $x + $factorial($x - 1) else $x > }; > $factorial(5) > > All the best, > Christian > > [1] https://github.com/BaseXdb/basex/issues/2324#issuecomment-2288790599 > > On Wed, Aug 14, 2024 at 3:43 PM Christian Grün <christian.gruen at gmail.com> wrote: > >> …thanks. I already guessed it wasn’t that easy ;) I’ve added it to [1]. >> >> In general, I hope we could get completely rid of self-dependency checks. It was only defined for variables, not for functions, and I cannot see why we still need it today. We are currently discussing this topic for version 4.0 [2]. >> >> Best, >> Christian >> >> [1] https://github.com/BaseXdb/basex/issues/2324 >> [2] https://github.com/qt4cg/qtspecs/issues/1379 >> >> On Wed, Aug 14, 2024 at 1:02 PM Amanda Galtman <galtmana at proton.me> wrote: >> >>> Christian, thanks very much. >>> >>> I returned to my actual code, and it works with the latest snapshot dated today. >>> >>> By the way, I also retried the variations I had created when trying to explore workarounds, and one of them still doesn't work with the latest snapshot. It's not blocking me, but in case it is helpful, I reduced it to another small query that reproduces the error with today's snapshot. I know you said you fixed part of the problem, so you might not be surprised that the following code still triggers the error. >>> >>> xquery version "3.1"; >>> >>> declare variable $variant := >>> if (exists(function-lookup(QName('nonexistent','nonexistent'), 0))) >>> then >>> ( (: not relevant :) ) >>> else >>> function-lookup(QName('http://www.w3.org/2005/xpath-functions','string'), 1); >>> >>> declare variable $variant-fcns := $variant; >>> >>> declare function local:fcn() { >>> $variant-fcns('abc') >>> }; >>> >>> local:fcn() >>> >>> The levels of indirection (variable, variable, function, function call) seem to be relevant for the problem. If I make the code more direct, it works. >>> >>> Regards, >>> Amanda >>> >>> On Monday, August 12th, 2024 at 5:16 AM, Christian Grün <christian.gruen at gmail.com> wrote: >>> >>>> I managed to fix a part of the dependency problem. Your query should now be executable with the latest snapshot [1]. >>>> – Christian >>>> >>>> [1] https://files.basex.org/releases/latest/ >>>> >>>> On Fri, Aug 9, 2024 at 5:51 PM Amanda Galtman <galtmana at proton.me> wrote: >>>> >>>>> Hi, all. >>>>> >>>>> I'm seeing an error in BaseX when I use function-lookup in both a global variable and a function, where the function relies on the variable. I reduced the situation to the following small query: >>>>> >>>>> xquery version "3.1"; >>>>> declare variable $local:lookup := function-lookup(QName("nonexistent", "nonexistent"), 1); >>>>> declare function local:myfcn() { >>>>> let $f := ($local:lookup, function-lookup(QName('http://www.w3.org/2005/xpath-functions','string'), 1))[1] >>>>> return $f('a') >>>>> }; >>>>> local:myfcn() >>>>> >>>>> When I run it with BaseX 11.1, I get >>>>> [XQDY0054] Static variable depends on itself: $local:lookup >>>>> >>>>> When I run it with Saxon-HE 12, I don't get this error. >>>>> >>>>> Is there anything I can do in my code to avoid this error? >>>>> >>>>> Thanks, >>>>> Amanda
CG
Hi Liam,
Quoted text · Liam R. E. Quin · 2 lines
Hmm, what if there's a $factorial in scope already? (this is a > technique i teach for taking advantage of closures to hide data)
Variables that are declared more than once in XQuery will continue to be rejected with the error code XQST0049 (duplicate declaration of static variable):
declare variable $a := 123;
declare variable $a := 'whatever';Best,
Christian
CG
Quoted text · Graydon · 3 lines
> > > If I use $x * $factorial($x - 1) >
True, it should have been multiplication; thanks.
I get an out-of-range error as of $factorial(21).
Quoted text · Graydon · 1 line
>
Integers in BaseX are limited to 64bit (that’s something the spec allows). You can use decimals to work with greater numbers:
declare variable $factorial := fn($x) {
if($x > 1) then $x * $factorial($x - 1) else $x
};
$factorial(1000.0)If you need even larger results, you can use a tail-call-optimized variant…
declare variable $factorial := fn($x, $result) {
if($x > 1) then $factorial($x - 1, $x * $result) else $result
};
$factorial(100000.0, 1)…or fold-left:
fold-left(1 to 100000, 1.0, op('*'))
Hope this helps,
Christian
LQ
Quoted text · Christian Grün · 10 lines
On Wed, 2024-09-18 at 13:08 +0200, Christian Grün wrote: > > In addition, XQuery 4 will allow all of us to write self-referencing > variable declarations (it’s already supported by the latest > snapshot): > > declare variable $factorial := fn($x) { > if($x > 1) then $x + $factorial($x - 1) else $x > }; > $factorial(5)
Hmm, what if there's a $factorial in scope already? (this is a technique i teach for taking advantage of closures to hide data)
Quoted text · Christian Grün · 1 line
> >
--
Liam Quin, https://www.delightfulcomputing.com/
Available for XML/Document/Information Architecture/XSLT/
XSL/XQuery/Web/Text Processing/A11Y training, work & consulting. Barefoot Web-slave, antique illustrations: http://www.fromoldbooks.org
G
Quoted text · Christian Grün · 8 lines
On Wed, Sep 18, 2024 at 01:08:17PM +0200, Christian Grün scripsit: > In addition, XQuery 4 will allow all of us to write self-referencing > variable declarations (it’s already supported by the latest snapshot): > > declare variable $factorial := fn($x) { > if($x > 1) then $x + $factorial($x - 1) else $x > }; > $factorial(5)
If I use $x * $factorial($x - 1)
I get an out-of-range error as of $factorial(21).
declare variable $factorial := fn($x) as xs:double {
if($x > 1) then $x * $factorial($x - 1) else $x
};goes until $factorial(171) gives INF.
If I were to be so unfortunate as to need larger factorials, is there a better approach?
It doesn't look like the math module has factorials and it does look like it uses xs:double for
math:pow(); on the other hand, XQuery isn't meant for numerical analysis.
Thanks!
Graydon--
Graydon Saunders | graydonish at fastmail.com
Þæs oferéode, ðisses swá mæg.
-- Deor ("That passed, so may this.")
LQ
Quoted text · Liam R. E. Quin · 4 lines
On Thu, 2024-09-19 at 09:01 -0400, Liam R. E. Quin wrote: > \ > Hmm, what if there's a $factorial in scope already? (this is a > technique i teach for taking advantage of closures to hide data)
Many thanks to Christian for taking the time to explain to me this isn’t a problem - the change provided a meaning for something that had previously been an error, and also only affecs XQuery.
Quoted text · Liam R. E. Quin · 1 line
>
--
Liam Quin, https://www.delightfulcomputing.com/
Available for XML/Document/Information Architecture/XSLT/
XSL/XQuery/Web/Text Processing/A11Y training, work & consulting. Barefoot Web-slave, antique illustrations: http://www.fromoldbooks.org
G
Quoted text · Christian Grün · 1 line
On Thu, Sep 19, 2024 at 04:08:34PM +0200, Christian Grün scripsit:
[snip]
Quoted text · Christian Grün · 20 lines
> Integers in BaseX are limited to 64bit (that’s something the spec allows). > You can use decimals to work with greater numbers: > > declare variable $factorial := fn($x) { > if($x > 1) then $x * $factorial($x - 1) else $x > }; > $factorial(1000.0) > > If you need even larger results, you can use a tail-call-optimized variant… > > declare variable $factorial := fn($x, $result) { > if($x > 1) then $factorial($x - 1, $x * $result) else $result > }; > $factorial(100000.0, 1) > > …or fold-left: > > fold-left(1 to 100000, 1.0, op('*')) > > Hope this helps,
Most helpful; thank you! It feels like my understanding of how types and processing interact has improved.
-- Graydon
RS
Rob Stapper21 Sep 2024 09:34 #
Perfect. Cascaded function-calls through variables within self-recursive constructs work fine now.
mvgr.
Rob Stapper
Written for BaseX 11.1, 11.2, 11.3. BaseX may have changed since: please check the current documentation.
⚡Generated with XQuery