diff --git a/.existdb.json b/.existdb.json deleted file mode 100644 index a8b611d..0000000 --- a/.existdb.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "servers": { - "localhost": { - "server": "http://localhost:8080/exist", - "user": "admin", - "password": "", - "root": "/db/system/repo/xbow" - } - }, - "package": { - "author": "Juri Leino", - "target": "xbow", - "description": "Shoot arrow (expressions) fast and comfortably", - "namespace": "http://line-o.de/xq/xbow", - "website": "https://github.com/line-o/xbow", - "status": "beta", - "title": "xBow - Shoot arrow expressions fast and comfortably", - "export": "xbow.xqm" - } -} diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..96841ba --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,13 @@ +import prettierPluginXQuery from 'prettier-plugin-xquery'; + +/** + * @type {import('prettier').Config} + */ +const config = { + useTabs: true, + singleQuote: true, + printWidth: 120, + plugins: [prettierPluginXQuery], +}; + +export default config; \ No newline at end of file diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..604be07 --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +nodejs 22.14.0 diff --git a/package-lock.json b/package-lock.json index 04d42ea..18bef79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,8 @@ "gulp-replace": "^1.0.0", "gulp-zip": "^5.0.2", "mocha": "^8.2.1", + "prettier": "^3.5.3", + "prettier-plugin-xquery": "^0.0.8", "semantic-release": "^17.3.3", "superagent": "^6.1.0" } @@ -8525,7 +8527,6 @@ }, "node_modules/npm/node_modules/lodash._baseindexof": { "version": "3.1.0", - "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -8541,19 +8542,16 @@ }, "node_modules/npm/node_modules/lodash._bindcallback": { "version": "3.0.1", - "extraneous": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/lodash._cacheindexof": { "version": "3.0.2", - "extraneous": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/lodash._createcache": { "version": "3.1.2", - "extraneous": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -8568,7 +8566,6 @@ }, "node_modules/npm/node_modules/lodash._getnative": { "version": "3.9.1", - "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -8586,7 +8583,6 @@ }, "node_modules/npm/node_modules/lodash.restparam": { "version": "3.6.1", - "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -11396,6 +11392,32 @@ "node": ">=0.10.0" } }, + "node_modules/prettier": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-xquery": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/prettier-plugin-xquery/-/prettier-plugin-xquery-0.0.8.tgz", + "integrity": "sha512-ZeGOv5A9KEptdbwwCrzyuktvRMqJW83qIeEA/4unTD7dJfP5hRDwWMBnLULxg9ptnoUIC7i84ynYkBy1VBuoxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier": "^3.5.3" + } + }, "node_modules/pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -20721,8 +20743,7 @@ }, "lodash._baseindexof": { "version": "3.1.0", - "bundled": true, - "extraneous": true + "bundled": true }, "lodash._baseuniq": { "version": "4.6.0", @@ -20735,18 +20756,15 @@ }, "lodash._bindcallback": { "version": "3.0.1", - "bundled": true, - "extraneous": true + "bundled": true }, "lodash._cacheindexof": { "version": "3.0.2", - "bundled": true, - "extraneous": true + "bundled": true }, "lodash._createcache": { "version": "3.1.2", "bundled": true, - "extraneous": true, "requires": { "lodash._getnative": "^3.0.0" } @@ -20758,8 +20776,7 @@ }, "lodash._getnative": { "version": "3.9.1", - "bundled": true, - "extraneous": true + "bundled": true }, "lodash._root": { "version": "3.0.1", @@ -20773,8 +20790,7 @@ }, "lodash.restparam": { "version": "3.6.1", - "bundled": true, - "extraneous": true + "bundled": true }, "lodash.union": { "version": "4.6.0", @@ -22960,6 +22976,21 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, + "prettier": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "dev": true + }, + "prettier-plugin-xquery": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/prettier-plugin-xquery/-/prettier-plugin-xquery-0.0.8.tgz", + "integrity": "sha512-ZeGOv5A9KEptdbwwCrzyuktvRMqJW83qIeEA/4unTD7dJfP5hRDwWMBnLULxg9ptnoUIC7i84ynYkBy1VBuoxg==", + "dev": true, + "requires": { + "prettier": "^3.5.3" + } + }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", diff --git a/package.json b/package.json index 9e42776..4c042f5 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "gulp-replace": "^1.0.0", "gulp-zip": "^5.0.2", "mocha": "^8.2.1", + "prettier": "^3.5.3", + "prettier-plugin-xquery": "^0.0.8", "semantic-release": "^17.3.3", "superagent": "^6.1.0" }, @@ -35,7 +37,8 @@ "scripts": { "test": "mocha src/test/mocha/*.js", "start": "gulp install", - "build": "gulp build" + "build": "gulp build", + "prettier": "prettier ./**/*.xq* --write" }, "repository": { "type": "git", diff --git a/src/content/xbow.xqm b/src/content/xbow.xqm index 1606cab..7bc7b40 100755 --- a/src/content/xbow.xqm +++ b/src/content/xbow.xqm @@ -1,14 +1,14 @@ -xquery version "3.1"; +xquery version '3.1'; + (:~ : : @author Juri Leino ~:) -module namespace xbow="http://line-o.de/xq/xbow"; - +module namespace xbow = 'http://line-o.de/xq/xbow'; (: Saxon does not declare map and array namespaces by default :) -declare namespace map = "http://www.w3.org/2005/xpath-functions/map"; -declare namespace array = "http://www.w3.org/2005/xpath-functions/array"; +declare namespace map = 'http://www.w3.org/2005/xpath-functions/map'; +declare namespace array = 'http://www.w3.org/2005/xpath-functions/array'; (:~ : get the first $n items from sequence $s @@ -16,9 +16,8 @@ declare namespace array = "http://www.w3.org/2005/xpath-functions/array"; : @param $s sequence of items : @param $n number of items to return ~:) -declare -function xbow:take ($s as item()*, $n as xs:integer) as item()* { - subsequence($s, 1, $n) +declare function xbow:take ($s as item()*, $n as xs:integer) as item()* { + subsequence($s, 1, $n) }; (:~ @@ -27,14 +26,12 @@ function xbow:take ($s as item()*, $n as xs:integer) as item()* { : @param $s sequence of items : @param $n number of items to return ~:) -declare -function xbow:last ($s as item()*, $n as xs:integer) as item()* { - subsequence($s, $n, count($s) - $n) +declare function xbow:last ($s as item()*, $n as xs:integer) as item()* { + subsequence($s, $n, count($s) - $n) }; -declare -function xbow:items-at ($s as item()*, $n as xs:integer*) as item()* { - for-each($n, subsequence($s, ?, 1)) +declare function xbow:items-at ($s as item()*, $n as xs:integer*) as item()* { + for-each($n, subsequence($s, ?, 1)) }; (:~ @@ -43,44 +40,60 @@ function xbow:items-at ($s as item()*, $n as xs:integer*) as item()* { : @param $s sequence of items : @param $f sorting function ~:) -declare -function xbow:sortBy ($s as item()*, $f as function(*)) as item()* { - sort($s, (), $f) +declare function xbow:sortBy ($s as item()*, $f as function(*)) as item()* { + sort($s, (), $f) }; -declare -function xbow:ascending ($s as item()*) as item()* { - xbow:sortBy($s, function ($a as item()) { xs:integer($a) }) +declare function xbow:ascending ($s as item()*) as item()* { + xbow:sortBy( + $s, + function ($a as item()) { + xs:integer($a) + } + ) }; -declare -function xbow:descending ($s as item()*) as item()* { - xbow:sortBy($s, function ($a as item()) { xs:integer(-$a) }) +declare function xbow:descending ($s as item()*) as item()* { + xbow:sortBy( + $s, + function ($a as item()) { + xs:integer(-$a) + } + ) }; (: group by :) -declare -function xbow:groupBy ($s as item()*, $key-function as function(*)) as map(*) { - fold-left($s, map {}, function ($result as map(*), $item as item()) { - let $key := $key-function($item) - let $value := ($result($key), $item) - return map:put($result, $key, $value) - }) -}; - -declare -function xbow:groupBy ($s as item()*, $key-function as function(*), $accessor as function(*)) as map(*) { - fold-left($s, map {}, function ($result as map(*), $item as item()) { - let $key := $key-function($accessor($item)) - let $value := ($result($key), $item) - return map:put($result, $key, $value) - }) -}; - -declare -function xbow:even-odd ($item as xs:numeric) as xs:string { - if ($item mod 2) then ('odd') else ('even') +declare function xbow:groupBy ($s as item()*, $key-function as function(*)) as map(*) { + fold-left( + $s, + map {}, + function ($result as map(*), $item as item()) { + let $key := $key-function($item) + let $value := ($result($key), $item) + return map:put($result, $key, $value) + } + ) +}; + +declare function xbow:groupBy ($s as item()*, $key-function as function(*), $accessor as function(*)) as map(*) { + fold-left( + $s, + map {}, + function ($result as map(*), $item as item()) { + let $key := $key-function($accessor($item)) + let $value := ($result($key), $item) + return map:put($result, $key, $value) + } + ) +}; + +declare function xbow:even-odd ($item as xs:numeric) as xs:string { + if ($item mod 2) then ( + 'odd' + ) else ( + 'even' + ) }; (: sequence tests :) @@ -95,11 +108,14 @@ function xbow:even-odd ($item as xs:numeric) as xs:string { : Returns : true() :) -declare -function xbow:all ($sequence as item()*, $comparison-function as function(*)) as xs:boolean { - fold-left($sequence, true(), function ($result as xs:boolean, $next as item()) as xs:boolean { - $result and $comparison-function($next) - }) +declare function xbow:all ($sequence as item()*, $comparison-function as function(*)) as xs:boolean { + fold-left( + $sequence, + true(), + function ($result as xs:boolean, $next as item()) as xs:boolean { + $result and $comparison-function($next) + } + ) }; (:~ @@ -112,11 +128,14 @@ function xbow:all ($sequence as item()*, $comparison-function as function(*)) as : Returns : true() :) -declare -function xbow:none ($sequence as item()*, $comparison-function as function(*)) as xs:boolean { - fold-left($sequence, true(), function ($result as xs:boolean, $next as item()) as xs:boolean { - $result and not($comparison-function($next)) - }) +declare function xbow:none ($sequence as item()*, $comparison-function as function(*)) as xs:boolean { + fold-left( + $sequence, + true(), + function ($result as xs:boolean, $next as item()) as xs:boolean { + $result and not($comparison-function($next)) + } + ) }; (:~ @@ -129,313 +148,347 @@ function xbow:none ($sequence as item()*, $comparison-function as function(*)) a : Returns : true() :) -declare -function xbow:some ($sequence as item()*, $comparison-function as function(*)) as xs:boolean { - fold-left($sequence, false(), function ($result as xs:boolean, $next as item()) as xs:boolean { - $result or $comparison-function($next) - }) +declare function xbow:some ($sequence as item()*, $comparison-function as function(*)) as xs:boolean { + fold-left( + $sequence, + false(), + function ($result as xs:boolean, $next as item()) as xs:boolean { + $result or $comparison-function($next) + } + ) }; (: accessor helpers :) -declare -function xbow:pluck ($field as xs:anyAtomicType) as item()* { - xbow:pluck(?, $field) +declare function xbow:pluck ($field as xs:anyAtomicType) as item()* { + xbow:pluck(?, $field) }; -declare -function xbow:pluck ($map-or-array-or-node as item(), $field as xs:anyAtomicType) as item()* { - typeswitch($map-or-array-or-node) - case array(*) - return xbow:pluck-array($map-or-array-or-node, $field) - case map(*) - return xbow:pluck-map($map-or-array-or-node, $field) - case node() - return xbow:pluck-node($map-or-array-or-node, $field) - default - return error( - xs:QName('xbow:invalid-argument'), - ``[`{$map-or-array-or-node}` is not an array, a map nor a node]``) +declare function xbow:pluck ($map-or-array-or-node as item(), $field as xs:anyAtomicType) as item()* { + typeswitch ($map-or-array-or-node) + case array(*) return + xbow:pluck-array($map-or-array-or-node, $field) + case map(*) return + xbow:pluck-map($map-or-array-or-node, $field) + case node() return + xbow:pluck-node($map-or-array-or-node, $field) + + default return + error(xs:QName('xbow:invalid-argument'), ``[`{$map-or-array-or-node}` is not an array, a map nor a node]``) }; -declare -function xbow:pluck-map ($field as xs:string) as item()* { - xbow:pluck-map(?, $field) +declare function xbow:pluck-map ($field as xs:string) as item()* { + xbow:pluck-map(?, $field) }; -declare -function xbow:pluck-map ($map as map(*), $field as xs:string) as item()* { - $map($field) +declare function xbow:pluck-map ($map as map(*), $field as xs:string) as item()* { + $map($field) }; -declare -function xbow:pluck-array ($index as xs:integer) as item()* { - xbow:pluck-array(?, $index) +declare function xbow:pluck-array ($index as xs:integer) as item()* { + xbow:pluck-array(?, $index) }; -declare -function xbow:pluck-array ($array as array(*), $index as xs:integer) as item()* { - $array($index) +declare function xbow:pluck-array ($array as array(*), $index as xs:integer) as item()* { + $array($index) }; -declare -function xbow:pluck-node ($field as xs:string) as item()* { - xbow:pluck-node(?, $field) +declare function xbow:pluck-node ($field as xs:string) as item()* { + xbow:pluck-node(?, $field) }; -declare -function xbow:pluck-node ($node as node(), $field as xs:string+) as item()* { - if (contains($field, '//')) - then (error( - xs:QName('xbow:invalid-dynamic-path'), - ``[`{$field}` contains "//" which is not supported]``)) - else if (contains($field, '/')) - then (fold-left(tokenize($field, '/'), $node, xbow:pluck-node-part#2)) - else if (count($field) > 1) - then (fold-left($field, $node, xbow:pluck-node-part#2)) - else (xbow:pluck-node-part($node, $field)) +declare function xbow:pluck-node ($node as node(), $field as xs:string+) as item()* { + if (contains($field, '//')) then ( + error(xs:QName('xbow:invalid-dynamic-path'), ``[`{$field}` contains "//" which is not supported]``) + ) else if (contains($field, '/')) then ( + fold-left(tokenize($field, '/'), $node, xbow:pluck-node-part#2) + ) else if (count($field) > 1) then ( + fold-left($field, $node, xbow:pluck-node-part#2) + ) else ( + xbow:pluck-node-part($node, $field) + ) }; -declare - %private -function xbow:pluck-node-part ($node as node(), $path-part as xs:string?) as node()? { - if (contains($path-part, ':') or contains($path-part, '[') or contains($path-part, '(')) - then (error( - xs:QName('xbow:invalid-dynamic-path'), - ``[`{$path-part}` contains ":", "[" or "(" which is not supported]``)) - else if (empty($path-part)) - then (root($node)) - else if ($path-part = ('', '.')) - then ($node) - else if ($path-part eq '..') - then ($node/..) - else if (starts-with($path-part, '@')) - then ($node/@*[local-name() eq substring($path-part, 2)]) - else ($node/*[name() eq $path-part]) +declare %private function xbow:pluck-node-part ($node as node(), $path-part as xs:string?) as node()? { + if (contains($path-part, ':') or contains($path-part, '[') or contains($path-part, '(')) then ( + error(xs:QName('xbow:invalid-dynamic-path'), ``[`{$path-part}` contains ":", "[" or "(" which is not supported]``) + ) else if (empty($path-part)) then ( + root($node) + ) else if ($path-part = ('', '.')) then ( + $node + ) else if ($path-part eq '..') then ( + $node/.. + ) else if (starts-with($path-part, '@')) then ( + $node/@*[local-name() eq substring($path-part, 2)] + ) else ( + $node/*[name() eq $path-part] + ) }; -declare -function xbow:pluck-deep ($fields as xs:anyAtomicType*) as item()* { - xbow:pluck-deep(?, $fields) +declare function xbow:pluck-deep ($fields as xs:anyAtomicType*) as item()* { + xbow:pluck-deep(?, $fields) }; -declare -function xbow:pluck-deep ($map-or-array-or-node as item(), $fields as xs:anyAtomicType*) as item()* { - fold-left($fields, $map-or-array-or-node, function ($eventual-item as item()*, $field) { - if (exists($eventual-item)) - then (xbow:pluck($eventual-item, $field)) - else () - }) +declare function xbow:pluck-deep ($map-or-array-or-node as item(), $fields as xs:anyAtomicType*) as item()* { + fold-left( + $fields, + $map-or-array-or-node, + function ($eventual-item as item()*, $field) { + if (exists($eventual-item)) then ( + xbow:pluck($eventual-item, $field) + ) else ( + ) + } + ) }; (: stats :) -declare variable $xbow:disdup-init := map { - 'distinct': map {}, - 'duplicates': () -}; +declare variable $xbow:disdup-init := map {'distinct': map {}, 'duplicates': ()}; declare function xbow:disdup-reducer ($result as map(*), $next as xs:string) as map(*) { - if (exists($result?distinct($next))) - then (map:put($result, 'duplicates', ($result?duplicates, $next))) - else (map:put($result, 'distinct', map:put($result?distinct, $next, true()))) + if (exists($result?distinct($next))) then ( + map:put( + $result, + 'duplicates', + ( + $result?duplicates, $next + ) + ) + ) else ( + map:put($result, 'distinct', map:put($result?distinct, $next, true())) + ) }; -declare function xbow:distinct-duplicates($s as item()*) as map(*) { - fold-left($s, $xbow:disdup-init, xbow:disdup-reducer#2) +declare function xbow:distinct-duplicates ($s as item()*) as map(*) { + fold-left($s, $xbow:disdup-init, xbow:disdup-reducer#2) }; -declare function xbow:distinct-duplicates($s as item()*, $accessor as function(*)) as map(*) { - fold-left(for-each($s, $accessor(?)), $xbow:disdup-init, xbow:disdup-reducer#2) +declare function xbow:distinct-duplicates ($s as item()*, $accessor as function(*)) as map(*) { + fold-left(for-each($s, $accessor(?)), $xbow:disdup-init, xbow:disdup-reducer#2) }; -declare -function xbow:sequence-stats-reducer ($result as map(*), $next as xs:numeric) as map(*) { - map { - 'min': min(($result?min, $next)), +declare function xbow:sequence-stats-reducer ($result as map(*), $next as xs:numeric) as map(*) { + map { + 'min': min(($result?min, $next)), 'max': max(($result?max, $next)), - 'avg': ($result?sum + $next) div ($result?length + 1), - 'sum': $result?sum + $next, - 'length': $result?length + 1 + 'avg': ($result?sum + $next) div ($result?length + 1), + 'sum': $result?sum + $next, + 'length': $result?length + 1 } }; -declare variable $xbow:initial-stats := - map { 'min': (), 'max': (), 'avg': 0.0, 'sum': 0, 'length': 0 }; +declare variable $xbow:initial-stats := map {'min': (), 'max': (), 'avg': 0.0, 'sum': 0, 'length': 0}; declare function xbow:num-stats ($sequence as xs:numeric*) as map(*) { - fold-left($sequence, $xbow:initial-stats, xbow:sequence-stats-reducer#2) + fold-left($sequence, $xbow:initial-stats, xbow:sequence-stats-reducer#2) }; (: conversion helper functions :) -declare -function xbow:to-array ($sequence as item()*) as array(*) { - array { $sequence } +declare function xbow:to-array ($sequence as item()*) as array(*) { + array{ + $sequence + } }; -declare -function xbow:to-sequence ($array as array(*)) as item()* { - $array?* +declare function xbow:to-sequence ($array as array(*)) as item()* { + $array?* }; (: comparison helper functions :) -declare -function xbow:ne ($comparison as item()) as function(*) { - function ($i as item()) as xs:boolean { $i ne $comparison } +declare function xbow:ne ($comparison as item()) as function(*) { + function ($i as item()) as xs:boolean { + $i ne $comparison + } }; -declare -function xbow:ne ($comparison as item(), $accessor as function(*)) as function(*) { - function ($i as item()) as xs:boolean { $accessor($i) ne $comparison } +declare function xbow:ne ($comparison as item(), $accessor as function(*)) as function(*) { + function ($i as item()) as xs:boolean { + $accessor($i) ne $comparison + } }; -declare -function xbow:eq ($comparison as item()) as function(*) { - function ($i as item()) as xs:boolean { $i eq $comparison } +declare function xbow:eq ($comparison as item()) as function(*) { + function ($i as item()) as xs:boolean { + $i eq $comparison + } }; -declare -function xbow:eq ($comparison as item(), $accessor as function(*)) as function(*) { - function ($i as item()) as xs:boolean { $accessor($i) eq $comparison } +declare function xbow:eq ($comparison as item(), $accessor as function(*)) as function(*) { + function ($i as item()) as xs:boolean { + $accessor($i) eq $comparison + } }; -declare -function xbow:gt ($comparison as item(), $accessor as function(*)) as function(*) { - function ($i as item()) as xs:boolean { $accessor($i) gt $comparison } +declare function xbow:gt ($comparison as item(), $accessor as function(*)) as function(*) { + function ($i as item()) as xs:boolean { + $accessor($i) gt $comparison + } }; -declare -function xbow:gt ($comparison as item()) as function(*) { - function ($i as item()) as xs:boolean { $i > $comparison } +declare function xbow:gt ($comparison as item()) as function(*) { + function ($i as item()) as xs:boolean { + $i > $comparison + } }; -declare -function xbow:ge ($comparison as item(), $accessor as function(*)) as function(*) { - function ($i as item()) as xs:boolean { $accessor($i) >= $comparison } +declare function xbow:ge ($comparison as item(), $accessor as function(*)) as function(*) { + function ($i as item()) as xs:boolean { + $accessor($i) >= $comparison + } }; -declare -function xbow:ge ($comparison as item()) as function(*) { - function ($i as item()) as xs:boolean { $i >= $comparison } +declare function xbow:ge ($comparison as item()) as function(*) { + function ($i as item()) as xs:boolean { + $i >= $comparison + } }; -declare -function xbow:lt ($comparison as item(), $accessor as function(*)) as function(*) { - function ($i as item()) as xs:boolean { $accessor($i) lt $comparison } +declare function xbow:lt ($comparison as item(), $accessor as function(*)) as function(*) { + function ($i as item()) as xs:boolean { + $accessor($i) lt $comparison + } }; -declare -function xbow:lt ($comparison as item()) as function(*) { - function ($i as item()) as xs:boolean { $i lt $comparison } +declare function xbow:lt ($comparison as item()) as function(*) { + function ($i as item()) as xs:boolean { + $i lt $comparison + } }; -declare -function xbow:le ($comparison as item(), $accessor as function(*)) as function(*) { - function ($i as item()) as xs:boolean { $accessor($i) le $comparison } +declare function xbow:le ($comparison as item(), $accessor as function(*)) as function(*) { + function ($i as item()) as xs:boolean { + $accessor($i) le $comparison + } }; -declare -function xbow:le ($comparison as item()) as function(*) { - function ($i as item()) as xs:boolean { $i le $comparison } +declare function xbow:le ($comparison as item()) as function(*) { + function ($i as item()) as xs:boolean { + $i le $comparison + } }; (: control-flow helpers :) -declare -function xbow:test ($item as item()*, $test as function(*), $then as function(*)) as item()* { - if ($test($item)) - then ($then($item)) - else ($item) +declare function xbow:test ($item as item()*, $test as function(*), $then as function(*)) as item()* { + if ($test($item)) then ( + $then($item) + ) else ( + $item + ) }; -declare -function xbow:if ($item as item()*, $test as function(*), $then as function(*), $else as function(*)) as item()* { - if ($test($item)) - then ($then($item)) - else ($else($item)) +declare function xbow:if ( + $item as item()*, + $test as function(*), + $then as function(*), + $else as function(*) +) as item()* { + if ($test($item)) then ( + $then($item) + ) else ( + $else($item) + ) }; -declare -function xbow:and ($item as item()*, $a as function(*), $b as function(*)) as item()* { - if ($a($item) and $b($item)) - then ($item) - else () +declare function xbow:and ($item as item()*, $a as function(*), $b as function(*)) as item()* { + if ($a($item) and $b($item)) then ( + $item + ) else ( + ) }; -declare -function xbow:or ($item as item()*, $a as function(*), $b as function(*)) as item()* { - if ($a($item) or $b($item)) - then ($item) - else () +declare function xbow:or ($item as item()*, $a as function(*), $b as function(*)) as item()* { + if ($a($item) or $b($item)) then ( + $item + ) else ( + ) }; -declare -function xbow:xor ($item as item()*, $a as function(*), $b as function(*)) as item()* { - let $_a := $a($item) - let $_b := $b($item) - return - if (($_a or $_b) and not($_a and $_b)) - then ($item) - else () +declare function xbow:xor ($item as item()*, $a as function(*), $b as function(*)) as item()* { + let $_a := $a($item) + let $_b := $b($item) + return if (($_a or $_b) and not($_a and $_b)) then ( + $item + ) else ( + ) }; -declare -function xbow:nor ($item as item()*, $a as function(*), $b as function(*)) as item()* { - if (not($a($item)) and not($b($item))) - then ($item) - else () +declare function xbow:nor ($item as item()*, $a as function(*), $b as function(*)) as item()* { + if (not($a($item)) and not($b($item))) then ( + $item + ) else ( + ) }; (: node constructors : these functions are inspired by a new standard proposed by Michael Kay :) -declare -function xbow:attribute ($name as item()*) as function(xs:string) as attribute() { - typeswitch($name) - case xs:QName return xbow:attribute-ns($name, ?) - case xs:string return xbow:attribute($name, ?) - default return error(xs:QName("xbow:invalid-argument"), "Invalid type of $name in xbow:element#1, expected either xs:QName or xs:string") +declare function xbow:attribute ($name as item()*) as function (xs:string) as attribute() { + typeswitch ($name) + case xs:QName return + xbow:attribute-ns($name, ?) + case xs:string return + xbow:attribute($name, ?) + + default return + error( + xs:QName('xbow:invalid-argument'), + 'Invalid type of $name in xbow:element#1, expected either xs:QName or xs:string' + ) }; -declare -function xbow:attribute-ns ($name as xs:QName, $contents as item()*, $joiner as xs:string) as attribute() { - attribute { $name } { string-join($contents, $joiner) } +declare function xbow:attribute-ns ($name as xs:QName, $contents as item()*, $joiner as xs:string) as attribute() { + attribute {$name} { + string-join($contents, $joiner) + } }; -declare -function xbow:attribute ($name as xs:string, $contents as item()*, $joiner as xs:string) as attribute() { - attribute { $name } { string-join($contents, $joiner) } +declare function xbow:attribute ($name as xs:string, $contents as item()*, $joiner as xs:string) as attribute() { + attribute {$name} { + string-join($contents, $joiner) + } }; -declare -function xbow:attribute-ns ($name as xs:QName, $value as xs:string) as attribute() { - attribute { $name } { $value } +declare function xbow:attribute-ns ($name as xs:QName, $value as xs:string) as attribute() { + attribute {$name} { + $value + } }; -declare -function xbow:attribute ($name as xs:string, $value as xs:string) as attribute() { - attribute { $name } { $value } +declare function xbow:attribute ($name as xs:string, $value as xs:string) as attribute() { + attribute {$name} { + $value + } }; -declare -function xbow:element ($name as item()) as function(item()*) as element() { - typeswitch($name) - case xs:QName return xbow:element-ns($name, ?) - case xs:string return xbow:element($name, ?) - default return error(xs:QName("xbow:invalid-argument"), "Invalid type of $name in xbow:element#1, expected either xs:QName or xs:string got: " || xbow:get-type($name)) +declare function xbow:element ($name as item()) as function (item()*) as element() { + typeswitch ($name) + case xs:QName return + xbow:element-ns($name, ?) + case xs:string return + xbow:element($name, ?) + + default return + error( + xs:QName('xbow:invalid-argument'), + 'Invalid type of $name in xbow:element#1, expected either xs:QName or xs:string got: ' || xbow:get-type($name) + ) }; -declare -function xbow:element ($name as xs:string, $contents as item()*) as element() { - element { $name } { $contents } +declare function xbow:element ($name as xs:string, $contents as item()*) as element() { + element {$name} { + $contents + } }; -declare -function xbow:element-ns ($name as xs:QName, $contents as item()*) as element() { - element { $name } { $contents } +declare function xbow:element-ns ($name as xs:QName, $contents as item()*) as element() { + element {$name} { + $contents + } }; (: wrapping values in nodes :) @@ -445,17 +498,23 @@ function xbow:element-ns ($name as xs:QName, $contents as item()*) as element() : returns function that returns an element() : <$node-name>$item(s) :) -declare -function xbow:wrap-element ($contents as item()*, $name as item()) as element() { - typeswitch($name) - case xs:QName return xbow:element-ns($name, $contents) - case xs:string return xbow:element($name, $contents) - default return error(xs:QName("xbow:invalid-argument"), "Invalid type of $name in xbow:wrap-element#2, expected either xs:QName or xs:string for parameter two got: " || xbow:get-type($name)) +declare function xbow:wrap-element ($contents as item()*, $name as item()) as element() { + typeswitch ($name) + case xs:QName return + xbow:element-ns($name, $contents) + case xs:string return + xbow:element($name, $contents) + + default return + error( + xs:QName('xbow:invalid-argument'), + 'Invalid type of $name in xbow:wrap-element#2, expected either xs:QName or xs:string for parameter two got: ' || + xbow:get-type($name) + ) }; -declare -function xbow:wrap-attribute ($value as item()*, $attribute-name as xs:string) as attribute() { - xbow:attribute($attribute-name, string-join($value, ' ')) +declare function xbow:wrap-attribute ($value as item()*, $attribute-name as xs:string) as attribute() { + xbow:attribute($attribute-name, string-join($value, ' ')) }; (:~ @@ -463,9 +522,8 @@ function xbow:wrap-attribute ($value as item()*, $attribute-name as xs:string) a : returns function that returns an attribute() : multiple items will be joined into a single string separated by $joiner :) -declare -function xbow:wrap-attribute ($value as item()*, $name as xs:string, $joiner as xs:string) as attribute() { - xbow:attribute($name, string-join($value, $joiner)) +declare function xbow:wrap-attribute ($value as item()*, $name as xs:string, $joiner as xs:string) as attribute() { + xbow:attribute($name, string-join($value, $joiner)) }; (:~ @@ -478,26 +536,26 @@ function xbow:wrap-attribute ($value as item()*, $name as xs:string, $joiner as <$node-name>$item[1] ) :) -declare -function xbow:wrap-each ($values as item()*, $node-name as xs:string) as element()* { - for-each($values, xbow:element($node-name, ?)) +declare function xbow:wrap-each ($values as item()*, $node-name as xs:string) as element()* { + for-each($values, xbow:element($node-name, ?)) }; -declare -function xbow:wrap-map-attribute ($map as map(*)) as attribute()* { - map:for-each($map, xbow:attribute#2) +declare function xbow:wrap-map-attribute ($map as map(*)) as attribute()* { + map:for-each($map, xbow:attribute#2) }; -declare -function xbow:wrap-map-element ($map as map(*)) as element()* { - map:for-each($map, xbow:element#2) +declare function xbow:wrap-map-element ($map as map(*)) as element()* { + map:for-each($map, xbow:element#2) }; -declare -function xbow:map-filter-keys ($map as map(*), $keys as xs:string*) as map(*) { - for-each($keys, function ($key as xs:anyAtomicType) { - map:entry($key, $map($key)) }) - => map:merge() +declare function xbow:map-filter-keys ($map as map(*), $keys as xs:string*) as map(*) { + for-each( + $keys, + function ($key as xs:anyAtomicType) { + map:entry($key, $map($key)) + } + ) + => map:merge() }; (:~ @@ -505,13 +563,14 @@ function xbow:map-filter-keys ($map as map(*), $keys as xs:string*) as map(*) { : Example: xbow:map-reverse(map { 'key': 'value'}) :) -declare -function xbow:map-flip ($map as map(*)) as map(*) { - map:for-each($map, - function ($key as xs:anyAtomicType, $value as xs:anyAtomicType) as map(*) { - map { $value : $key } - }) - => map:merge() +declare function xbow:map-flip ($map as map(*)) as map(*) { + map:for-each( + $map, + function ($key as xs:anyAtomicType, $value as xs:anyAtomicType) as map(*) { + map {$value: $key} + } + ) + => map:merge() }; (:~ @@ -527,13 +586,14 @@ function xbow:map-flip ($map as map(*)) as map(*) { xbow:map-reverse(map { 'key': 'value'}, function ($v) { upper-case($v) }), xbow:map-reverse(map { 'key': 'value'}, function ($v) { util:uuid($v) }) :) -declare -function xbow:map-flip ($map as map(*), $hash-value as function(*)) as map(*) { - map:for-each($map, - function ($key as xs:anyAtomicType, $value as item()*) as map(*) { - map { $hash-value($value): $key } - }) - => map:merge() +declare function xbow:map-flip ($map as map(*), $hash-value as function(*)) as map(*) { + map:for-each( + $map, + function ($key as xs:anyAtomicType, $value as item()*) as map(*) { + map {$hash-value($value): $key} + } + ) + => map:merge() }; (:~ @@ -544,115 +604,147 @@ function xbow:map-flip ($map as map(*), $hash-value as function(*)) as map(*) { xbow:get-type([map{"a": true(), "b": false()}, map{"a":false()}]) : returns "array(map(xs:string, xs:boolean))" :) -declare -function xbow:get-type ($item as item()?) as xs:string { - typeswitch($item) - case element() return ``[element(`{name($item)}`)]`` - case attribute() return ``[attribute(`{name($item)}`)]`` - - case text() return "text()" - case comment() return "comment()" - - case array(*) return ``[array(`{xbow:array-type($item)}`)]`` - case map(*) return ``[map(`{xbow:map-type($item)}`)]`` - - (: XQuery 3.1 does not specify inspection functions only arity can be read :) - case function(*) return "function(*)" - - case xs:boolean return 'xs:boolean' - case xs:string return 'xs:string' - - case xs:positiveInteger return 'xs:positiveInteger' - case xs:negativeInteger return 'xs:negativeInteger' - case xs:integer return 'xs:integer' - case xs:double return 'xs:double' - case xs:float return 'xs:float' - case xs:decimal return 'xs:decimal' - - case xs:date return 'xs:date' - case xs:time return 'xs:time' - case xs:dateTime return 'xs:dateTime' - - case xs:QName return 'xs:QName' - case xs:NCName return 'xs:NCName' - - case xs:anyAtomicType return 'xs:anyAtomicType' - default return 'item()' -}; - -declare -function xbow:array-type($array as array(*)) as xs:string { - if (array:size($array) eq 0) - then "*" - else array:fold-left($array, (), xbow:subtype-reducer#2) -}; - -declare -function xbow:map-type($map as map(*)) as xs:string { - let $keys := map:keys($map) - return - if (count($keys) eq 0) - then "*" - else fold-left($keys, [(), ()], - function ($result as array(xs:string), $next as xs:anyAtomicType) { - [ - xbow:subtype-reducer($result?1, $next), - xbow:subtype-reducer($result?2, $map($next)) - ] - }) - => (function ($array as array(xs:string)) as xs:string { - if ($array?1 = "*" and $array?2 = "*") - then "*" - else string-join($array?*, ', ') - })() -}; - -declare %private -function xbow:subtype-reducer ($result as xs:string?, $item as item()?) as xs:string { - if ($result = "*") - then $result (: fast-track mixed content :) - else if (not(exists($item))) - then "*" - else if (not(exists($result))) - then xbow:get-type($item) - else if (xbow:get-type($item) eq $result) - then $result - else "*" -}; - -declare -function xbow:instance-of($item as item()?, $type as xs:string) as xs:boolean { - (: complex types :) - - if (starts-with($type, "array")) then $item instance of array(*) - else if (starts-with($type, "map")) then $item instance of map(*) - else if (starts-with($type, "function")) then $item instance of function(*) - else if (starts-with($type, "node")) then $item instance of node() - else if (starts-with($type, "element")) then $item instance of element() - else if (starts-with($type, "attribute")) then $item instance of attribute() - else if (starts-with($type, "text")) then $item instance of text() - else if (starts-with($type, "document")) then $item instance of document-node() - - (: simple types :) - - else if (ends-with($type, "anyAtomicType")) then $item instance of xs:anyAtomicType - else if (ends-with($type, "string")) then $item instance of xs:string - else if (ends-with($type, "numeric")) then $item instance of xs:numeric - else if (ends-with($type, "decimal")) then $item instance of xs:decimal - else if (ends-with($type, "integer")) then $item instance of xs:integer - else if (ends-with($type, "dateTime")) then $item instance of xs:dateTime - else if (ends-with($type, "date")) then $item instance of xs:date - else if (ends-with($type, "time")) then $item instance of xs:time - else if (ends-with($type, "boolean")) then $item instance of xs:boolean - - (: generic types :) - - else if (starts-with($type, "item")) then $item instance of item() - else if (starts-with($type, "empty-sequence")) then $item instance of empty-sequence() - - (: unknown types :) - - else error(xs:QName("xbow:unknown-type"), "Unknown or unsupported type:'" || $type || "'.") +declare function xbow:get-type ($item as item()?) as xs:string { + typeswitch ($item) + case element() return + ``[element(`{name($item)}`)]`` + case attribute() return + ``[attribute(`{name($item)}`)]`` + case text() return + 'text()' + case comment() return + 'comment()' + case array(*) return + ``[array(`{xbow:array-type($item)}`)]`` + case map(*) return + ``[map(`{xbow:map-type($item)}`)]`` + (: XQuery 3.1 does not specify inspection functions only arity can be read :) + case function(*) return + 'function(*)' + case xs:boolean return + 'xs:boolean' + case xs:string return + 'xs:string' + case xs:positiveInteger return + 'xs:positiveInteger' + case xs:negativeInteger return + 'xs:negativeInteger' + case xs:integer return + 'xs:integer' + case xs:double return + 'xs:double' + case xs:float return + 'xs:float' + case xs:decimal return + 'xs:decimal' + case xs:date return + 'xs:date' + case xs:time return + 'xs:time' + case xs:dateTime return + 'xs:dateTime' + case xs:QName return + 'xs:QName' + case xs:NCName return + 'xs:NCName' + case xs:anyAtomicType return + 'xs:anyAtomicType' + + default return + 'item()' +}; + +declare function xbow:array-type ($array as array(*)) as xs:string { + if (array:size($array) eq 0) then + '*' + else + array:fold-left($array, (), xbow:subtype-reducer#2) +}; + +declare function xbow:map-type ($map as map(*)) as xs:string { + let $keys := map:keys($map) + return if (count($keys) eq 0) then + '*' + else + fold-left( + $keys, + [(), ()], + function ($result as array(xs:string), $next as xs:anyAtomicType) { + [xbow:subtype-reducer($result?1, $next), xbow:subtype-reducer($result?2, $map($next))] + } + ) + => ( + function ($array as array(xs:string)) as xs:string { + if ($array?1 = '*' and $array?2 = '*') then + '*' + else + string-join($array?*, ', ') + } + )() +}; + +declare %private function xbow:subtype-reducer ($result as xs:string?, $item as item()?) as xs:string { + if ($result = '*') then + $result (: fast-track mixed content :) + else if (not(exists($item))) then + '*' + else if (not(exists($result))) then + xbow:get-type($item) + else if (xbow:get-type($item) eq $result) then + $result + else + '*' +}; + +declare function xbow:instance-of ($item as item()?, $type as xs:string) as xs:boolean { + (: complex types :) + + if (starts-with($type, 'array')) then + $item instance of array(*) + else if (starts-with($type, 'map')) then + $item instance of map(*) + else if (starts-with($type, 'function')) then + $item instance of function(*) + else if (starts-with($type, 'node')) then + $item instance of node() + else if (starts-with($type, 'element')) then + $item instance of element() + else if (starts-with($type, 'attribute')) then + $item instance of attribute() + else if (starts-with($type, 'text')) then + $item instance of text() + else if (starts-with($type, 'document')) then + $item instance of document-node() + (: simple types :) + + else if (ends-with($type, 'anyAtomicType')) then + $item instance of xs:anyAtomicType + else if (ends-with($type, 'string')) then + $item instance of xs:string + else if (ends-with($type, 'numeric')) then + $item instance of xs:numeric + else if (ends-with($type, 'decimal')) then + $item instance of xs:decimal + else if (ends-with($type, 'integer')) then + $item instance of xs:integer + else if (ends-with($type, 'dateTime')) then + $item instance of xs:dateTime + else if (ends-with($type, 'date')) then + $item instance of xs:date + else if (ends-with($type, 'time')) then + $item instance of xs:time + else if (ends-with($type, 'boolean')) then + $item instance of xs:boolean + (: generic types :) + + else if (starts-with($type, 'item')) then + $item instance of item() + else if (starts-with($type, 'empty-sequence')) then + $item instance of empty-sequence() + (: unknown types :) + + else + error(xs:QName('xbow:unknown-type'), "Unknown or unsupported type:'" || $type || "'.") }; (:~ @@ -661,157 +753,174 @@ function xbow:instance-of($item as item()?, $type as xs:string) as xs:boolean { : @param function(*) $f two argument function : @returns calls function $f with its arguments flipped :) -declare -function xbow:flip-arguments ($a as item()*, $b as item()*, $f as function(item()*, item()*) as item()*) as function(*) { - if (function-arity($f) ne 2) - then ( - error( - xs:QName('xbow:wrong-number-of-arguments'), - ``[Received a function with an arity of `{function-arity($f)}` to xbow:flip-arguments but must be exactly 2]`` - ) - ) - else ($f($b, $a)) +declare function xbow:flip-arguments ( + $a as item()*, + $b as item()*, + $f as function (item()*, item()*) as item()* +) as function(*) { + if (function-arity($f) ne 2) then ( + error( + xs:QName('xbow:wrong-number-of-arguments'), + ``[Received a function with an arity of `{function-arity($f)}` to xbow:flip-arguments but must be exactly 2]`` + ) + ) else ( + $f($b, $a) + ) +}; + +declare function xbow:apply-insert-at ( + $argument as item()*, + $function as function(*), + $position as xs:integer, + $other-arguments as array(*) +) as item()* { + apply($function, array:put($other-arguments, $position, $argument)) +}; + +declare function xbow:apply-as-last ( + $argument as item()*, + $function as function(*), + $other-arguments as array(*) +) as item()* { + apply($function, array:append($other-arguments, $argument)) }; -declare -function xbow:apply-insert-at ($argument as item()*, $function as function(*), $position as xs:integer, $other-arguments as array(*)) as item()* { - apply($function, array:put($other-arguments, $position, $argument)) +(:~ + : combine a sequence of $functions and returns the combined function + :) +declare function xbow:combine ($functions as function(*)*) as function(*) { + function ($initial as item()*) { + fold-left($functions, $initial, xbow:combination-reducer#2) + } }; -declare -function xbow:apply-as-last ($argument as item()*, $function as function(*), $other-arguments as array(*)) as item()* { - apply($function, array:append($other-arguments, $argument)) +declare %private function xbow:combination-reducer ($result as item()*, $next as function(*)) as item()* { + apply($next, xbow:spread($result, function-arity($next))) }; -(:~ - : combine a sequence of $functions and returns the combined function - :) -declare -function xbow:combine ($functions as function(*)*) as function(*) { - function ($initial as item()*) { - fold-left($functions, $initial, xbow:combination-reducer#2) - } -}; - -declare - %private -function xbow:combination-reducer ($result as item()*, $next as function(*)) as item()* { - apply($next, - xbow:spread($result, function-arity($next))) -}; - -declare - %private -function xbow:spread ($arguments as item()*, $arity as xs:integer) as array(*) { - if (count($arguments) < $arity) - then error( - xs:QName('xbow:not-enough-arguments'), - ``[Received `{count($arguments)}` argument(s) for a function with arity `{$arity}`]``) - else if ($arity = 1) - then [$arguments] - else array:join(( - [head($arguments)], - xbow:spread(tail($arguments), $arity - 1) - )) +declare %private function xbow:spread ($arguments as item()*, $arity as xs:integer) as array(*) { + if (count($arguments) < $arity) then + error( + xs:QName('xbow:not-enough-arguments'), + ``[Received `{count($arguments)}` argument(s) for a function with arity `{$arity}`]`` + ) + else if ($arity = 1) then + [$arguments] + else + array:join(([head($arguments)], xbow:spread(tail($arguments), $arity - 1))) }; (:~ : categorize all elements of $sequence by first matching rule in $rules :) -declare -function xbow:categorize ($sequence as item()*, $rules as array(function(*))) as function(*) { - let $test := xbow:find-first-matching($rules, ?) - let $zero := xbow:array-fill(array:size($rules), ()) - - return fold-left($sequence, $zero, function ($result as array(*), $item as item()) { - let $pos := $test($item) - - return - if ($pos eq 0) - then ($result) (: $item did not match any criteria :) - else (xbow:array-put($result, $pos, ($result($pos), $item))) - }) +declare function xbow:categorize ($sequence as item()*, $rules as array(function(*))) as function(*) { + let $test := xbow:find-first-matching($rules, ?) + let $zero := xbow:array-fill(array:size($rules), ()) + return fold-left( + $sequence, + $zero, + function ($result as array(*), $item as item()) { + let $pos := $test($item) + return if ($pos eq 0) then ( + $result + ) (: $item did not match any criteria :) else ( + xbow:array-put( + $result, + $pos, + ( + $result($pos), $item + ) + ) + ) + } + ) }; (:~ : spread all elements of $sequence over $scale using an $accessor function :) -declare -function xbow:categorize ($sequence as item()*, $rules as array(function(*)), $accessor as function(*)) as array(*) { - let $test := xbow:find-first-matching($rules, ?) - let $zero := xbow:array-fill(array:size($rules), ()) - - return fold-left($sequence, $zero, function ($result as array(*), $item as item()) { - let $pos := $test($accessor($item)) - - return - if ($pos eq 0) - then ($result) (: $item did not match any criteria :) - else (xbow:array-put($result, $pos, ($result($pos), $item))) - }) +declare function xbow:categorize ( + $sequence as item()*, + $rules as array(function(*)), + $accessor as function(*) +) as array(*) { + let $test := xbow:find-first-matching($rules, ?) + let $zero := xbow:array-fill(array:size($rules), ()) + return fold-left( + $sequence, + $zero, + function ($result as array(*), $item as item()) { + let $pos := $test($accessor($item)) + return if ($pos eq 0) then ( + $result + ) (: $item did not match any criteria :) else ( + xbow:array-put( + $result, + $pos, + ( + $result($pos), $item + ) + ) + ) + } + ) }; - (:~ : xquery implemention of a special array:put in xquery : fills elements of sparse arrays with empty sequences :) -declare -function xbow:array-put ($array as array(*), $pos as xs:integer, $items-to-put as item()*) as array(*) { - array:join(( - if (array:size($array) < $pos) - then ( - $array, - xbow:array-fill($pos - array:size($array) -1, ()), - [$items-to-put] - ) - else if (array:size($array) > $pos + 1) - then ( - array:subarray($array, 1, $pos -1), - [$items-to-put], - array:subarray($array, $pos + 1) - ) - else ( - array:subarray($array, 1, $pos -1), - [$items-to-put], - array:subarray($array, $pos + 1) - ) - )) +declare function xbow:array-put ($array as array(*), $pos as xs:integer, $items-to-put as item()*) as array(*) { + array:join( + if (array:size($array) < $pos) then ( + $array, + xbow:array-fill( + $pos - array:size($array) - 1, + ( + ) + ), + [$items-to-put] + ) else if (array:size($array) > $pos + 1) then ( + array:subarray($array, 1, $pos - 1), [$items-to-put], array:subarray($array, $pos + 1) + ) else ( + array:subarray($array, 1, $pos - 1), [$items-to-put], array:subarray($array, $pos + 1) + ) + ) }; (:~ : Return the last item in a sequence or array. : Will return an empty sequence if array or sequence is empty :) -declare -function xbow:last($array-or-sequence as item()*) as item()? { - typeswitch($array-or-sequence) - case array(*) - return xbow:last-member-of($array-or-sequence) - default - return xbow:last-item-of($array-or-sequence) +declare function xbow:last ($array-or-sequence as item()*) as item()? { + typeswitch ($array-or-sequence) + case array(*) return + xbow:last-member-of($array-or-sequence) + + default return + xbow:last-item-of($array-or-sequence) }; (:~ : Return the last item in a sequence. : Will return an empty sequence if sequence is empty :) -declare -function xbow:last-item-of($seq as item()*) as item()? { - if (count($seq)) - then ($seq[count($seq)]) - else () +declare function xbow:last-item-of ($seq as item()*) as item()? { + if (count($seq)) then ( + $seq[count($seq)] + ) else ( + ) }; (:~ : Return the last item in array. : Will return an empty sequence if array is empty :) -declare -function xbow:last-member-of($array as array(*)) as item()? { - if (array:size($array)) - then ($array(array:size($array))) - else () +declare function xbow:last-member-of ($array as array(*)) as item()? { + if (array:size($array)) then ( + $array(array:size($array)) + ) else ( + ) }; (:~ @@ -822,12 +931,15 @@ function xbow:last-member-of($array as array(*)) as item()? { Example: xbow:sequence-for-each-index((1,2,3), function ($i, $p) { $i + $p }) :) -declare -function xbow:sequence-for-each-index ($seq as item()*, $func as function(*)) as item()* { - fold-left($seq, [0, ()], function ($result as array(*), $next as item()) { - let $pos := $result?1 + 1 - return [$pos, ($result?2, $func($next, $pos))] - })?2 +declare function xbow:sequence-for-each-index ($seq as item()*, $func as function(*)) as item()* { + fold-left( + $seq, + [0, ()], + function ($result as array(*), $next as item()) { + let $pos := $result?1 + 1 + return [$pos, ($result?2, $func($next, $pos))] + } + )?2 }; (:~ @@ -837,12 +949,15 @@ function xbow:sequence-for-each-index ($seq as item()*, $func as function(*)) as Example: xbow:array-for-each-index([1,2,3], function ($i, $p) { $i + $p }) :) -declare -function xbow:array-for-each-index ($arr as array(*), $func as function(*)) as array(*) { - array:fold-left($arr, [0, []], function ($result as array(*), $next as item()*) { - let $next-pos := $result?1 + 1 - return [$next-pos, array:append($result?2, $func($next, $next-pos))] - })?2 +declare function xbow:array-for-each-index ($arr as array(*), $func as function(*)) as array(*) { + array:fold-left( + $arr, + [0, []], + function ($result as array(*), $next as item()*) { + let $next-pos := $result?1 + 1 + return [$next-pos, array:append($result?2, $func($next, $next-pos))] + } + )?2 }; (:~ @@ -853,13 +968,13 @@ function xbow:array-for-each-index ($arr as array(*), $func as function(*)) as a xbow:for-each-index((1,2,3), function ($i, $p) { $i + $p }) xbow:for-each-index([1,2,3], function ($i, $p) { $i + $p }) :) -declare -function xbow:for-each-index ($array-or-items as item()*, $func as function(*)) as item()* { - typeswitch ($array-or-items) - case array(*) - return xbow:array-for-each-index($array-or-items, $func) - default - return xbow:sequence-for-each-index($array-or-items, $func) +declare function xbow:for-each-index ($array-or-items as item()*, $func as function(*)) as item()* { + typeswitch ($array-or-items) + case array(*) return + xbow:array-for-each-index($array-or-items, $func) + + default return + xbow:sequence-for-each-index($array-or-items, $func) }; (:~ @@ -871,55 +986,67 @@ function xbow:for-each-index ($array-or-items as item()*, $func as function(*)) xbow:array-fill(4, ()), xbow:array-fill(4, function ($i, $p) { $i + $p }) :) -declare -function xbow:array-fill ($size as xs:integer, $function-or-value as item()?) as array(*) { - if ($size < 1) - then (error( - xs:QName('xbow:invalid-argument'), - "array size must be greater than zero")) - else ( - typeswitch ($function-or-value) - case function(*) - return xbow:array-for-each-index( - array { (1 to $size) }, $function-or-value) - default - (: we need an array to iterate over for [(),()] to be possible :) - return array:for-each( - array { (1 to $size) }, function ($ignore) { $function-or-value }) - ) -}; - -declare - %private -function xbow:match-first ($item as item(), $result as xs:integer+, $rule as function(*)) as xs:integer+ { - let $current-pos := head($result) + 1 - let $current-match := tail($result) - - return - if ($current-match > 0) - then $result (: did match, do nothing :) - else if ($rule($item)) - then ($current-pos, $current-pos) - else ($current-pos, $current-match) -}; - -declare - %private -function xbow:match-all ($item as item(), $result as xs:integer+, $rule as function(*)) as xs:integer+ { - let $current-pos := head($result) + 1 - let $current-match := tail($result) - - return - if ($rule($item)) - then ($current-pos, $current-pos) - else ($current-pos, $current-match) -}; - -declare - %private -function xbow:find-first-matching ($rules as array(*), $item as item()) as xs:integer { - array:fold-left($rules, (0, 0), xbow:match-first($item, ?, ?)) - => tail() +declare function xbow:array-fill ($size as xs:integer, $function-or-value as item()?) as array(*) { + if ($size < 1) then ( + error(xs:QName('xbow:invalid-argument'), 'array size must be greater than zero') + ) else ( + typeswitch ($function-or-value) + case function(*) return + xbow:array-for-each-index( + array{ + ( + 1 to $size + ) + }, + $function-or-value + ) + + default return (: we need an array to iterate over for [(),()] to be possible :) + array:for-each( + array{ + ( + 1 to $size + ) + }, + function ($ignore) { + $function-or-value + } + ) + ) +}; + +declare %private function xbow:match-first ( + $item as item(), + $result as xs:integer+, + $rule as function(*) +) as xs:integer+ { + let $current-pos := head($result) + 1 + let $current-match := tail($result) + return if ($current-match > 0) then + $result (: did match, do nothing :) + else if ($rule($item)) then ( + $current-pos, $current-pos + ) else ( + $current-pos, $current-match + ) +}; + +declare %private function xbow:match-all ( + $item as item(), + $result as xs:integer+, + $rule as function(*) +) as xs:integer+ { + let $current-pos := head($result) + 1 + let $current-match := tail($result) + return if ($rule($item)) then ( + $current-pos, $current-pos + ) else ( + $current-pos, $current-match + ) +}; + +declare %private function xbow:find-first-matching ($rules as array(*), $item as item()) as xs:integer { + array:fold-left($rules, (0, 0), xbow:match-first($item, ?, ?)) => tail() }; (:~ @@ -929,15 +1056,13 @@ function xbow:find-first-matching ($rules as array(*), $item as item()) as xs:in : 'label' (n-th item of the second array) : NOTE: both arrays must have the same size :) -declare -function xbow:label ($array as array(*), $labels as array(*)) as array(map(*)) { - array:for-each-pair($array, $labels, xbow:assign-label#2) +declare function xbow:label ($array as array(*), $labels as array(*)) as array(map(*)) { + array:for-each-pair($array, $labels, xbow:assign-label#2) }; -declare %private -function xbow:assign-label ($items as item()*, $label as xs:string) as map(xs:string, item()*) { - map { - 'items': $items, - 'label': $label - } +declare %private function xbow:assign-label ($items as item()*, $label as xs:string) as map(xs:string, item()*) { + map {'items': $items, 'label': $label} }; + + + diff --git a/src/examples/arrow-exclamation-mark.xq b/src/examples/arrow-exclamation-mark.xq index cc1fe0e..ff15006 100644 --- a/src/examples/arrow-exclamation-mark.xq +++ b/src/examples/arrow-exclamation-mark.xq @@ -1,35 +1,41 @@ -xquery version "3.1"; +xquery version '3.1'; -declare function local:add ($a, $b) { $a + $b }; +declare function local:add ($a, $b) { + $a + $b +}; declare function local:for-each-add ($s, $a) { - for-each($s, local:add($a, ?)) + for-each($s, local:add($a, ?)) }; -(0 to 9) -(: => (function ($a) { $a ! string(.) })():) - => string-join() - => (function ($a) { $a || "" })() - => string-to-codepoints() - => (function ($a) { $a ! (. + 1) })() - => sum() -, -(1 to 10) - => for-each(local:add(-1, ?)) -(: => for-each(string#1) :) - => string-join() - => concat("") - => string-to-codepoints() - => local:for-each-add(1) - => sum() -, -( - (1 to 10) - ! (. - 1) -(: ! string(.) :) - => string-join() - => concat("") - => string-to-codepoints() -) - ! (. + 1) - => sum() +(0 to 9) + (: => (function ($a) { $a ! string(.) })():) + => string-join() + => ( + function ($a) { + $a || '' + } + )() + => string-to-codepoints() + => ( + function ($a) { + $a!(. + 1) + } + )() + => sum(), + (1 to 10) + => for-each(local:add(-1, ?)) + (: => for-each(string#1) :) + => string-join() + => concat('') + => string-to-codepoints() + => local:for-each-add(1) + => sum(), + ( + (1 to 10)!(. - 1) + (: ! string(.) :) + => string-join() + => concat('') + => string-to-codepoints() + )!(. + 1) + => sum() \ No newline at end of file diff --git a/src/examples/categorize-activity.xq b/src/examples/categorize-activity.xq index fb691d8..9c91d6b 100644 --- a/src/examples/categorize-activity.xq +++ b/src/examples/categorize-activity.xq @@ -1,9 +1,9 @@ -xquery version "3.1"; +xquery version '3.1'; import module namespace xbow = 'http://line-o.de/xq/xbow'; -let $data := - +let $data := + @@ -18,11 +18,10 @@ let $data := - -let $activity-rules := [ xbow:lt(5), xbow:lt(20), xbow:ge(20) ] -let $activity-labels := [ 'inactive', 'active', 'hyperactive' ] -let $post-accessor := function ($i as element(person)) { xs:integer($i/@posts) } - -return $data/person - => xbow:categorize($activity-rules, $post-accessor) - => xbow:label($activity-labels) +let $activity-rules := [xbow:lt(5), xbow:lt(20), xbow:ge(20)] +let $activity-labels := ['inactive', 'active', 'hyperactive'] +let $post-accessor := + function ($i as element(person)) { + xs:integer($i/@posts) + } +return $data/person => xbow:categorize($activity-rules, $post-accessor) => xbow:label($activity-labels) \ No newline at end of file diff --git a/src/examples/categorize.xq b/src/examples/categorize.xq index 75fd5de..1665eee 100644 --- a/src/examples/categorize.xq +++ b/src/examples/categorize.xq @@ -1,80 +1,55 @@ -xquery version "3.1"; - +xquery version '3.1'; import module namespace xbow = 'http://line-o.de/xq/xbow'; -let $age-rules := [ - xbow:lt(10), - xbow:lt(20), - xbow:lt(30), - xbow:lt(60), - xbow:ge(60) -] - -let $age-labels := [ - 'minors', - 'youngsters', - 'twens', - 'adults', - 'seniors' -] - -let $age-accessor := function ($i as map(*)) { $i?age } - -let $activity-rules := [ - xbow:lt(5), - xbow:lt(20), - xbow:ge(20) -] - -let $activity-labels := [ - 'inactive', - 'active', - 'hyperactive' -] - -let $post-accessor := function ($i as element(person)) { xs:integer($i/@posts) } - +let $age-rules := [xbow:lt(10), xbow:lt(20), xbow:lt(30), xbow:lt(60), xbow:ge(60)] +let $age-labels := ['minors', 'youngsters', 'twens', 'adults', 'seniors'] +let $age-accessor := + function ($i as map(*)) { + $i?age + } +let $activity-rules := [xbow:lt(5), xbow:lt(20), xbow:ge(20)] +let $activity-labels := ['inactive', 'active', 'hyperactive'] +let $post-accessor := + function ($i as element(person)) { + xs:integer($i/@posts) + } return ( - xbow:categorize((1, 3, 4, 5, 6, 7, 8, 9, 9, 0, 34, 45, 65), $age-rules), - xbow:categorize((1, 3, 4, 5, 6, 7, 8, 9, 9, 0, 34, 45, 65), $activity-rules), - (1, 3, 4, 5, 6, 7, 8, 9, 9, 0, 34, 45, 65) - => xbow:categorize($age-rules) - => xbow:label($age-labels) - , - ( - map { "age": 1, "name": "a" }, - map { "age": 3, "name": "b" }, - map { "age": 4, "name": "c" }, - map { "age": 5, "name": "d" }, - map { "age": 6, "name": "e" }, - map { "age": 7, "name": "f" }, - map { "age": 8, "name": "g" }, - map { "age": 9, "name": "h" }, - map { "age": 9, "name": "i" }, - map { "age": 17, "name": "j" }, - map { "age": 34, "name": "k" }, - map { "age": 45, "name": "l" }, - map { "age": 54, "name": "m" } - ) - => xbow:categorize($age-rules, $age-accessor) - => xbow:label($age-labels) - , - ( - , - , - , - , - , - , - , - , - , - , - , - , - - ) - => xbow:categorize($activity-rules, $post-accessor) - => xbow:label($activity-labels) -) + xbow:categorize((1, 3, 4, 5, 6, 7, 8, 9, 9, 0, 34, 45, 65), $age-rules), + xbow:categorize((1, 3, 4, 5, 6, 7, 8, 9, 9, 0, 34, 45, 65), $activity-rules), + (1, 3, 4, 5, 6, 7, 8, 9, 9, 0, 34, 45, 65) => xbow:categorize($age-rules) => xbow:label($age-labels), + ( + map {'age': 1, 'name': 'a'}, + map {'age': 3, 'name': 'b'}, + map {'age': 4, 'name': 'c'}, + map {'age': 5, 'name': 'd'}, + map {'age': 6, 'name': 'e'}, + map {'age': 7, 'name': 'f'}, + map {'age': 8, 'name': 'g'}, + map {'age': 9, 'name': 'h'}, + map {'age': 9, 'name': 'i'}, + map {'age': 17, 'name': 'j'}, + map {'age': 34, 'name': 'k'}, + map {'age': 45, 'name': 'l'}, + map {'age': 54, 'name': 'm'} + ) + => xbow:categorize($age-rules, $age-accessor) + => xbow:label($age-labels), + ( + , + , + , + , + , + , + , + , + , + , + , + , + + ) + => xbow:categorize($activity-rules, $post-accessor) + => xbow:label($activity-labels) + ) \ No newline at end of file diff --git a/src/examples/combine.xq b/src/examples/combine.xq index 7910ec8..9d74a6f 100644 --- a/src/examples/combine.xq +++ b/src/examples/combine.xq @@ -1,35 +1,51 @@ -xquery version "3.1"; - +xquery version '3.1'; import module namespace xbow = 'http://line-o.de/xq/xbow'; -declare -function local:from-to ($from as xs:integer, $to as xs:integer) as xs:integer+ { - ($from to $to) +declare function local:from-to ($from as xs:integer, $to as xs:integer) as xs:integer+ { + ($from to $to) }; ( - xbow:combine(( - function ($n) { (1, $n) }, - local:from-to#2, - sum#1, - function ($n) { map { 'value': $n } } - ))(10), - xbow:combine(( - local:from-to#2, - sum#1, - function ($n) { map { 'value': $n } } - ))((1, 10)), - xbow:combine(( - sum#1, - function ($n) { $n + 1 } - ))((2, 3)), - xbow:combine(( - array:filter(?, function ($n) { $n > 0 }), - xbow:to-sequence(?) - ))([1, 19, -1]), - xbow:combine(( - sum#1, - local:from-to(1, ?) - ))((1 to 10)) + xbow:combine( + ( + function ($n) { + (1, $n) + }, + local:from-to#2, + sum#1, + function ($n) { + map {'value': $n} + } + ) + )(10), + xbow:combine( + ( + local:from-to#2, + sum#1, + function ($n) { + map {'value': $n} + } + ) + )((1, 10)), + xbow:combine( + ( + sum#1, + function ($n) { + $n + 1 + } + ) + )((2, 3)), + xbow:combine( + ( + array:filter( + ?, + function ($n) { + $n > 0 + } + ), + xbow:to-sequence(?) + ) + )([1, 19, -1]), + xbow:combine((sum#1, local:from-to(1, ?)))((1 to 10)) ) \ No newline at end of file diff --git a/src/examples/copy-collection-contents.xq b/src/examples/copy-collection-contents.xq index a49b054..e826d53 100644 --- a/src/examples/copy-collection-contents.xq +++ b/src/examples/copy-collection-contents.xq @@ -1,42 +1,41 @@ -xquery version "3.1"; +xquery version '3.1'; declare function local:copy-collection-contents ($source, $target) { - xmldb:get-child-resources($source) - => for-each(xmldb:copy-resource($source, ?, $target, ?)) - , - xmldb:get-child-collections($source) - => for-each(concat($source, "/", ?)) - => for-each(xmldb:copy-collection(?, $target)) + xmldb:get-child-resources($source) => for-each(xmldb:copy-resource($source, ?, $target, ?)), + xmldb:get-child-collections($source) + => for-each(concat($source, '/', ?)) + => for-each(xmldb:copy-collection(?, $target)) }; declare function local:copy-collection-contents-and-check ($source, $target) as xs:boolean { - xmldb:get-child-resources($source) - => fold-left(true(), function ($result, $next) { - let $action := xmldb:copy-resource($source, $next, $target, $next) - return $result and exists($action) - }) - - and - - xmldb:get-child-collections($source) - => for-each(concat($source, "/", ?)) - => fold-left(true(), function ($result, $next) { - let $action := xmldb:copy-collection($next, $target) - return $result and exists($action) - }) + xmldb:get-child-resources($source) + => fold-left( + true(), + function ($result, $next) { + let $action := xmldb:copy-resource($source, $next, $target, $next) + return $result and exists($action) + } + ) and + xmldb:get-child-collections($source) + => for-each(concat($source, '/', ?)) + => fold-left( + true(), + function ($result, $next) { + let $action := xmldb:copy-collection($next, $target) + return $result and exists($action) + } + ) }; -if (local:copy-collection-contents-and-check("/db/a", "/db/b")) -then "OK" -else "FAIL" - -(: create /db/a :) +if (local:copy-collection-contents-and-check('/db/a', '/db/b')) then + 'OK' + else + 'FAIL', + (: create /db/a :) (: create /db/a/a.xml :) (: create /db/a/aa :) (: create /db/a/aa/aa.xml :) (: create /db/a/ab :) (: create /db/a/ab/ab.xml :) -local:copy-collection-contents("/db/a", "/db/b") - -(: check contents of b :) \ No newline at end of file + local:copy-collection-contents('/db/a', '/db/b') (: check contents of b :) \ No newline at end of file diff --git a/src/examples/dynamic-path.xq b/src/examples/dynamic-path.xq index 3f8624b..e6d279f 100644 --- a/src/examples/dynamic-path.xq +++ b/src/examples/dynamic-path.xq @@ -1,29 +1,15 @@ -xquery version "3.1"; - +xquery version '3.1'; import module namespace xbow = 'http://line-o.de/xq/xbow'; - -declare variable $xml := - +declare variable $xml := some text - -; - + ; ( - $xml - => xbow:pluck('@b') - => data(), - $xml - => xbow:pluck('b') - => xbow:pluck('@d') - => data(), - $xml - => xbow:pluck('b/@d') - => string(), - $xml - => xbow:pluck('./b/../b/@d') - => string() + $xml => xbow:pluck('@b') => data(), + $xml => xbow:pluck('b') => xbow:pluck('@d') => data(), + $xml => xbow:pluck('b/@d') => string(), + $xml => xbow:pluck('./b/../b/@d') => string() ) \ No newline at end of file diff --git a/src/examples/example.xq b/src/examples/example.xq index acd7a2b..9e1d77c 100644 --- a/src/examples/example.xq +++ b/src/examples/example.xq @@ -1,27 +1,32 @@ -xquery version "3.1"; +xquery version '3.1'; -import module namespace xbow="http://line-o.de/xq/xbow"; +import module namespace xbow = 'http://line-o.de/xq/xbow'; (: using functions from external modules :) (0 to 9) - => for-each(math:pow(?, 2)) - - (: convert :) - => for-each(xs:string#1) - => for-each(xs:integer#1) - => for-each(xbow:to-array#1) - => for-each(xbow:to-sequence#1) - - (: filter by using a function returning a function :) - => filter(xbow:gt(10)) - - (: all four lines below do the same thing, choose the one that fits you :) - => reverse() - => sort((), function ($a) { -$a }) - => xbow:sortBy(function ($a) { -$a }) - => xbow:ascending() - - (: group by even and odd :) + => for-each(math:pow(?, 2)) + (: convert :) + => for-each(xs:string#1) + => for-each(xs:integer#1) + => for-each(xbow:to-array#1) + => for-each(xbow:to-sequence#1) + (: filter by using a function returning a function :) + => filter(xbow:gt(10)) + (: all four lines below do the same thing, choose the one that fits you :) + => reverse() + => sort( + (), + function ($a) { + -$a + } + ) + => xbow:sortBy( + function ($a) { + -$a + } + ) + => xbow:ascending() + (: group by even and odd :) (: => fold-left([], function ($result, $next) {:) (: let $rem := ($next mod 2):) @@ -33,16 +38,10 @@ import module namespace xbow="http://line-o.de/xq/xbow"; (: let $field := if ($next mod 2) then ('odd') else ('even'):) (: return map:put($result, $field, ($result($field), $next)):) (: }) :) - => xbow:groupBy(xbow:even-odd#1) - - (: get a key from a map :) - => xbow:pluck('even') - => sum() - (: returns 116 :) -, -(: return the first item in the reversed sequence as an integer :) -('1', '3', '2') - => reverse() - => xbow:take(1) - => xs:integer() - (: returns 2 :) + => xbow:groupBy(xbow:even-odd#1) + (: get a key from a map :) + => xbow:pluck('even') + => sum(), + (: returns 116 :) + (: return the first item in the reversed sequence as an integer :) + ('1', '3', '2') => reverse() => xbow:take(1) => xs:integer() (: returns 2 :) \ No newline at end of file diff --git a/src/examples/for-each-index-array-fill.xq b/src/examples/for-each-index-array-fill.xq index f41c976..654d83d 100644 --- a/src/examples/for-each-index-array-fill.xq +++ b/src/examples/for-each-index-array-fill.xq @@ -1,21 +1,23 @@ -xquery version "3.1"; +xquery version '3.1'; -import module namespace xbow = "http://line-o.de/xq/xbow"; +import module namespace xbow = 'http://line-o.de/xq/xbow'; -declare -function local:position-minus-item ($item as xs:integer, $position as xs:integer) as xs:integer { - $position - $item +declare function local:position-minus-item ($item as xs:integer, $position as xs:integer) as xs:integer { + $position - $item }; -declare -function local:lt-position-squared ($item as xs:integer, $position as xs:integer) as function(*) { - xbow:lt($position * $position) +declare function local:lt-position-squared ($item as xs:integer, $position as xs:integer) as function(*) { + xbow:lt($position * $position) }; (: for-each-index examples with sequence and array :) xbow:for-each-index((0 to 4), local:position-minus-item#2), -xbow:for-each-index(array { (0 to 4) }, local:position-minus-item#2), - -(: array-fill examples with constant value and callback function :) -xbow:array-fill(4, true()), -xbow:array-fill(4, local:lt-position-squared#2) + xbow:for-each-index( + array{ + (0 to 4) + }, + local:position-minus-item#2 + ), + (: array-fill examples with constant value and callback function :) + xbow:array-fill(4, true()), + xbow:array-fill(4, local:lt-position-squared#2) \ No newline at end of file diff --git a/src/examples/group-even-odd.xq b/src/examples/group-even-odd.xq index ef5f95e..c559111 100644 --- a/src/examples/group-even-odd.xq +++ b/src/examples/group-even-odd.xq @@ -1,41 +1,43 @@ -xquery version "3.1"; +xquery version '3.1'; -import module namespace xbow="http://line-o.de/xq/xbow"; +import module namespace xbow = 'http://line-o.de/xq/xbow'; (:~ : the shortest form to group by even and odd : the output will have numerical keys ~:) -declare -function local:even-odd-with-numerical-keys ($item as xs:numeric) as xs:integer { - $item mod 2 +declare function local:even-odd-with-numerical-keys ($item as xs:numeric) as xs:integer { + $item mod 2 }; (: group by even and odd using a user provided function :) (0 to 9) => xbow:groupBy(local:even-odd-with-numerical-keys#1), -(: group by even and odd using the module function :) -(0 to 9) => xbow:groupBy(xbow:even-odd#1), -(: group by even and odd using the sum of each array :) -([0,1,2], [3,4,5], [6,7,8], [9]) - => xbow:groupBy(xbow:even-odd#1, - function ($array as array(*)) { $array?* => sum() }), -