The Polymath Variant
When you learn a programming language, within the first three lessons you know how to declare a variable, and the most common data types you'll use in that language. After a while, you usually get to discover the "super" data type of the language: void* in C, Object in C# or Java. You can basically store whatever data type you'd like in that "thing" so it can adapt to multiple situations and calls. In LabVIEW, we have variants.
Because their content can vary (woohoo, minds were blown). However, there is so much more to variants than most people care to imagine. A variant isn't just a shell or a bucket that you can fill with any possible data type. But before going beyond this, we have to look at the structure of a variant:
First of all, a variant is primarily made of 2 fields : the type descriptor, and the value. The TD is the ID card of the variant: it tells what the variant contains. It's like the label on your jar so you know you're dealing with wine and not grape fruit. It gives exactly enough information to be able to fully retrieve the value (like the type of a reference or a class, the size of each dimension in an array...). The value is, heh, the actual value that was hiding inside the variant.
Then, comes the dark side of the variant: its attributes. That part people ignore, mostly because it's optional, and because its assets and replaceable by using more usual functions. Yes, one can live without variant attributes. I know some LabVIEW Architects that have never used them, usually because they don't know what they're good at (sometimes because they don't know they exist), except giving an additional description to the data inside the variant.
With variant attributes, you can:
- Describe data (metadata)
- Store data as a dictionary or keyed array
- Organize data
- Efficiently search for data
- Create recursive data structures
Variant attributes come with 3 simple functions that lie in the Cluster->Variant palette : Set, Get, Delete. An attribute is named. And an attribute can be anything, it's actually a variant! From these rules, it's quite easy to understand how to describe data (e.g. I have a numeric data and want to add its maximum value and its timestamp, so I'd call Set Variant Attribute twice :
Because attributes are named, they're unique. Call "Set" with an existing name, and it's going to be replaced (you can tell with the Replaced? output of the function). It's super powerful for creating array cousins that strictly exclude duplicates, so no more need to double check if there's an existing entry in your list/array before inserting it.
If we start looking at variant attributes as an array, we should be able to perform basic operations on it, like searching. Using the Search 1D Array primitive on a regular array results in a O(n) performance. Using the "Get Variant Attribute" function to look for a specific attribute is a O(log(n)). It means that for a 1-million elements array, it'll take 1 million times more time to find the last element than the first, versus 6 times with variant attributes. You can find more information here.
Least but not last, I wrote earlier that variant attributes values are variants. It should not take long before realizing that we have a wonderful recursion here! Variant attributes can have their own variant attributes and et caetera. You can then form a tree, adopt parents/children terms and build your own API to store recursive/layered structures. For instance, you could build a variant that stores TDMS file information (a TDMS file is a layered structure File/Groups/Channels with metadata associated with each layer - seems like we have some similar traits here...).
To preserve your sanity and the length of this post chose not to illustrate variant attributes powers here, but if that's something you'd like to see in the next posts, let me know in the comments!
Edit: Props to Sam T. who righteously pointed out an excellent illustration of how to use variants and variant attributes: LabVIEW Containers, created by Chris Cilino a few years ago. Will publish a more personal example soon :)