module namespace set = "http://qt4cg.org/atomic-set"; (: This package defines a type set:atomic-set which represents a set of distinct atomic items. Atomic items are considered distinct based on the comparison function fn:atomic-equal. An instance of an atomic set can be constructed using a function call such as set:build((1, 3, 5, 7, 9)). If $A and $B are instances of set:atomic-set, then they can be manipulated using methods including: $A=?>size() - returns the number of items in the set $A=?>empty() - returns true if the set is empty $A=?>contains($k) - determines whether $k is a member of the set $A=?>contains-all($B) - returns true if $B is a subset of $A $A=?>values() - returns the items in $A, as a sequence $A=?>add($k) - returns a new atomic set containing an additional item $A=?>remove($k) - returns a new atomic set in which the given item is absent $A=?>union($B) - returns a new atomic set holding the union of $A and $B $A=?>intersect($B) - returns a new atomic set holding the intersection of $A and $B $A=?>except($B) - returns a new atomic set holding the difference of $A and $B :) declare %public record set:atomic-set ( _data as map(xs:anyAtomicType, xs:boolean), size as fn($set as set:atomic-set) as xs:integer, empty as fn($set as set:atomic-set) as xs:boolean, contains as fn($set as set:atomic-set, $value as xs:anyAtomicType) as xs:boolean, contains-all as fn($set as set:atomic-set, $value as set:atomic-set) as xs:boolean, add as fn($set as set:atomic-set, $item as xs:anyAtomicType) as set:atomic-set, remove as fn($set as set:atomic-set, $item as xs:anyAtomicType) as set:atomic-set, union as fn($set as set:atomic-set, $value as set:atomic-set) as set:atomic-set, intersect as fn($set as set:atomic-set, $value as set:atomic-set) as set:atomic-set, except as fn($set as set:atomic-set, $value as set:atomic-set) as set:atomic-set, * ); declare %private variable DATA := "'_data'"; (: The private function set:replaceData processes the internal map by applying a supplied function, and returns a new atomic set with the resulting internal map :) declare %private function set:replaceData ( $input as set:atomic-set, $update as fn(map(*)) as map(*)) as map(xs:anyAtomicType, xs:boolean) { map:put($input, $DATA, $update($input?$DATA)) } declare %public function set:build ( $values as xs:anyAtomicType* := ()) { { _data: map:build($values, values:=true#0, {'duplicates': 'use-first'}), size: fn($set as set:atomic-set) as xs:integer { map:size($set?$DATA) }, empty: fn($set as set:atomic-set) as xs:boolean { map:empty($set?$DATA) }, contains: fn($set as set:atomic-set, $value as xs:anyAtomicType) as xs:boolean { map:contains($set?$DATA, $value) }, contains-all: fn($set as set:atomic-set, $other as set:atomic-set) as xs:boolean { every($other, map:contains($set?$DATA, ?)) }, values: fn($set as set:atomic-set) as xs:anyAtomicType* { keys($set?$DATA) }, add: fn($set as set:atomic-set, $value as xs:anyAtomicType) as xs:anyAtomicType* { set:replaceData($set, map:put(?, $value, true())) }, remove: fn($set as set:atomic-set, $value as xs:anyAtomicType) as xs:anyAtomicType* { set:replaceData($set, map:remove(?, $value)) }, union: fn($set as set:atomic-set, $other as set:atomic-set) as set:atomic-set { set:replaceData($set, fn($this) {map:merge(($this, $other?$DATA), {'duplicates': 'use-first'})}) }, intersect: fn($set as set:atomic-set, $other as set:atomic-set) as set:atomic-set { set:replaceData($set, map:filter(?, $other?contains)) }, except: fn($set as set:atomic-set, $other as set:atomic-set) as set:atomic-set { set:replaceData($set, map:remove(?, $other?values())) } } };