Hans-Jurgen,
Thank you for your detailed help. This really helped me to understand what I was doing (as opposed to what I was trying to do).
Based on your detailed comments and the following usage notes on fold-left from Priscilla Walmsley's XQuery book
"This function performs an operation (the function $f ) on two items at a time, accu‐ mulating a result as it goes. It first calls the function using $zero as the first argument and the first item in $seq as the second argument. It then calls it a second time using the result of the previous function call as the first argument, and the second item in $seq as the second argument. It continues until there are no further items in $seq ."
I figured out that I reversed the two parameters in the function call, and based on that also reversed the ordering in the first argument of the fold-left. The following (note the reversal of arguments in local:stand-totaal($obj, $stand) and in the first argument of `fold-left`) gives me the desired result:
``` let $stand1 := fold-left(($obj1, $obj2) , (), function($stand, $obj) { local:stand-totaal($obj, $stand) }) let $stand2 := fold-left(($obj2, $obj3) , (), function($stand, $obj) { local:stand-totaal($obj, $stand) }) let $stand3 := fold-left(($obj1, $obj2, $obj3) , (), function($stand, $obj) { local:stand-totaal($obj, $stand) })
return ( '1 <-> 2 ==================', $stand1, '2 <-> 3 ==================', $stand2, '1 <-> 2 <-> 3 ============', $stand3 ) ```
From your expectations I gather that you want to exclude later reuse
of an ID possessed by an object with status "beeindigen". Therefore I suggest the following simple solution of the problem:
Actually, that is not the case. Later reuse must be possible.
Thank you all for the help, MArco
On 19-12-2023 11:23, Hans-Juergen Rennau wrote:
Hi Marco,
I've also taken a look at the code and I think the observed behaviour is in accordance with the logic of the accumulator function (local:stand-totaal), while this logic is probably not really what. First - why do you get the result which you get?
(1) The logic of local:stand-totaal (a) Accept the new item only if its ID is not found among the accumulated items (before filtering these for the status, see b)) (b) Retain only those accumulated items which do not have a certain status
The input sequence is objects 3, 2, 1 (1) Process object 3: Object accepted, as the accumulator is still empty, so the object ID is "new"; the fact that the new object has a <status> element is ignored. (2) Process object 2: The object is rejected, as its ID is found in the accumulator; the accumulator is then filtered, discarding object 3 because of its status; result: the accumulator is again empty (nothing added, and what was there has been removed) (3) Process object 1: The object is accepted, as the accumulator is again empty, so the item ID is "new"
From your expectations I gather that you want to exclude later reuse of an ID possessed by an object with status "beeindigen". Therefore I suggest the following simple solution of the problem: (a) Extract all IDs of an object with that status (b) Before fold-left, filter the sequence of objects, discarding any object with such an ID (c) Process the filtered sequence, not thinking about the status any more, just checking the ID
This processing is best encapsulated in a function (e.g. update-stand()).
With kind regards, Hans-Jürgen
PS: Code snippet for the suggestion:
declare function local:update-stand($objects as element()*) as element()* { let $idsIGN := $objects[.//*:status = 'beëindigen']//*:identificatie => distinct-values() let $objectsF := $objects[not(.//*:identificatie = $idsIGN)] return fold-left($objectsF, (), local:stand-totaal#2) }; declare function local:stand-totaal (: returns an object by comparing new to old :) (: newest should be returned, except when ow:statusbeëindigen</ow:status> then no object should be returned :) ($new as item()*, $old as item()*) as item()* { let $new_ids := $new//*:identificatie => distinct-values() return ($new, $old[not(.//*:identificatie = $new_ids)]) };
Am Dienstag, 19. Dezember 2023 um 10:38:49 MEZ hat Martin Honnen martin.honnen@gmx.de Folgendes geschrieben:
On 19/12/2023 09:53, Marco Duiker - LandGoed wrote:
Please help me with the following problem:
I try to construct the current status of a series of objects along the following simple rules:
- the current status of on object with a certain `identificatie` (id) is the newest version of that object
- except when the newest object has the property `<status>beëindigen</status>` then the object stops existing.
I use a fold-left to proces these rules with a simple function implementing those rules. This gives me unexpected results.
I've reduced the problem to a single stand alone query in which the last object (`obj3`) has the property `<status>beëindigen</status>`.
So I would expect this line: `let $stand4 := fold-left(($obj3, $obj2, $obj1), (), function($stand, $obj) { local:stand-totaal($stand, $obj) })` to give me an empty result as `obj3`has the property <status>beëindigen</status> but I am getting `obj1` as demonstrated in the following stand alone query.
When running the stand alone query I would *expect*:
declare function local:stand-totaal (: returns an object by comparing new to old :) (: newest should be returned, except when ow:statusbeëindigen</ow:status> then no object should be returned :) ($new as item()*, $old as item()*) as item()* {
let $new_ids := local:id($new) let $stand_deel1 := for $obj_oud in $old//*:owObject where not(local:id($obj_oud) = $new_ids) return sl:stand{ $obj_oud }</sl:stand> let $stand_deel2 := for $obj_new in $new//*:owObject[not(.//*:status)] return sl:stand{ $obj_new }</sl:stand>
return ($stand_deel1, $stand_deel2) };
From your comment and explanation I kind of would expect a check for that particular value
ow:statusbeëindigen</ow:status>
but that value is not checked for or mentioned at all in the XQuery code.