Thank you for this really useful article, there is some great information here.

FYI: I get consistently slower performance with the 'for' loop variation here (around 10% slower) so at least in my simple test the while loop both looks nicer and runs faster.

Much better, the main page request is down to 1.0s and total load time is 1.7s which while still slow is no where near as bad as >6s, thanks.

The MAK4540 fix was approved for porting to 2016.1.1 and all later releases.

I fully agree with hoisting constants out of a loop and have recently spent a while optimizing code to use $listnext in SQL and so agree it is a much faster way to iterate over $listbuild structures.

However in your first case of a 'For' loop the end condition is evaluated when entering the loop the first time and is not re-evaluated at all, for example run this:

CACHE20164:USER>set a=2 for i=1:1:a { set a=10 write i,! }
1
2

As you can see it always stops at '2' rather than going on to '10'.

Also there is overhead in converting from a delimited string into a $list format in order to use the more efficient $listnext, you can avoid the O(n^2) overhead with the regular $piece(string,",",i) code in a loop using $find with a starting position and then $extract the item you need. This should perform better than $listnext version of the loop at least for mid sized strings as it avoids the conversion overhead.

The use of ZZW was a mistake and we removed this in the next release after it was introduced.

I did not see any documentation that said that 'ZZ' was reserved for any particular use and the examples in the documentation show functions that do not use 'ZZ' as part of their name so I was trying to avoid user extensions in naming the item 'ZZPRINT' by assuming we can use 'ZZ' and customers will use 'Z<something else>'. I apologize if this caused a problem for you, that was the opposite of my intension.

I would generally advise against using %File class for reading files as this is a very low level wrapper around the COS file commands. For example if you want to apply a translate table you need to know about the 'K' flag on the open command. I much prefer using the %Stream.FileBinary or %Stream.FileCharacter classes as these provide a much more consistent interface to the file.

I often do this too, I think this sort of pattern is a good way to make the error handling simple and consistent.

The problem with this is I believe they do not want the object saved into the database at all. It seams like a worthwhile enhancement that export to XML could optionally call %ValidateObject on the objects as it walks the tree.