Jump to content
John Lokanis

Magical variant to data? Or bug?

Recommended Posts

One of my minions is working thought the online Core3 course and showed me some code that made no sense to me. I am wondering it this is a bug or some little known feature.

In the code, he was told to wire a variant to the 'variant to data' function and wire in a path constant so the output would be a path. This was later wired to a function needing a path input. So far so good. But later in the same code (in a different case) he was instructed to do the same thing but this time there was no input to the 'variant to data' function to tell it what to cast the variant data to. But for some reason, the output was still a path and he could still wire it to another function that needed a path as input. Here is a screen grab of the magical code:

post-2411-0-51093000-1348769082.png

So, what is going on here? Bug?

Share this post


Link to post
Share on other sites

My vote is bug, but I've never seen this.

Is it possible for you to post the VI? I'm curious to see if this works with other data types or somehow just is convinced a path is wired to the missing Type terminal.

I guess theoretically this could be a feature, if all of the sink nodes are the same data type. But since NI hasn't done it yet I'm guessing it is a difficult feature to implement, but I would love to have a polymorphic VI change it's type based on an output that's needed, as well as its input.

Share this post


Link to post
Share on other sites

I've been using that little trick for years. I could take either side of the debate, but as a user I lean towards not having to define the output data.

  • Like 1

Share this post


Link to post
Share on other sites

My gut says "BAD. Prone to abuse." I'm going with my gut on this one.

What if the required output type changes, and it's way downstream? You won't get an error until you run. This should be a development-time error, not a run-time one.

(Also, anything that AQ calls "magical" scares me :) )

Edited by jaegen

Share this post


Link to post
Share on other sites

+1 for "bug". Recently read an article entitled "Coffeescript: less writing, bad readability" where the consensus is that explicit is better than implicit when comparing Coffeescript (implicit syntax) vs Javascript (explicit syntax), and the same principles seem to apply here.

Share this post


Link to post
Share on other sites

Well given that this 'trick/feature' was used in the Core3 materials and WAS NOT EXPLAINED, it is going to lead to misuse and abuse. When my coworker asked me to explain it, I could not and told him he was right to think this was bad form. I prefer any such operation to be explicit. The implicit nature of this will lead to confusing bugs in the future.

Share this post


Link to post
Share on other sites

Well given that this 'trick/feature' was used in the Core3 materials and WAS NOT EXPLAINED, it is going to lead to misuse and abuse. When my coworker asked me to explain it, I could not and told him he was right to think this was bad form. I prefer any such operation to be explicit. The implicit nature of this will lead to confusing bugs in the future.

So I understand the abuse side of things for sure, but anything can be abused right? If there is proper documentation, and training (which it sounds like there isn't) then I don't see anything wrong with this feature.

Should every polymorphic VI not have the "Automatic" option when choosing the type based on the inputs? Should we have to be explicit about that as well? What about Data To Variant, should I have to tell it, hey this is a string and you should convert from string to Variant. I understand this example is weak given that it is a primitive and accepts all data types.

Share this post


Link to post
Share on other sites

So I understand the abuse side of things for sure, but anything can be abused right?

On the "abusable" spectrum, this ranks more toward the "asking for problems" side. :P

Should every polymorphic VI not have the "Automatic" option when choosing the type based on the inputs?

That's a little different, since it's downstream vs. upstream type propagation, and sources-to-sinks is one-to-many.

Share this post


Link to post
Share on other sites

That's a little different, since it's downstream vs. upstream type propagation, and sources-to-sinks is one-to-many.

I agree so I'll just post what I'm thinking.

I want this functionality for my own code so I can use (and likely abuse) it.

Edited by hooovahh
  • Like 1

Share this post


Link to post
Share on other sites

Feature. That kind of magical backpropagation is rare in LV but a few nodes have implemented it. There's a lot of internal debate about how good an idea it is. Myself, I would rather the type terminal be a required input.

Another thought on this matter: a broken run-arrow is your friend; the mentality of "avoid the broken run-arrow" to justify language features feels flawed (think: "auto-insert feedback node into cycles").

A broken run-arrow and strong, explicit typing is like a friendly heads-up at compile-time saying "you did it wrong". Compare this to the insidious manifestation of a run-time error, or even worse, unexplained or quirky behavior with no error, inadvertently introduced by automatic code mutations. The compiler constantly validates all syntax (yay!), whereas run-time, it's not so easy to exercise every execution path to flush out the bugs.

  • Like 1

Share this post


Link to post
Share on other sites

But this is different from the usual arguments for strict typing: the wire is strictly typed. And what other type could you have picked? Path doesn't convert to anything else.

Share this post


Link to post
Share on other sites

I didn't know you could do that, neat.

I don't see the problem though. I'm assuming you'd get an error if the other side of the sink couldn't resolve to a static type (polymorphic VI, an input that adapts to type, or an object)?

Share this post


Link to post
Share on other sites

Although this "feature" is kind of cool, I believe the usage is a bit limited.

What I do find magical about this function, however, is the following construct. Before discovering this trick I wrote a lot of unnecessary for loops.

post-26690-0-26316600-1348802032.png

Edited by Darin
  • Like 1

Share this post


Link to post
Share on other sites

What I do find magical about this function, however, is the following construct. Before discovering this trick I wrote a lot of unnecessary for loops.

I love this trick. Related to this, Variant to Data will also convert a variant that contains an array into an array of variants, which is sometimes useful.

Personally I think the compiler should infer (or propagate) types as much as possible, so I don't see it as a bug. There's always a risk of passing an incompatible type when using variants - it's the price of using a non-specified type in a strongly-typed language - and it's the programmer's responsibilty to manage that risk. This doesn't prevent you from wiring the type input, if you want that check at compile-time, it just makes it optional for those situations where you don't need it and don't want extra constants on the block diagram.

Share this post


Link to post
Share on other sites

I agree with Jack.

I think it is a feature that should not have been implemented. From the point of human performance and error prevention it is horrible.

Share this post


Link to post
Share on other sites

I agree so I'll just post what I'm thinking.

I want this functionality for my own code so I can use (and likely abuse) it.

Well almost two years later and guess what, I have found how to replicate this functionality, and abuse it to my liking.  I just submitted a code repository for a Variant Repository which is basically reading and writing variant attributes with some added functionality.  The read function has the ability to look at the data type that the output is wired to, and change the type to that.  

 

Doing this was relatively easy using XNodes and the Adapt To Inputs ability.  It gets the reference to the output terminal, then gets the reference to the sink location of the wired tied to it, then gets the data type of that terminal.  It will default to a Variant if it has issues in this operation.  The performance of using this is basically nothing because all it does in my case, is change the type of a constant on the block diagram of my XNode.

Share this post


Link to post
Share on other sites

Well almost two years later and guess what, I have found how to replicate this functionality, and abuse it to my liking.  I just submitted a code repository for a Variant Repository which is basically reading and writing variant attributes with some added functionality.  The read function has the ability to look at the data type that the output is wired to, and change the type to that.  

 

Doing this was relatively easy using XNodes and the Adapt To Inputs ability.  It gets the reference to the output terminal, then gets the reference to the sink location of the wired tied to it, then gets the data type of that terminal.  It will default to a Variant if it has issues in this operation.  The performance of using this is basically nothing because all it does in my case, is change the type of a constant on the block diagram of my XNode.

 

Did you mean to add "penalty" or something there?

Also, I decided to give this a try myself. Here's an XNode I made that's basically the type cast function, only it implements the behavior described in the thread. (I actually got the idea to do this in an XNode before I noticed hooovahh's post; maybe he hadn't posted it yet.) A couple warnings though: one, I haven't tested it that much, and two, it uses a private method in the GenerateCode ability to create a constant of a given type. No idea why this method is private; I don't see any problems using it can cause, but I'm warning you because I imagine it's marked private for a reason.

 

Also, if you right-click it, there's an option to replace it with a regular typecast node along with a constant of the proper type.

 

Auto Typecast.zip

Edited by flarn2006
  • Like 1

Share this post


Link to post
Share on other sites

Although this "feature" is kind of cool, I believe the usage is a bit limited.

What I do find magical about this function, however, is the following construct. Before discovering this trick I wrote a lot of unnecessary for loops.

attachicon.gifVariantToArray.png

 

This is not the same thing. Variant to Data can very well deal with arrays and even clusters as long as the data structure inside the variant is actually compatible. That doesn't even mean it needs to be exactly the same. LabVIEW will happily convert numerics and timestamps, etc inside the variant, into strings. It will only joke on fundamentally incompatible elements and some that are debatable if it should still attempt a conversion.

 

On the other hand, the conversion from timestamp to string, or floating point to string for instance will use the platform specific formatting rules (system setting dependent). That is often not what one wants when it's meant for more than just display purposes. But LabVIEW hasn't a runtime mind reading interface (yet) :D .

 

As to the original topic, I'm not sure I like it. The lazy dog in me says: sure it's fine! but the purist prefers explicit type definition for such things. Call Library Node is another function that also does attempt back propagation of types for "Adapt to Type" terminal, but this usually fails as soon as there is any structure border in between. And it can indeed cause nasty problems if one changes the datatype of a control downstream the wire without even a warning indication of a change to the Call Library Node configuration and suddenly the application crashes nastily.

Share this post


Link to post
Share on other sites

Did you mean to add "penalty" or something there?

Yeah that's what I meant.  There is no run-time penalty, because at development time is when the constant is made.

 

 

Also, I decided to give this a try myself. Here's an XNode I made that's basically the type cast function, only it implements the behavior described in the thread. (I actually got the idea to do this in an XNode before I noticed hooovahh's post; maybe he hadn't posted it yet.) A couple warnings though: one, I haven't tested it that much, and two, it uses a private method in the GenerateCode ability to create a constant of a given type. No idea why this method is private; I don't see any problems using it can cause, but I'm warning you because I imagine it's marked private for a reason.

Yup this is similar to the Variant Repository I posted.  Not sure why that method is private either but I couldn't find a better way to make a constant.  Your code does also fall short if there is no data associated with the sink yet.  I know you said you didn't test it much so that's fine, but you don't handle if you wire the output to the tunnel of a case structure for example.  The data becomes void, and you get an error popup.  My implementation looks for error and defaults to a variant data type if one is seen in the process of finding the sink data type.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.