(Original creator: pietervandijk)
I was reading Gerton’s blog on The Struct 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.