John Lokanis Posted September 27, 2012 Report Posted September 27, 2012 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: So, what is going on here? Bug? Quote
hooovahh Posted September 27, 2012 Report Posted September 27, 2012 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. Quote
drjdpowell Posted September 27, 2012 Report Posted September 27, 2012 It’s adapting to the type of the control it’s connected to, which I did not know it could do. Quote
Popular Post Aristos Queue Posted September 27, 2012 Popular Post Report Posted September 27, 2012 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. 6 Quote
crossrulz Posted September 27, 2012 Report Posted September 27, 2012 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. 1 Quote
jaegen Posted September 27, 2012 Report Posted September 27, 2012 (edited) 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 September 27, 2012 by jaegen Quote
JackDunaway Posted September 27, 2012 Report Posted September 27, 2012 +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. Quote
John Lokanis Posted September 27, 2012 Author Report Posted September 27, 2012 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. Quote
hooovahh Posted September 27, 2012 Report Posted September 27, 2012 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. Quote
JackDunaway Posted September 27, 2012 Report Posted September 27, 2012 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. 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. Quote
hooovahh Posted September 27, 2012 Report Posted September 27, 2012 (edited) 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 September 27, 2012 by hooovahh 1 Quote
JackDunaway Posted September 27, 2012 Report Posted September 27, 2012 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. 1 Quote
Aristos Queue Posted September 28, 2012 Report Posted September 28, 2012 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. Quote
mje Posted September 28, 2012 Report Posted September 28, 2012 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)? Quote
Darin Posted September 28, 2012 Report Posted September 28, 2012 (edited) 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. Edited September 28, 2012 by Darin 1 Quote
ShaunR Posted September 28, 2012 Report Posted September 28, 2012 (edited) This is what I've always wanted it to do. Edited September 28, 2012 by ShaunR Quote
Popular Post JackDunaway Posted September 28, 2012 Popular Post Report Posted September 28, 2012 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. Here's the scenario to create a bug: change the interface of the VI with banner "Files" and wired enum "Save Cues" to have a string filepath instead of a Filepath filepath (perhaps not the best example... consider changing say a DBL to a U32). Yet that change was not propagated back to the message sender, whatever is stuffing that queue. Now, you've got a bug that manifests itself as a run-time bug. Whereas, if the Variant to Data had the Filepath wired as its type, that case structure above would have broken when the "Files" VI ConPane was changed. Sure, you could change the Variant to Data type within that case and still forget to change the message senders, but since you're in the domain of changing message datatypes, you're much more likely to remember to change the senders also. Whereas, in the current implementation above, a change to the ConPane of the "Files" VI might not necessarily trigger the correct synapses in your brain to also change your message datatypes. I guess in a nutshell it just simplifies the mental ruleset and memory stack size required of developers when you're able to depend on the broken run arrow and compiler messages. And that probably means fewer possibilities for creating bugs. 3 Quote
Popular Post mike_spacex Posted September 28, 2012 Popular Post Report Posted September 28, 2012 (edited) But this is different from the usual arguments for strict typing: the wire is strictly typed. While I agree 100% with this, I'm still on the fence. If there's a 'type' input, my personal preference is to be explicit and wire it up. But, then again, the fewer replacements I have to make if I change types later, the better. When it comes to remembering to modify the data originator, a broken run arrow in the receiver won't help my brain synapses work any better unfortunately. So, rather than vote bug or no-bug, I'd rather just push for consistency; Either give me the "magic" everywhere, or none at all. The inconsistency can definitely be cause for confusion: Edited September 28, 2012 by mike_nrao 3 Quote
ned Posted September 28, 2012 Report Posted September 28, 2012 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. Quote
Stagg54 Posted October 22, 2012 Report Posted October 22, 2012 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. Quote
hooovahh Posted September 4, 2014 Report Posted September 4, 2014 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. Quote
Sparkette Posted September 4, 2014 Report Posted September 4, 2014 (edited) 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 September 5, 2014 by flarn2006 1 Quote
Rolf Kalbermatter Posted September 5, 2014 Report Posted September 5, 2014 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. VariantToArray.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) . 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. Quote
hooovahh Posted September 5, 2014 Report Posted September 5, 2014 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. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.