So Here's Why I Hate LotusScript
Oct 29, 2011, 1:44 PM
For the most part, writing agents in LotusScript is the best way to go (at least when it can't be done in formula language), mostly for smoothness of interaction with the built-in libraries (no
.recycle()) and because it's less prone to running into memory problems when other agents go wonky than Java agents are. That doesn't mean I have to like it, though.
If there's one thing that drives me nuts about LotusScript more than any other aspect, it's its handling of arrays. This came to the fore with one of my recent projects, which involves spitting out the contents of a view, which in turn entails lots of use of
entry.ColumnValues. My first, quick-and-dirty draft ran into an early performance issue, which is that every call of
.ColumnValues on a NotesViewEntry seems to be as expensive as the first, meaning that the class doesn't do any internal cacheing and has to re-fetch it every time. Ugh, fine - I'll just assign the value to a new variable at the start:
Dim colValues as Variant
colValues = entry.ColumnValues
Not too bad - two extra lines at the start of a loop is a small price to pay for a significant speed improvement. Unfortunately, it doesn't work - it throws a Type Mismatch error at runtime. After doing a
entry.ColumnValues, I saw that it considers it "VARIANT( )", an array of Variants, which makes sense. It's a bit weird, since I've stored arrays in Variants before, but whatever - with a quick code adjustment, we're off to the races:
Dim colValues() as Variant
colValues = entry.ColumnValues
Great! Now hit Ctrl-S and... compiler error. You're not allowed to assign to the entirety of an array like that. Argh! So I guess I'm going to have to make my new array manually and loop through the original to copy each entry over individually. If you're familiar with another scripting language, that probably sounds like a simple task, but LotusScript's array annoyances continue. Because this is like BASIC, you can't just do "
colValues.add(something)" - you have to
ReDim the array to the right size. Here's the code I ended up with:
Dim columnValues() As Variant
ReDim columnValues(-1 To -1)
ForAll columnValue In entry.ColumnValues
If UBound(columnValues) = -1 Then
ReDim columnValues(0 To 0)
ReDim Preserve columnValues(0 To UBound(columnValues)+1)
columnValues(UBound(columnValues)) = columnValue
Before you look at that "-1 to -1" crap and deem me insane, hear me out. Though the NotesViewEntry doesn't cache its property value, the
ForAll loop does, meaning that, according to the profiler,
ColumnValues is only called once for each view entry, which is about as efficient as it gets. All that extra crap about
ReDim'ing the array over and over instead of just once is essentially "free" compared to the expense of the product object call, so it ends up being completely worth it.
Swence - Jul 20, 2012, 5:17 PM
You just narrated all the frustration I have had today. Thank you for this explanation! Saved me a lot of headache.
Sjef - Apr 26, 2021, 4:26 PM
Aaaaand... we're 10 years later and LotusScript is still compatible with itself! Drat...