"belltown" wrote:
From my reading of the documentation, in the context of arrays and lists, Invalid is not a thing; it represents the absence of a thing.
Oh,
invalid is very much a thing. It is the
intentional omission of a thing. Rather, the
absence of a thing is `<UNINITIALIZED>` of type "<uninitialized>"^. Not only is `invalid` a thing but it has all kind of strange properties of a singularity (like division by zero :mrgreen:). For example,
invalid has a counterpart "nuclear particle" - the <Component: roInvalid> instance of the "roInvalid" class. And invalid == roInvalid (the two compare favorably). Plus
invalid sometimes autoboxes (e.g. getInterface(invalid, "ifString") ) and sometimes does not (e.g. (invalid).toStr() ), just to keep you on your toes.
In an array, Invalid is used to represent "an array element that has never been set". Invalid is used when "there is no object to return".
Kinda. Although half-ace-d, through insufficient design and not deep foresight. Look at Lua if you want to see consistent implementation of the concept of the Nothing - in Lua all unassigned variables's value is `nil`. Trying to access table value for missing key returns `nil` - but moreover,
assigning `nil` - i.e. myDict['someKey'] = nil - actually erases the slot, as if it was never set. In B/S, assigning
invalid does not remove the key-value pair, i.e. the .doesExist() predicate still returns true.
This btw, not to be confused with yet another kind of "no object to return" - the "function X as void" with "empty RETURN" :lol:
Many of the ifArray and ifList methods (Push, Pop, RemoveHead, RemoveTail, etc.) return Invalid if "the array is empty" or "end of list reached".
So what the documentation would have me believe is that you're not supposed to be able to treat Invalid as a thing that can be stored in a list item. From the list of APIs you mentioned, I couldn't come up with an example where Invalid could be returned in a list item. I'm curious if you came up with an example,
Brightscript Debugger> ? parseJson("[1, null, 2]")
<Component: roArray> =
[
1
invalid
2
]
This will break if one starts processing the result from JSON parse with the methods you mention. Which serves to demonstrate a koan from the humorous "Zen of Python": "Special cases aren't special enough to break the rules."
... or have a particular use case for this.
I have a particular use case for this indeed. I am laboring over a test framework, in which i have to enumerate all elements of a collection - be it array, list, dictionary or... <gasp> roSgNode. Without prejudice if invalid/roInvalid is one of the members or not. That's why i was looking at the different ways to enumerate collections. And no, not all of them implement
ifEnum - cases in point roXmlList and roSgNode.
However ... There's nothing to stop you from pushing Invalid into one of your own lists, and since roList implements ifArray, which "supports the array operator[]", I don't see why they "cannot be enumerated over with [ ]", if that's what you want to do; i.e. why the need for GetIndex() in the first place.
That sounds fine and dandy... until you realize that roXMLList, roAssociativeArray, roSgNode do not implement
ifArrayGet, i.e. numeric indexing.
Furthermore, even though Invalid is returned when the end of the list is reached, it appears that it is indeed possible to Pop() a "genuine invalid element" that is inside the list, and continue to Pop() the remaining non-Invalid elements; in this case, if you allow Invalid elements in the list, you'd have to use Count() to ensure the list is empty, rather than testing for Invalid.
That actually would work, yes - i thought of that, a counter-intuitive combo of
iList .count()/resetIndex()/getIndex(). Please read carefully what i said - i warned that naive enumerating `while getIndex() <> invalid` would exit prematurely on collections containing `invalid`. I have no question how to enumerate my collections - i found another way
(^) and that is assignable between variables (i.e. a=1: ? a: a = UNINITIALIZED: ? a), so yes - <UNINITIALIZED> is also a
thing... but entirely
another thing. I'd argue assigning <UNINITIALIZED> to something should never pass by silently, never ever - including as argument in function calls or return value. It beggars belief otherwise, the need of existence of <UNINITIALIZED> != invalid... but that's yet another topic
🙂