(Original creator: Gerton)

  Hi bloggers, For the ones that do not know me, I'm Gerton Leijdekker, Usability Consultant and Lead Developer for the Uniface product line in the Uniface Lab in Amsterdam. My intention is to blog about technical subjects, so this first blog will be about the Struct. With Uniface we always try to keep things simple with the intention to keep it a productive tool; don't bother with complex stuff, simply plug in the features you need, some ProcScript to glue them together, and done. But simplicity also has a downside, because now and then you just need more… Some features take the enablement approach, where the functionality can be used to solve a wide range of problems. But where simplicity adds limitations, flexibility adds complexity and complex things are most of the time harder to understand. The Struct is one of them: powerful, flexible, useful … but complex. The Struct is introduced in Uniface 9.5 and can solve a variation of challenges, like data transformations, data communication, and data processing. The Struct has no format limitations and therefore can handle any data format, whether it is Entities, XML, JSON, or your own custom format. But in all cases it helps if you fully understand what a Struct is and how it works. Currently, I'm working on the new Uniface 10 IDE and we use the Struct for almost everything. It replaces entity, occurrence, list, and xmlstream parameters and is heavily used for data cashing purposes. But although I was involved during the original design of the Struct, now that I need to use it, I still find it a challenging thing to use and it took me some time to fully grasp its concepts. In this first blog, I will focus on its core technical concepts being the Struct itself, the Struct Node, the Struct Variable, and the Struct Node Reference. To me it was very helpful once I fully understood those. The info in this blog is also being used to update the Uniface Library, but remember, you read it here first. :)

The Struct

The Struct is a collection of objects, called Struct Nodes. These Struct Nodes are hierarchically organized, hence the term 'struct'. Every Struct Node can have i/o refers to 0, 1, or more child Struct Nodes. The Struct always has only one root Struct Node. The image shows two Structs as the reside somewhere in Uniface memory:

Struct Image 1

The Struct Variable

You can declare a struct variable the way you like any other variables, but unlike to variables of type String, Numeric, or Boolean, the Struct Variable does NOT contain the data itself; the Struct Variable only refers to the struct data that (as said) resides somewhere in Uniface memory. To be more specific, a Struct Variable refers to the root Struct Node of a struct dataset making this dataset the thing we call 'Struct'. The image shows two Struct variables referring to the root node of a Struct.

Struct Image 2

A Struct Variable can actually refer to multiple Structs or to none at all.  To be specific, a Struct Variable can refer to 0, 1, or more Structs. The image shows a single Struct Variable containing 2 references to two Structs.

Struct Image 3

The opposite is also possible: multiple references to the same Struct. The image shows two Struct Variables referring to the same Struct. One has to refer to the root node, the other refers to some node in the same Struct making it a kind of sub-Struct or nested Struct. More about this construction later.

Struct Image 4

Struct Variable declaration

The declaration of a Struct Variable, does not create the Struct, it only creates a Struct Variable with zero references. This variable can now be used to either create a Struct from scratch or have it referred to an already existing Struct. The image shows two Struct Variables that do not refer to any Struct.

Struct Image 5

Struct creation

There are two ways to create a Struct. The first is by making use of the Proc function $newstruct. This Proc function creates a single Struct Node and returns a reference to it. If this reference is then assigned to a Struct Variable, a Struct consisting of a single node, has been created. The image shows the code used create a Struct with only one node. This Struct is now accessible via the Struct Variable.

Struct Image 6

The second is by making use of the conversion Proc statements like componenttostruct, xmltostruct, and jsontostruct. Maybe more conversion statements will follow in the future. A struct conversion function uses the provided data in some external format and generates a (huge) set of hierarchical related Struct nodes that logically represent the data. The Proc instruction returns a reference to the root node of this Struct which is typically assigned to a Struct Variable. This Struct is now accessible via the Struct Variable.

Struct Image 7

Struct member creation

To create a sub node, or a Struct member, you also use the Proc function $newstruct, but instead of assigning the newly created node to a Struct Variable, you assign it to a member a specified by its name. The image shows the code used create the initial Struct and then how members are created. The image also shows how an existing member is assigned to a Struct Variable, creating a sub-struct or nested Struct.

Struct Image 8

Struct deletion

A Struct that is no longer referenced by a Struct Variable, and therefore not accessible, is automatically deleted from Uniface memory. The image shows that setting "" to the Struct Variable that refers the root node of the Struct will have as a consequence that the Struct will deleted. A Struct Variable running out of scope has the same effect. Struct Image 9

The image shows that deleting a Struct does not affect any sub or nested Structs. The sub Struct, or nested Struct, has its own variable referring to its root node (this is what makes it a Struct) and therefore is still referenced and not deleted.

Struct Image 10

Struct parameters

Uniface also supports Struct Parameters. The Struct Parameter is like the Struct Variable, it works with references. Image a Proc function that takes one struct parameter as input, it checks all members of the referenced Struct and returns references to the members that are leaves as Struct out parameter. The image shows the result after calling this function, where myStructVar1 refers to the root node of the Struct and myStructVar2 refers to all leaves in the same Struct as detected by the function. But more about Struct Parameters next time.

Struct Image 11

That's it for now, next time more about passing structs by reference and by value. Gerton's Emoticon



  1. Hi Gerton, as you said: as soon as you start to use struct for a concrete task, you have a need for more information. It's the same when Jan Bank provided the Building Blocks long time ago and found some functional extensions necessary. Thanks for starting with some useful scenarios on the struct front and the nice explanations. I will "build to learn" some of your "test cases" to play a bit more with structs. The tags of your blog say 9.5: is there any minimal patch level to run your examples? On Berrys webex, he mentioned $dbgstruct to examine the contents of structures. And I was impressed that such a function is available (even undocumented).
  2. For the little coding examples in the pictures, I do not think so. 9.5 should be good enough (but I will be honest, I did not check the examples on 9.5). Regarding the $dbgstruct, I do not know about a $dbgstruct. It is either a non-documented feature that I do not know about (I doubt that) or Berry made a little mistake and he means $dbgstring. And then there is an alternative for $dbgstring, and that is $dbgstringplain. Both are documented in what they do.
  3. SESSION 2: WEB DEVELOPMENT & WEB SERVICES WITH UNIFACE 9.6 When: Thursday, 31st January, 2013 $dbgstruct was on slide 32 of http://de.slideshare.net/Uniface/uniface-web
  4. Hello Gerton, before talk about struct I want to thank you and your team about RIA uniface: Special thank on weboperation statement: Which was the missing statement in uniface 9.4: allows to make reusable DSP components. Thanks for webtrigger and weboperation statements: Get responsive web applications. Mixed with JavaScript API and weboperation statement, a real Ajax web application. The structs are also very interresting: a service: params string pXml : out endparams variables struct lvStruct endvariables ... componenttostruct lvStruct, "TopEntity" structoxml pXml, lvStruct end another component: params string pXml : in endparams variables struct lvStruct endvariables xmltostruct lvStruct, pXml structtocomponent lvStruct->TopEntity ... end Four statements for exchanging set of datas between two uniface components, fomidable! :-) But, because there is a but, it's slower, with large amount of data, than list exchange with forentity, putlistitems/occ, and so on in case of entities nesting. But, because there is another but, 4 statements is realy interresting. It's the good way, go on! Philippe PS: I only test it in 9.5, perhasp in 9.6 it's more speed
  5. Hi Philippe, you should take a look at the latest maintenance from Uniface, there have been quite a few enhancements for performance in the area of structs. Most have been delivered in both Uniface 9.5 and Uniface 9.6, and I think a few more enhancements will be in the MX01 service pack which is due out in the coming weeks. We're also planning on a webex session about structs, and we'll cover off some best practices based on our experiences with using the functionality.
  6. I have no knowledge of this language and was re-testing / learning my flowcharting logic knowledge. In your example, can you clarify in the 4th blue box chart on Node 4 the arrow showing Struct variable MyStructVar2..with Reference to Node 3. I believe the Reference field is only descriptive but I think it should be to Node 4..and this occurs several more times up to struct deletion. My confusion then carries to the final struct parameters blue box where Node 3 reference to node 3 box is that valid? Thank you Elia
  7. Looks like a typo in the diagrams, obviously.
  8. Yes, definitely a typo. If I get the change I will fix it (if possible).
  9. See Adrian's reply. These patches include new enhancements on the struct and one of them is struct as a parameter on public operations. Check that out, you do not even have to (de-) serialized to/from XML anymore. You simply do componenttostruct, pass the struct, and structtocomponent. My next blog will be about structs as parameters, so keep in touch.
  10. Oh, and before I forget, most time is spend on XML (de-) serialization, so if we can skip that, it will be a lot faster.
  11. We have met this week Adrian Gosbell in Amsterdam offices to show details of Uniface 9.6 and he pushed us to read your paper. So I did, enjoy and jump into Uniface documentation (I have only 9.5 doc for the moment). Not too difficult to understand, if you have C++ developer background and you dream of extending listitems possibilities. As you may know we have build our own language (MPL) build on the 3GL API that let our customers change our product behavior. So it has already functions and operators to manipulate some structures like listitems, included entities (a heritage from Uniface 5), simple xml strings. Nice to know that we used also the {} for indexing. I dreamed to extend this to more sophisticated structures. And YOU DID IT!! This as almost all features I dreamed for. Thanks for this fantastic extension. Now I would like to implement it in my MPL language and I have a stupid question: What about 3GL API? What will I get reading struct variables?
  12. "Thanks for this fantastic extension." - You're welcome :-) "What about 3GL API?" - Sorry, no 3GL API on structs. :-( "What will I get reading struct variables?" - huh, what do you mean with this? It is not clear to me.
  13. “What will I get reading struct variables?” I mean executing UFGET on it or reading retruning param of an operation called by 3GL.
  14. Ah, if we would enable a 3GL API (and we do not), then I think you would get a set of 3GL functions that are the equivalent of the 4GL functions. But again, there are not plans for this. If you needs something like this, I suggest you contact Adrian or one of his fields guys to talk the use cases through. Maybe there is some other way to achieve the thing you want to achieve. Gerton