(Original creator: pietervandijk)
I was reading Gerton’s blog on Structs and its references, and I realized that he skillfully danced around some complex topics to avoid being distracted from his main focus. It is the only way to get your message across of course, but I was tempted to tackle one of those other tricky topics so I would like to show what happens exactly on struct assignment. Let’s borrow one of Gerton’s structs and assume we have a struct variable myStructVar1, pointing to a struct in Uniface memory:
Now, the following two assignments have very different effects: [uniface] myStructVar2 = myStructVar1 ;- assignment (1) myStructVar3 = $newstruct myStructVar3->someNode = myStructVar1 ;- assignment (2) [/uniface] I’m not talking about the obvious difference that the structure of myStructVar3 is slightly different, but what do these assignment statements do? The crucial difference is that the first assignment is to a Struct Variable, while the other assignment is to a Struct Member; this triggers other behavior. In the first line, myStructVar2 simply becomes another reference to the struct in Uniface memory, which was already referenced by myStructVar1. Consequently, if the struct is modified through myStructVar1, the effect is seen in myStructVar2 and vice versa, because they point to the same memory space.
The assignment to a member of myStructVar3 is more complex. Structs cannot contain references to arbitrary other structs, so myStructVar3‑>someNode simply cannot refer to that same memory space. Instead, a copy is made of the struct referred to by myStructVar1, and it is created as a child Struct Node of myStructVar3. The assignment also dictates that the name of this node is someNode, so the copied struct is renamed from its original name (Node1) to the new name (someNode).
However, you may want to inherit the name from the assigned struct. You have two options to achieve this effect: either explicitly use the name of the source struct in the assignment, or prevent renaming. First, let’s explicitly use the proper name on assignment: [uniface] myStructVar3->"%%(myStructVar1->$name)" = myStructVar1 ;- assignment (3) [/uniface] Alternatively, do not use any name in the assignment, but simply append a new child without any name assignment: [uniface] myStructVar3->*{-1} = myStructVar1 ;- assignment (4) [/uniface] The syntax of this last assignment may puzzle you: ->* is an operator which returns all children. The index between curly braces specifies where to insert or append the new node. A positive number is an absolute location among the existing child nodes, while -1 simply means: append at the end of the child node list. Then there is one more thing: suppose we do not want to create a copy on assignment, suppose we DO want to assign the struct referred to by myStructvar1, as a member to some other struct, referred to by myStructVar2. This is a very valid requirement, as the effect is that other references to the struct will notice the effect of the assignment. How to do this? It is quite simple, but requires you to think out of the box: do not assign the struct itself, but instead assign its parent: [uniface] myStructVar1->$parent = myStructVar3 ;- assignment (5) [/uniface]
Of course, if the struct referred to by myStructVar1 already had a parent, this assignment will detach the struct from its original parent. In summary the different options, with a short one liner to characterize the effect: [uniface] myStructVar2 = myStructVar1 ;- (1) copy a reference to the struct and assign the struct myStructVar3->someNode = myStructVar1 ;- (2) copy, rename and assign the struct myStructVar3->"%%(myStructVar1->$name)" = myStructVar1 ;- (3) copy, (rename) and assign the struct myStructVar3->*{-1} = myStructVar1 ;- (4) copy and assign the struct myStructVar1->$parent = myStructVar3 ;- (5) attach the struct as a child [/uniface] Pieter van Dijk Developer in the Uniface Lab During the development of Uniface 9.5, I contributed to the design of the Struct.
Currently I am actively using the Struct while working on the new version 10 IDE.
Posts

19 Comments
Local Administrator
Local Administrator
That is a nice question. Even though the main reason for introducing the struct was to enable the Uniface proc language to handle any (external) XML stream, it is an additional benefit that structs can be used as a replacement for Uniface lists. So how does the struct compare to the Uniface list?
The list can be used to hold complex structures, but this only works well for read-only structures - the problem with lists is that they are difficult to modify. Only the top level of a nested list can be updated (adding/deleting or updating list items), This means that an update to a lower nested item can only be done by first decomposing the list down to that level, then update it and finally reconstruct the list. Moreover, it is not possible to insert an item into a list: to achieve this you need to build a new list with the additional item inserted on the right location. Such techniques are cumbersome and expensive. The structure in contrast can be updated at any level: it is possible to add, insert, delete and update items.
Another problem with lists is that also for the Uniface kernel they are inefficient to handle. One reason lies in the way they are implemented: they use separator characters which depend on the nesting level. This means the whole (sub)list needs to be parsed and updated when popping or pushing takes place - such as when using $item. We cannot fix this, as the physical structure is exposed and public; many 4GL developers manipulate lists using this knowledge.
Then, structs come with a whole set of new features:
myStruct->*->*->$parent = myOtherStruct
will remove all grandchildren and unite them under a new parent struct
renames all children of myStruct called 'client' to 'Client'
Lists currently also have some advantages over structs:
Altogether, we personally believe the struct is superior over lists: specifically due to its strong manipulation power and its reference efficiency. In the new version 10 IDE we use the struct extensively for data manipulation and data exchange. This would simply have been impossible with lists.
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Local Administrator
Hi Uli
A great initiative. For some practical examples on how to work with structs I'd like to refer the the documentation: search for the topic 'Struct Code Examples'. There is a sample how to traverse through a struct recursively (look for the entry struct_loops).
good luck!
Pieter
Local Administrator