LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
JackDunaway

Officially Support "Coerce to Type"

Status: Completed

The Coerce To Type function is supported in LabVIEW 2018 and later. It is available in Quick Drop, and in the Functions > Numeric > Conversion subpalette.

This is written as both an Idea and as a Community Nugget.

 

Did you know there exists a function that decreases code fragility when it comes to typecasting and type converting datatypes? It's called 'Coerce to Type', and I bet you've never heard of this function unless you have kept up with this conversation. Thanks to RandyP for creating that Idea which culminated in a 'public' release of the Coerce to Type function.

 

21195iD087EF25489F6CED

 

Since that post, I have become aware of potential risks/bugs I had been proliferating in my coding style. First, I will briefly describe my understanding of the difference between typecasting and typeconverting in the context of LabVIEW. Next, I'll show a few use cases where this node increases code robustness. Finally, it's up to you to Kudos this Idea so we get Coerce to Type officially supported and in the palette!

 

Simply, "type converting" preserves the value of a wire, and "typecasting" preserves the raw bits that express that value on a wire. These two concepts are not interchangeable - they perform distinctly different data transfer functions (which is why they show up on two separate subpalettes: "Numeric>>Conversion" and "Numeric>>Data Manipulation"). Then there's this new function: Coerce to Type. I think of it as a Coerce-Cast combo. The data input is first Coerced to the datatype harvested from the top input, and then it is typecasted to that type.

 

Dynamic event registration is sensitive to the name on the wire, and for documentation's sake it has historically been important to typecast the event source ref to achieve a good name. Well, typecasting refs can get you into trouble (ask Ben), especially if you change the source control type while forgetting to update your "pretty name" ref constant.

 

21187iA83D4F02211D2DCB

 

My next favorite example is when you need to coerce a numeric datatype into an enum. Sometimes it's impossible to control the source datatype of an integer, while it's desirable to typecast the value into an enum for self-documented syntax inside your app. 

 

For instance, take the "standard" integer datatype in LabVIEW - I32 - and cast it to an enum. You're going to get some unexpected results (assuming, you expected the *value* to be preserved). Consider the following scenario:

 

  1. You desire to typecast a plain integer '2' into an enum {Zero, One, Two, Three}, and after 45 minutes of debugging, realize "Typecasting" has hacked off 75% of the bits and clobbered the value. Drats!
  2. The enterprising engineer you are, you determine how to fix the problem with a deftly-placed "Coerce to U8". (This is one of the fragile errors I proliferated prior to learning about this node)
  3. Maniacal manager/customer comes along and says "I want that enum to count to 10k". Drats again. A datatype change from U8 to U16 for the typedef'd enum, and a lot of typing with the wretched enum editor. Finally, two hours into testing and wondering why the program doesn't work, you realize you also forgot to replace all of the Type Converts to U16 (this is the definition of fragile code: you change one thing, and another thing(s) breaks).
  4. Rockstar Programmer Epiphany: use Coerce to Type, bask in your robust code. You even enjoy data value preservation from floating point numbers.
21191iD3339D40A531F181
 
Finally, typecasting can generate mysterious failure modes at Run-Time, but Coerce to Type can catch errors at Design Time. This is especially helpful for references (see above), but can also prevent some boneheaded data gymnastics (see below). Whew! Saved by compiler type resolution mismatch!
 
21193iC698E122C5BE16AC
 
In short, now that you realize you need this function, I hope you will want to see it added to the Data Manip palette.
 
Penultimate note: Coerce to Type is neither a replacement for typecast nor any of the type converts!!! There are distinct scenarios appropriate for each of the three concepts.
Ultimate note: please check the comments section, because I expect you'll find corrections to my terminology/concepts from GregR, et al.
14 Comments
Jim_Kring
Trusted Enthusiast

Hey Jack: I usually just use the Variant to Data function.  I think, but am not 100% sure, that it's equivalent to the Coerce to Type function. (BTW, it was great seeing you at NIWeek.)

LabBEAN
Active Participant

Hi Jack, two quick notes:

 

1) You can name User Events by adding a label to your numeric constant.  When you change the label name, the Event Structure will reflect the new User Event name.  No type cast(s) or coerce to type(s) needed.

 

2) You can feed an I32, U8, DBL, etc. constant directly to an Enum without coercing first.  You will get a coercion dot, but as Christian has demonstrated, there are cases where this is actually faster than "converting".  (Coercion in this way also prevents you from trying to typecast a string to an enum.)  Is coerce to type faster than wiring an I32 » Enum with a coercion dot?


Certified LabVIEW Architect
TestScript: Free Python/LabVIEW Connector

One global to rule them all,
One double-click to find them,
One interface to bring them all
and in the panel bind them.
LabBEAN
Active Participant

To add to what Jack explained:

 

Numerical conversion nodes change the *type* as specified AND manipulate the *bits* in memory such that input wire value is preserved.  That said, data types have limits (you cannot convert -1 to a U8 nor can you convert 256 to a U8 since U8s are bounded from 0 to 255).

 

Type Cast nodes change the *type* as specified but do not touch the *bits*.  Certain numbers can be converted this way [e.g. 1 (U16) » I16], but most cannot [e.g. 1 (U16) » U32].  Type Casting can be great for casting numbers to enums in (e.g. LabVIEW Core 1 and 2 simple state machines) or anything to string (e.g. sending it to another application with TCP and then casting it back on the other side).

 

The reason that I point this out is that, as easy as LabVIEW makes programming for us engineers, there are limits.  Fear of engineer programming ignorance is not a good reason to keep something off of an advanced palette, but I guess I'm not seeing the benefit for this function in the use cases you listed.

 

A coerce to type node seems like a way to eliminate the coercion dot between numbers and enums (which, when you're trying to optimize for speed, can be accomplished *faster* with a type cast, right?).  Are there other benefits? 

 

Why do I have the sneaking suspicion that I'm about to learn something 😄


Certified LabVIEW Architect
TestScript: Free Python/LabVIEW Connector

One global to rule them all,
One double-click to find them,
One interface to bring them all
and in the panel bind them.
LabBEAN
Active Participant

For my own sanity, I had put together a VI to demonstrate which datatypes would cast and which would not.  U16 » I16 casted okay (until we exceed the limit for I16) but that was the only case:

 

21249iAB1D8D78ED74EAE4


Certified LabVIEW Architect
TestScript: Free Python/LabVIEW Connector

One global to rule them all,
One double-click to find them,
One interface to bring them all
and in the panel bind them.
ASInc
Member

Seeing this Coerce to Type bullet show up makes me wonder:  How many more features like it are sitting in the RTE/Dev Environment not on any palette that we can get to?  I'm betting that this is by no means the only tidbit thats hiding in the woodwork.  We came up with valid uses for this one, I wonder what else is out there that the collective mind could think up a valid use for.

Albert.Geven
Trusted Enthusiast

Hi

 

I prefer a simple warning from the compiler when a typecast acts between two types that have a different memory usage.

Typecasting between two types that occupy the same amount of memory is safe (no bits got lost or added)

But typecasting between different memorysizes should be warned by an excalmation mark (preferably in red) in the typecast function.

 

By the way typecasting is fast because the compiler only sees the same memory in a different way, no copying needed!

greetings from the Netherlands
AristosQueue (NI)
NI Employee (retired)

> Seeing this Coerce to Type bullet show up makes me wonder:  How many more features like it are sitting

> in the RTE/Dev Environment not on any palette that we can get to?  I'm betting that this is by no means

> the only tidbit thats hiding in the woodwork.  We came up with valid uses for this one, I wonder what

> else is out there that the collective mind could think up a valid use for.

 

To the best of my knowledge, there is only one other magic secret primitive node that has not been released publicly at this point, and that one has a public counterpart that actually works better, but we had to keep the old one because we had some NI-written toolkits that used the old one. Two years ago, there were several private primitives, but I think they're all out now. I could be wrong, but I think this is the only one remaining. Now, that's not to say we won't develop more. It isn't uncommon for us to develop a new prim and keep it private for a release or two to make sure it has all the kinks worked out. But nothing else is hiding at the moment.

JackDunaway
Trusted Enthusiast

 


@Jim Kring wrote:

Hey Jack: I usually just use the Variant to Data function.  I think, but am not 100% sure, that it's equivalent to the Coerce to Type function. (BTW, it was great seeing you at NIWeek.)


 

From a little bit of testing, yes, these functions appear to behave the same (thanks, learned something new), and perhaps Coerce to Type is merely a wrapper for Variant to Data (???). Two reasons I would prefer Coerce to Type over Variant to Data: 1) If one is trying to type convert and cast a piece of data to a new piece of data, it's not readily evident that a Variant operation should be used. A more coherent Coerce to Type would be more intuitive, and 2) Coerce to Type doesn't currently suffer from a superiority complex 😄 (Re: NIWeek - Likewise!)

 

 


@LabBEAN wrote:

1) You can name User Events by adding a label to your numeric constant. 

2) You can feed an I32, U8, DBL, etc. constant directly to an Enum without coercing first.  You will get a coercion dot, but as Christian has demonstrated, there are cases where this is actually faster than "converting".


 

Good points, but here are two scenarios where those won't work:

1. If the User Event Ref is not created by harvesting datatype from a BD constant, but rather a wire whose source you cannot control. A specific example involves a central data server where client VI's in the same application instance can subscribe to data. Rather than having several cases in the client's Event Handler structure that all say <Subscribed Data Event>, you can provide descriptive names. Simply: sometimes one is justified renaming a wire for readability, and this does not only apply to references.

2. Yes, sometimes implicit casting is faster (I remember the post from Christian). But what if you want to feed the data into a Case Selector? Another boon, if you type convert an out-of-range integer into an enum, it "rails out" at the largest enum value, which can be exploited as a catch-all. You're right, sometimes conversion is not necessary, but when it is, there's not a more robust solution than Coerce to Type.

 


@Aristos Queue wrote:
To the best of my knowledge, there is only one other magic secret primitive node that has not been released publicly at this point...


<digression>

Presumably, you're not referring to the new primitive Randomize 1D Array, which could be considered at this time "super-secret" classification given the low volume of users who have discovered that thread. But like I said in the thread, the randomize function itself is marginally exciting, while the "Chameleon VI" framework is revolutionary in terms of polymorphism. I would urge someone who is better-versed than I in polymorphism to create a new Idea as an attempt to get this framework prioritized on R&D's release schedule. Currently, I avoid creating polymorphic VIs because of the design-time hassle and the maintenance shortcoming of propagating bugfixes to all instances. As Wikipedia harshly states, LabVIEW's current method of generating polymorphic VIs is a symptom of "an insufficiently expressive development environment"... ouch!

</digression>

AristosQueue (NI)
NI Employee (retired)

> Presumably, you're not referring to the new primitive Randomize 1D Array,

 

That's a VI, not a built-in node. We were talking about built-in nodes. If we're talking about partially complete features that are being tried out for future release, there are always three or four of those. And don't bother adding that chameleon ability to the idea exchange. It's being worked on, but we're years away from having anything we could release.

tst
Knight of NI Knight of NI
Knight of NI

> And don't bother adding that chameleon ability to the idea exchange. It's being worked on, but we're years away from having anything we could release.

 

 

And it already exists - http://forums.ni.com/t5/LabVIEW-Idea-Exchange/Provide-a-better-way-to-implement-a-polymorphic-VI/idi...


___________________
Try to take over the world!