|
Derar Novice
Joined: 09 Sep 2006 Posts: 44
|
Posted: Mon Aug 02, 2010 7:32 pm
[3.22] #FORALL, %ismember, and %del(n)item... internal indexing issue? |
So I try not to say "bug" unless I feel like I can point to what exactly I think is causing it.
Frankly, this stumps me completely.
Code: |
<var name="TestSorted" type="StringList" copy="yes">
<value>20|12|10|10|10|5|5|2</value>
<json>[20,12,10,10,10,5,5,2]</json>
</var>
<var name="TestList" type="StringList" copy="yes">
<value>10|10|2|20|5|12|10|5</value>
<json>[10,10,2,20,5,12,10,5]</json>
</var>
<alias name="RunTest" copy="yes">
<value>
$sorted = %1
$unsorted = %2
#SHOW "$sorted: " %json($sorted)
#SHOW "$unsorted: " %json($unsorted)
#FORALL ($sorted) {
$pos = %ismember(%repeatnum, $unsorted)
#SHOW %repeatnum " is " $pos " in " %json($unsorted)
$unsorted = %delnitem($unsorted, $pos)
}
</value>
</alias>
|
Execute: RunTest @TestSorted @TestList
Output:
Code: |
$sorted: [20,12,10,10,10,5,5,2]
$unsorted: [10,10,2,20,5,12,10,5]
20 is 4 in [10,10,2,20,5,12,10,5]
12 is 5 in [10,10,2,5,12,10,5]
10 is 1 in [10,10,2,5,10,5]
10 is 1 in [10,2,5,10,5]
10 is 1 in [2,5,10,5]
5 is 1 in [5,10,5]
5 is 1 in [10,5]
2 is 0 in [5]
|
Now, if you're missing it, the third time it hits 10, the whole thing flies off the handle because %ismember stops returning the correct index. This is the simplest posting example of what happens, but I've done some other testing with it as well, such as...
- Using all string values instead of number values. Result is the same.
- Echoing a raw %ismember in the loop to see if $pos just got stuck; the %ismember matches the $pos output
- Using %delitem(%repeatnum, $unsorted) instead of %delnitem($unsorted, $pos); same result.
- Changing the order of the unsorted list, or removing the tripled value of 10 (went to 30|20|12|10|10|5|5|2); still started screwing up after a few iterations
- Using the actual variables in the loop instead of local copies; same result
Now, what does make it work, is creating my own ismember function and substituting it in place of %ismember in the alias loop:
Code: |
<func name="_ismember" id="5">
<value>
$item = %1
$list = %2
#RETURN %ismember($item, $list)
</value>
</func>
|
Running it then outputs properly:
Code: |
$sorted: [20,12,10,10,10,5,5,2]
$unsorted: [10,10,2,20,5,12,10,5]
20 is 4 in [10,10,2,20,5,12,10,5]
12 is 5 in [10,10,2,5,12,10,5]
10 is 1 in [10,10,2,5,10,5]
10 is 1 in [10,2,5,10,5]
10 is 3 in [2,5,10,5]
5 is 2 in [2,5,5]
5 is 2 in [2,5]
2 is 1 in [2]
|
So it seems like somewhere in there, the delete item call screws up and I guess doesn't update the list index properly? But passing the list out to a user function to obtain the value creates a list copy with a proper index, I guess.
But... something's not right. :) |
|
|
|
Zugg MASTER
Joined: 25 Sep 2000 Posts: 23379 Location: Colorado, USA
|
Posted: Tue Aug 03, 2010 4:52 pm |
Yep, definitely a bug somewhere. As you say, it looks like the internal index isn't getting updated properly by %delnitem.
The reason your user function works is that CMUD is making a copy of the lists (when you assign $item=%1) and that causes CMUD to recompute the internal index cache for $item.
Added to bug list. Good catch!
P.S. Thanks for the excellent procedure for reproducing this. This is a very good example of an excellent bug report. |
|
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|