ForAll Loops and Type Mismatches
There are always challenges when moving from something familiar to something similar but different. When you've been working with that "something familiar" for a very long time, some things become second nature. But when you move to "something similar but different", sooner or later you hit an error and become convinced it's not working like it used to. This is even more probable if enhancements mean you more frequently come across a specific paradigm. The rash developer starts throwing accusations, assuming they must be right because they have years of experience on their side. The wise developer double-checks first...and may find out that they were mistaken.
The Problem
When you have a great developer on your team, they improve on the past. Processing collections is one such place where Bob Balaban improved VoltScript. Every Domino database has business logic or data processing agents that loops through collections. Every developer knows the paradigm:
Dim coll as NotesDocumentCollection
Dim doc as NotesDocument
Set doc = coll.getFirstDocument()
While Not doc Is Nothing
...
Set doc = coll.getNextDocument(doc)
Wend
Every LotusScript developer, at some time or another, has written this kind of loop and forgotten the highlighted line and caused an infinite loop. The wise developer will type the highlighted line first when they write a loop. Some may even have leveraged IDE functionality to store snippets for the whole While
loop, to speed up their development.
But when we started with VoltScript, we wanted to prevent this kind of problem. There are ways that's easy to set up. If you have a Variant array - or a function returns a Variant array - you can use a ForAll
loop. This can also be done on Lists.
The most common data collection we will iterate in VoltScript is probably a JsonObject (which can be a JSON object or a JSON array), using JsonObject.getChildren()
. But sooner or later you want to pass the ForAll reference variable (the current element in the container) to a function, something like this:
When coding this in VoltScript, the compiler frequently complained, giving me a Type Mismatch
error for the call to testValue()
. The solution was simple:
Dim temp as JsonObject
ForAll elem in jsonObj.getChildren()
Set temp = elem
Call testValue(temp)
End ForAll
Comparisons with Other Languages
This is consistent with what we have to do in Java. In Java, the syntax for casting the variable to a specific Class can be done inline:
But the variable still needs to be cast to the derived class, if the method being called does not take the generic class or the generic class does not have the method to be called.
LotusScript
But when developing VoltScript, I've been conscious to try to avoid introducing more verbose syntax that is not consistent with LotusScript development. This felt unusual compared to my experience of LotusScript development. But was this perception or reality? I created a ticket to investigate whether this is different to LotusScript.
Writing something comparable to the JsonObject.getChildren() ForAll loop proved less straightforward. As mentioned, NotesDocumentCollection and NotesViewEntryCollection cannot be iterated by a ForAll loop. The same is the case for more recent classes like NotesJsonObject. Fortunately, I was able to find one pretty quickly.
ForAll itm in doc.Items
Call printName(itm)
End ForAll
Sub printName(item as NotesItem)
Print item.name
End Sub
This confirmed we had not introduced a regression in VoltScript. LotusScript also gave the Type Mismatch
error that VoltScript had given. What others might have called a "bug" was merely a mistaken expectation because we challenged the paradigm, broke from the getFirst...
and getNext...
approach and increased the number of places where ForAll loops could be used in VoltScript.
Conclusion
Is the required syntax ideal? Maybe not.
Is there a better, easy-to-code solution? Maybe we could add a global function to JsonVSE called castToJsonObject(incoming as Variant)
. But will this be intuitive to people who have not looked at the full API doc for JsonVSE? Probably not. And would it easier than the solution I used? Probably not.
Is the Type Mismatch
error obvious on what to do to solve it? Maybe not. So I plan on updating the API doc sample code and the How Tos, ready for our next release.
But the million-dollar question is, are there better problems for us to fix. Absolutely!