Jump to content

typeless wire


Recommended Posts

I would like to propose the typeless wire. Along with that comes a typeless control and indicator. Black might be a good colour. It's a bit like a template type in C, but then better because it's LabVIEW :)

post-1555-1168804663.gif?width=400

Actually the proposed wire is only typeless in the diagram of the VI concerned. As soon as the VI is placed somewhere as a subVI, the connections made to the VI determine the actual type of the wires inside the VI. For example, you could make a VI with a typeless input and output, place an array resize function in the VI that resizes a connected array to be able to set an element (as in picture above). It would work on any 1D array that is connected. Whether the VI is compilable or not depends on the type of wires that are connected where it is placed. The type of a typeless output terminal is also determined by these connections.

To keep the behaviour similar to normal VIs, the VI should lock like any other VI, so that only one instance can be running at a time. Extra code will be generated for the type of wires that are connected. There should not be completely different instances of code for each type, because a great part of the code can be shared between different types. The compiler can insert a branch instruction when a typeless wire is reached, to jump to the code required to execute an action for the wire of the specific type.

If you would connect a typeless wire to a shift register, each type would generate its own instance of the shift register. However, if a normal (typed) wire is connected to an another shift register in the same VI, that shift register is shared between all types. That way you could for example create a "generic" storage functional global.

post-1555-1168804719.gif?width=400

To be able to do different things for different connected types, the case structure could be used to switch between the various behaviours. It would then switch based on the wired type. E.g. if you create case frames for a DBL and a Boolean, the VI is compilable for those types. The wire is available in the case frame as of this type. It would allow you to return a string for both a double and a boolean: "3.14" and "True". If a type is connected to a typeless input of the VI for which there is no case frame, the VI is not compilable.

This mechanism as an alternative to polymorphic VIs. Polymorphics require multiple VI's, with often identical diagrams, which causes code duplication. Untyped wires allow to have only a single diagram for multiple types. They are easier to manage and understand, give smaller code and don't require all the types to be known and implemented beforehand.

Something for LV9 ?

Joris

Link to comment
I would like to propose the typeless wire.

I've thought of this issue as well. I had the same idea as you in the beginning. However, if you go into more detail you notice that such a typeless type will cause you also some troubles. There exists very advanced template techniques is some modern programming languages that would solve this problem in much more elegant way. I don't go into detail here as it's a field of computer science of it's own.

Link to comment
I've thought of this issue as well. I had the same idea as you in the beginning. However, if you go into more detail you notice that such a typeless type will cause you also some troubles. There exists very advanced template techniques is some modern programming languages that would solve this problem in much more elegant way. I don't go into detail here as it's a field of computer science of it's own.

I know about template trouble in C. But unlike C, LV already has its way of determining propagating datatypes of wires, which would work here as well.

What problems do you see ?

Joris

Link to comment

This looks like a very good idea to extend the power of one of my favourite features of LabVIEW 7 (or was it 6.1)! :)

I wonder if the LabVIEW real time compiler can handle such a wire. I guess it is not an easy job, else the untyped wire would have been there already. I can imagine that an untyped wire also has less overhead than subVIs.

I agree that a polymorph VI based solution is not so easy to master when you start editting the existing code. It is very easy to introduce a bug or if there are a lot of functions it can be quite a job to start editting all these VIs manually since a "replace all" action is not available yet (a source control tool is a big help here). I have not enough experience with other languages on this level to compare.

I guess you do not want to use variant type based solutions because of the speed/memory penalty?

FYI: I don't know if you are aware that editting polymorph Vis is only possible in the professional edition of LabVIEW.

Link to comment
I know about template trouble in C.

C doesn't have templates and I didn't refer to C++ templates. What I'm saying is that one shouldn't invent the wheel twice. There already are better solutions to this problem, see Java generics for an example. Java generics is not the best possible solution but as Java is familiar at least to some people, I think it's a good example.

Link to comment
I guess you do not want to use variant type based solutions because of the speed/memory penalty?

No, because it does not allow compile-time checking. You would have to run your program in order to find problems in your wiring.

If you want to see more about template problems in other languages have a look at this:

http://burks.brighton.ac.uk/burks/pcinfo/p...it/index003.htm, chapter Templates.

Joris

Link to comment

50x faster? I didn't know the improvement was that dramatic. I have an speed issue in a LV7.1 application with the OpenG /NLConfig Variant config VIs when loading a very big settings file, it seems I have to force the customer (Johnson & Johnson) to go for 8.20.

It seems somebody at NI deserves a Belgian beer :-) or chocolate bar. Who?

Link to comment

FYI, upgrading to 8.20 is MUCH more to loading your old code and recompiling.

You'll have to create a project, check that your code doesn't suffer from LV bugs like the table problem, autoindexing/inplaceness, and then create a new installer (MUCH larger than in the past).

post-949-1142450691.gif

If you haven't done this before, you may have a lot of work ahead of you....

Link to comment
  • 6 months later...

On a slightly unrelated topic, I wish there was the ability to perform "Dynamic dispatching" based on Data type, or even just on Strict Typedefs.......

This wouldn't be a "one size fit all" approach, as there need to be a finite number of defined end states, but I think it'd still go a long way to allow some more advanced features. especially when tied to a producer/consumer design. My original post (NI Forum) is here.

This, in my opinion, would make some issues in UI programming a LOT more versatile indeed. Haven't tried Xnodes though. Will do shortly.

Shane.

Link to comment

QUOTE(shoneill @ Aug 13 2007, 08:00 AM)

On a slightly unrelated topic, I wish there was the ability to perform "Dynamic dispatching" based on Data type, or even just on Strict Typedefs.......

You're talking all data types, not just LV classes, right?

The problem you're facing (I know because I tried this as one of the initial approaches to classes) is that you need a central data type repository (such as the .ctl) that knows "this VI is my 'add' function and this other VI is my 'subtract' function" etc. The ctl has to store all these relationships to these VIs. The result is something that looks a whole lot like a library, with a centralized data type, which is effectively what a LV class is. The piece that we sidestep is the map from "function XYZ" to "implementation ABC". That would be operator overloading and requires that there be a map of all possible functions to overload in LV to the particular implementor.

I've played around with such concepts, and they get pretty ugly, both on the debugging side and on the UI side. Personally, I don't particularly like open-ended plugable functions (aka operator overloading). With the dynamic dispatching of classes, I can view the class hierarchy and know whether or not a given class has a given functionality. With arbitrary overloading, I become less sure at every turn whether that "add" primitive that I see on the diagram is actually an add.

James Gosling, the inventor of JAVA, left operator overloading out of JAVA because he saw C++ and noticed that it was now *ANSI standard* to use the left shift operator for output to a file. I've seen C++ code where "a == b" was overloaded to not actually evaluate whether a equals b but instead was a special type of assignment (deep assignment instead of shallow assignment, for those who know pointers). That sort of horrific situation is not one that I want LV to enter into.

Link to comment

QUOTE(Aristos Queue @ Aug 13 2007, 01:52 PM)

You're talking all data types, not just LV classes, right? ...

I don't particularly like open-ended plugable functions (aka operator overloading). With the dynamic dispatching of classes, I can view the class hierarchy and know whether or not a given class has a given functionality. With arbitrary overloading, I become less sure at every turn whether that "add" primitive that I see on the diagram is actually an add.

James Gosling, the inventor of JAVA, left operator overloading out of JAVA because he saw C++ and noticed that it was now *ANSI standard* to use the left shift operator for output to a file. I've seen C++ code where "a == b" was overloaded to not actually evaluate whether a equals b but instead was a special type of assignment (deep assignment instead of shallow assignment, for those who know pointers). That sort of horrific situation is not one that I want LV to enter into.

Absolutely. This has been one of the biggest concerns I've had over what APPEARED to be (but actually wasn't/isn't -- I hope) a headlong rush to make LV into LV++. After hearing some of the buzz at NI Week, I feel much more comfortable with the development as it's proceeding. Nicely done, esp to you AQ and esp re: the Tarot deck ;-)

Link to comment

QUOTE(Aristos Queue @ Aug 13 2007, 10:52 PM)

You're talking all data types, not just LV classes, right?

......

I've played around with such concepts, and they get pretty ugly, both on the debugging side and on the UI side. Personally, I don't particularly like open-ended plugable functions (aka operator overloading). .....

I agree with you 100%. If you refer back to my nugget, you'll see that it's the combination of UI and dynamic dispatch which I was looking for. In the end, I employed an ugly open-end system (based on variants) because I didn't see any other way of doing it. What I would like is somewhere between that and the current system. LVOOP would be perfect if we could place class data directly on the FP for user interaction, but we can't. Hence the idea of having a list of "registered" typedefs for a kind of dynamic dispatching (A Typedefed Control CAN be on the FP). I appreciate that the ability of the compiler to detect wrong data types at compile time is very important, and I'd be delighted to have this functionality.

I also tried creating a polymorphic VI with different Typedefed (sp?) inputs, but although no error was created with several polymorphic instances with (essentially) the same datatype but different Typedefs, no polymorphism resulted.

At the moment, "With the dynamic dispatching of classes, I can view the class hierarchy and know whether or not a given class has a given functionality. With arbitrary overloading, I become less sure at every turn whether that "add" primitive that I see on the diagram is actually an add." I find it difficult to fully appreciate the real difference between the two cases you're mentioning here.

Maybe when I get more familiar with LVOOP things will clear up for me. But I think your example of overloading the "add" primitive is overshooting the mark a tad. The original idea was (when you get down to the bare bones) a convenient way of working with known data structures. I was also trying to demonstrate function overloading, not operator overloading (i.e. Pi() and Pi(2)). In reality, I was actually coming closer to a sort of polymorphism with an extended definition of "Data type". Upon reflection, I have come to realise that the ability to define polymorphic VIs based on their ENTIRE TD would be the right way to go about this. Certainly a long way from arbitrary overloading.

To quote one of my posts in my nugget thread (spelling mistakes retained for authenticity :wacko: )

"I've jsut started working my way into classes, and I love "Dynamic dispatch". I'd also love exactly the same thing for Typedefs. I want a control I can place on a Front panel, wire up to a function and to have the function automatically execute a method "registered" for that exact typedef (such as entering that value into a pre-defined cluster). Replace the control with another Typedef, and the code called updates..... How and where the "registration" takes place, I dunno. Maybe even statically within the VI being called, thus providing strict limits to accepted typedefs."

I think the usage of Variants and the admittedly open-ended implementation of my code has actually distracted from what I actually was trying to create. "Registration" is the key here, otherwise you don't get compile-time error checking.

So we're agreed on that at least.

Shane.

Link to comment
  • 2 weeks later...

QUOTE(Aristos Queue @ Aug 13 2007, 10:52 PM)

That would be operator overloading and requires that there be a map of all possible functions to overload in LV to the particular implementor.

Yeah, operator overloading, brrr, scary stuff !

Joris

BTW, objects do fit in in the original idea that I presented by starting this thread. The type of a class OR parent class should be settable in the case selector. If you were to insert a method of a given parent class, all derived (child) classes would also be accepted, because they "are" also of the parent type. Fits perfectly in OO philosophy. This ensures the VI can handle all known types connected to the typeless input VI. Of any child you usually know sufficiently via its parent. If not, you could define the child class behaviour in a separate frame. The child handling should preceed the parent handling, because it is more specific.

You don't need this structure to do something on ANY type. For that you can use a variant. But then the distinction between types is lost, what I meant the structure for. With this structure, on type A you want to perform action X and on type B you want to perform action Y. Probably the results of the actions is alike (but that is not required).

Joris

Link to comment
  • 12 years later...

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.