Found problems with map:for-each
Monday, 19 February 2024 · 3 messages · last reply 20 Feb 2024
VC
Vincenzo Cestone19 Feb 2024 16:51 #
Hi all,
with the basex 10.7 version (but even in 9.6 version I have the same issue)
I found that the following code wont work as expected:
(: It wont work :)
let $files := map {"hello1.txt" : xs:base64Binary('SGVsbG8gd29ybGQ='),
"hello2.txt" : xs:base64Binary('SGVsbG8gd29ybGQ=')}
let $w := map:for-each($files, function($filename, $content) {
file:write-binary($filename, $content, 0)
})
return ()that is, it will not write the two files hello1.txt and hello2.txt in the basex_home/bin folder.
But, if you return $w instead:
(: It works :)
let $files := map {"hello1.txt" : xs:base64Binary('SGVsbG8gd29ybGQ='),
"hello2.txt" : xs:base64Binary('SGVsbG8gd29ybGQ=')}
let $w := map:for-each($files, function($filename, $content) {
file:write-binary($filename, $content, 0)
})
return $wWith a similar implementation, with the classic FLWOR, the issue does not arise, even if I return the empty sequence:
(: It works :)
let $files := map {"hello1.txt" : xs:base64Binary('SGVsbG8gd29ybGQ='),
"hello2.txt" : xs:base64Binary('SGVsbG8gd29ybGQ=')}
let $w := for $filename in map:keys($files)
return file:write-binary($filename, map:get($files, $filename), 0)
return ()that is it will write two files hello1.txt and hello2.txt in basex_home/bin folder.
Note that the files in the examples above are for demonstration purposes, however in my code they are actually binary files.
My java version is a Oracle JDK 17
This problem also occur to others?
Thanks,
Vincenzo
CG
Christian Grün19 Feb 2024 19:20 #
Hi Vincenzo,
Thanks for your observation and the easily reproducible test case; we’ve uploaded a new stable snapshot with a bug fix.
Please note that it’s generally risky to explicitly return empty sequences, as the optimizer will always try to get rid of code that may not contribute to the final result (we try hard, though, to keep code alive that has side effects, such as
file:write-binary). In the given case, you could simply rewrite your code as follows:let $files := map {"hello1.txt" : ... }
return map:for-each($files, function($filename, $content) {
file:write-binary($filename, $content, 0)
})Ciao,
Christian
[1] https://files.basex.org/releases/latest/
Quoted text · Vincenzo Cestone · 47 lines
On Mon, Feb 19, 2024 at 4:51 PM Vincenzo Cestone <v.cestone at gmail.com> wrote: > Hi all, > > with the basex 10.7 version (but even in 9.6 version I have the same > issue) I found that the following code wont work as expected: > (: It wont work :) > let $files := map {"hello1.txt" : xs:base64Binary('SGVsbG8gd29ybGQ='), > "hello2.txt" : xs:base64Binary('SGVsbG8gd29ybGQ=')} > let $w := map:for-each($files, function($filename, $content) { > file:write-binary($filename, $content, 0) > }) > return () > > that is, it will not write the two files hello1.txt and hello2.txt in the > basex_home/bin folder. > > But, if you return $w instead: > (: It works :) > let $files := map {"hello1.txt" : xs:base64Binary('SGVsbG8gd29ybGQ='), > "hello2.txt" : xs:base64Binary('SGVsbG8gd29ybGQ=')} > let $w := map:for-each($files, function($filename, $content) { > file:write-binary($filename, $content, 0) > }) > return $w > > With a similar implementation, with the classic FLWOR, the issue does not > arise, even if I return the empty sequence: > (: It works :) > let $files := map {"hello1.txt" : xs:base64Binary('SGVsbG8gd29ybGQ='), > "hello2.txt" : xs:base64Binary('SGVsbG8gd29ybGQ=')} > let $w := for $filename in map:keys($files) > return file:write-binary($filename, map:get($files, $filename), 0) > return () > > that is it will write two files hello1.txt and hello2.txt in > basex_home/bin folder. > > Note that the files in the examples above are for demonstration purposes, > however in my code they are actually binary files. > My java version is a Oracle JDK 17 > > This problem also occur to others? > > Thanks, > Vincenzo >
VC
Vincenzo Cestone20 Feb 2024 09:56 #
Hi Christian,
thank you very much for your very quick response and for fixing the issue.
Greetings
Quoted text · Christian Grün · 74 lines
Il giorno lun 19 feb 2024 alle ore 19:20 Christian Grün < christian.gruen at gmail.com> ha scritto: > Hi Vincenzo, > > Thanks for your observation and the easily reproducible test case; we’ve > uploaded a new stable snapshot with a bug fix. > > Please note that it’s generally risky to explicitly return empty > sequences, as the optimizer will always try to get rid of code that may not > contribute to the final result (we try hard, though, to keep code alive > that has side effects, such as file:write-binary). In the given case, you > could simply rewrite your code as follows: > > let $files := map {"hello1.txt" : ... } > return map:for-each($files, function($filename, $content) { > file:write-binary($filename, $content, 0) > }) > > Ciao, > Christian > > [1] https://files.basex.org/releases/latest/ > > > > On Mon, Feb 19, 2024 at 4:51 PM Vincenzo Cestone <v.cestone at gmail.com> > wrote: > >> Hi all, >> >> with the basex 10.7 version (but even in 9.6 version I have the same >> issue) I found that the following code wont work as expected: >> (: It wont work :) >> let $files := map {"hello1.txt" : xs:base64Binary('SGVsbG8gd29ybGQ='), >> "hello2.txt" : xs:base64Binary('SGVsbG8gd29ybGQ=')} >> let $w := map:for-each($files, function($filename, $content) { >> file:write-binary($filename, $content, 0) >> }) >> return () >> >> that is, it will not write the two files hello1.txt and hello2.txt in the >> basex_home/bin folder. >> >> But, if you return $w instead: >> (: It works :) >> let $files := map {"hello1.txt" : xs:base64Binary('SGVsbG8gd29ybGQ='), >> "hello2.txt" : xs:base64Binary('SGVsbG8gd29ybGQ=')} >> let $w := map:for-each($files, function($filename, $content) { >> file:write-binary($filename, $content, 0) >> }) >> return $w >> >> With a similar implementation, with the classic FLWOR, the issue does not >> arise, even if I return the empty sequence: >> (: It works :) >> let $files := map {"hello1.txt" : xs:base64Binary('SGVsbG8gd29ybGQ='), >> "hello2.txt" : xs:base64Binary('SGVsbG8gd29ybGQ=')} >> let $w := for $filename in map:keys($files) >> return file:write-binary($filename, map:get($files, $filename), 0) >> return () >> >> that is it will write two files hello1.txt and hello2.txt in >> basex_home/bin folder. >> >> Note that the files in the examples above are for demonstration purposes, >> however in my code they are actually binary files. >> My java version is a Oracle JDK 17 >> >> This problem also occur to others? >> >> Thanks, >> Vincenzo >> >
Written for BaseX 10.7. BaseX may have changed since: please check the current documentation.
⚡Generated with XQuery