If you haven't already heard--or tried it for yourself--LabVIEW 2017 offers a simple but powerful new language feature that definitely warrants a deeper look.
Somehow, I made it all the way to the CLA Summit in Austin--having used LabVIEW 2017 for months--before learning about this. Obviously I neglected to scan the LabVIEW 2017 Features and Changes list. At the very least, this new feature addresses the common tedium of making typed polymorphic APIs. It also potentially addresses a design problem I've been banging my head on for months. (A little more on that later.)
What is a Malleable VI?
For starters, check out the link above to the LabVIEW 2017 new features page. It covers the basics of Malleable VIs quite thoroughly. It turns out, that the strict typing of data wires in LabVIEW, and the abundant polymorphism in the IDE, permit the compiler to make some pretty powerful (i.e. time-saving) assumptions. Let's consider a simple scenario:
The thing I never wondered until learning about malleable VIs is, why?
Make a Malleable VI
In case you were too busy to read the LabVIEW 2017 features and changes list linked above, here is a comprehensive list of instructions for converting a standard VI to a malleable VI:
In my world these attributes are more often helpful than harmful. Is it good that LabVIEW doesn't treat every VI as malleable? Sure. On the flip side, the behavior exists if you want it, and with only the tiniest effort. Edit-time polymorphism now traverses VI boundaries!
What's the performance penalty for this compiler sorcery? As far as I can tell, absolutely none--and this makes complete sense. There should be no performance difference at run-time. The malleable VI is still called statically (in fact, it is inlined) and the compiler checks and adapts type(s) at edit-time. If you did something silly, like try to add strings inside a malleable math VI, you'll get a broken wire.
Goodbye (Most) POLY VIs
This all felt immediately relevant to me because I just recently spun my own polymorphic array functions (in LabVIEW 2015) for Promote and Demote element. I figured I would do it right and make both functions polymorphic so I could reuse these simple widgets in other projects. After a bunch of tedious tinkering, typing, and testing, I had two polymorphic selector VIs, 26 typed instance VIs, and one big annoying compromise--properly handle only my most common data types.
Polymorphic selector VI for Promote Element:
And the disk footprint for both functions:
With malleable VIs, there is no polymorphic selector VI, and the footprint shrinks to:
Not only is this far easier to write, maintain, and test--it also handles types I chose not to support because I needed to draw the line somewhere. (I originally added that dirty polymorphic variant instance to handle the types I wasn't willing to code explicitly.)
In this slick new world, the only thing that matters is whether the input types play nicely with the subVIs and primitives inside the malleable VI. All array element types work just fine, and I only wrote one VI for each behavior (Promote, Demote). Ladies and gentlemen, I think we have a winner.
But surely this requires some new syntax, terminal type, or something?
I made my VI icon background orange because that's NI's convention with the new malleable VIs added to the palettes. It was simply a style choice.
I used variants for my malleable array type because they imply "wire anything!" It actually doesn't matter--I could have used input/output arrays of DBL, I32, String, etc.. Setting the VI as malleable tells the compiler to reconcile types at edit time--and it does!
The Future, Service Pack 1
At the CLA Summit, we got a quick preview of the malleable VI behavior coming in LV2017 Service Pack 1, and that's when I got really jazzed. SP1 malleable VIs will include a form of dynamic dispatch that allows classes to implement non-ancestor methods. GET OUT.
For months, I have worked on a home-cooked solution to object-oriented interfaces (the capital "I" interfaces that exist in other languages). After lots of deep thinking, kludgy demo code, and wheel-spinning, I had no good solution that provided clean, composition-based, functionality (probably because it was impossible). No harm in thinking big.
...But combine malleability with object-oriented dynamic dispatch (i.e. run-time polymorphism) and you suddenly have a powerful non-hierarchical way of designing classes. If I'm thrilled with the prospect of (almost) never again writing a polymorphic VI, I'm borderline giddy over this interface possibility. I can hardly wait to try some cleaner (and 100% kludge-free) design patterns with the release of LV2017 SP1. Stay tuned.
Ethan Stern is a Managing Partner at Composed Systems and is a Certified LabVIEW Architect, Certified LabVIEW Embedded Developer, Certified TestStand Developer, NI Certified Professional Instructor, and a certifiable LabVIEW geek.