Topic
  • 14 replies
  • Latest Post - ‏2012-02-24T15:53:08Z by llandale
llandale
llandale
2972 Posts

Pinned topic LinkList

‏2012-02-19T20:27:36Z |

I think I've implemented the notion of a dynamic Linked List in DXL. I was inspired after using Arrays with huge number of rows but fixed number of columns; but the columns could extend depending on how many items were associated with the KEY of the row; but assigning large column values multiplies the size of the table by iRowMax X iColMax, and I was running out of memory. Again.

I FINALLY used a "struct"; Anybody want to welcome me to the 1990s? lol
Constructive critism encouraged.

The following code does not yet allow the notion of removing an item from a list, and it if id did we'd need some form of garbage collection or reuse; probably a "Skip" of removed rows.

Comments need improving but I need to go home.

Seems to me that these two lines could be improved with some form of Alias, but I failed at that.

Line#
#107    int     iRow_Tally      = (int   dxloLList->c_LList_Field_Tally) 
#160    dxloLList->c_LList_Field_Tally = iRow_Tally


-Louie

Updated on 2014-01-06T17:27:34Z at 2014-01-06T17:27:34Z by iron-man
  • Mathias Mamsch
    Mathias Mamsch
    1969 Posts

    Re: LinkList

    ‏2012-02-20T12:21:53Z  

    Hi Louie,

    It is an honour for me to welcome you in this exciting age ;-) For starters: It seems to me you implemented more than a Linked List. You implemented a 'Linked List Container', which actually contains memory for a set of 'labeled' linked lists and contains functions to handle them. That maybe makes your code more complex than necessary.

    But first some code improvements:

    • do not use reference parameters for your LinkedList, if not necessary (e.g. 'fLList_Put'). Otherwise your 'null' checks will not work! the code if (null ref) {...} will actually not check the value of the reference, but the reference itself, i.e. if you passed a null reference. If you pass a variable with a null value, then the reference will not be null - you are still referencing an existing variable. Therefore in the 'fLList_Delete' you need to dereference the reference before checking for null. On the other functions I would just pass a normal variable.

     

    • Note that the global string parameters and the DxlObject are used all over the place in the file. That really makes the code hard to read and to change. Therefore I would always suggest the following pattern for a struct:

     

     

    struct LinkedList {}
     
    // Turn the LinkList into a DxlObject
    DxlObject fl_LList_DxloOf (LinkedList in_LList) { return (DxlObject(addr_ in_LList)) }   
     
    // constructor for DXL Object
    LinkedList fLList_Create_ () { DxlObject dx = new(); return ((addr_ dx) LinkedList) }
     
    // struct properties
    void  set_FieldArray (LinkedList L, Array ar) { (fl_LList_DxloOf L)->"FieldArray" = ar }
    Array get_FieldArray (LinkedList L          ) { return ((fl_LList_DxloOf L)->"FieldArray") Array }
     
    void  set_FieldTally (LinkedList L, int    ar) { (fl_LList_DxloOf L)->"FieldTally" = ar }
    int   get_FieldTally (LinkedList L           ) { return ((fl_LList_DxloOf L)->"FieldTally") int    }
     
    void  set_FieldSkip (LinkedList L, Skip ar) { (fl_LList_DxloOf L)->"FieldSkip" = ar }
    Skip  get_FieldSkip (LinkedList L         ) { return ((fl_LList_DxloOf L)->"FieldSkip") Skip }
     
    void   set_sFieldLast (LinkedList L, string ar) { (fl_LList_DxloOf L)->"sFieldLast" = ar }
    string get_sFieldLast (LinkedList L           ) { return ((fl_LList_DxloOf L)->"sFieldLast") string }
     
    void   set_iFieldLast (LinkedList L, int   ar) { (fl_LList_DxloOf L)->"iFieldLast" = ar }
    int    get_iFieldLast (LinkedList L          ) { return ((fl_LList_DxloOf L)->"iFieldLast") int   }
    



    It makes the code much easier to read, and separates the internal storage (DxlObject) completly from the rest of the code. This way if you later decide to add functionality and therefore decide that you would want to replace one property by a function that not just stores stuff, but maybe implements a more complex functionality, you already have this function and only replace the code. There are more advantages, e.g. that in an editor with 'auto complete' you will always have the function definitions of your properties if you type 'set_' including the datatype. You cannot store the wrong datatype in your DxlObject anymore... And so on. Note that this way, you can get rid of the string constants, you can embed them directly in the functions.



     

     

     

    • You should really not ignore if someone passes a non-null LinkedList with a null Array List or Skip List to your function:

     

     

     

    void    fLList_Put(LinkedList in_LList, string in_NameList, in_Item) {
       ...if (null in_LList   or ...) return 
     
       // this is for sure a programming error! Make it obvious to the programmer by explicitly raising an error!
       if (null arr_List or null skp_Index)  return
    



    The interface to your data structures seems not optimal. You are mixing two data types in one type. Actually the data structures that you have are:

    ListItem: one item in a list, with a successor, which builds together with other ListItems a linked list.
    ListContainer / LabeledLists: a Skip of 'labels/columns' with a root element of a linked list each.

    Therfore your class interface should probably look like this:



     

     

     

    struct ListContainer {}   
            // Properties:   
        
            // Key: list label (string)   Value: Root Item (LinkedList)
            // stores the column heads and the root list items
            Skip get_RootItems (LinkedList) { ... }
            void set_RootItems_(LinkedList, Skip) {... }
                                       
     
            // set the root element for list with label 'sLabel'
            void setRootItem (LinkedList, string sLabel, ListItem) { ... }
     
     
            // allows you to write    insertItem( MyList["column"], "A") 
            ListItem ::[] (LinkedList L, string label)  { ...}
     
            // how about some syntactic sugar?    myLinkedList["A"] <- "New Item"
     
     
    struct ListItem {}
     
     
            Properties: 
                    ListItem get_nextItem(ListItem)
                    string get_Value(ListItem) 
     
            Methods: 
                    // inserts the element sItem in the list starting at listStart 
                    insertItem (ListItem listStart, string sItem)
    


    Regarding the storage of the list items, you can use a global array for all list items (which makes the implementation easy and will work for large item counts). In this case a 'ListItem' is only a row number in the global array, which gets rid of DxlObjects altogether (remember the allocation list!). The basic approach for this that I always use is:

     

     

     

     

    // Allocate initial memory for 10000 list items
    // one row is one ListItem, columns store the properties
    Array garListItemMemory = create(10000, 3 ) 
     
    // stores the next row in the list memory array to be allocated
    int   giListItemHandleCount = 0 
     
    // This skip stores the rows that have been invalidated, i.e. deleted and can be reused
    Skip skFreeListItemNodes = create()
    int giFreeListItemNodes = 0
     
    struct ListItem {}
     
    // ... Properties ... 
    ListItem getNext (ListItem x) { return (get(garListItemMemory, (addr_ x) int, 0)) ListItem }
    void setNext_ (ListItem x, ListItem val  ) { put(garListItemMemory, val, (addr_ x) int, 0) }
     
    string getValue (ListItem x) { return (get(garListItemMemory, (addr_ x) int, 1)) ListItem }
    void setValue (ListItem x, ListItem val  ) { put(garListItemMemory, val, (addr_ x) int, 1) }
     
    // constructor & destructor for List
    ListItem createListItem_ () {
        ListItem x = null
        // reuse an existing list nodem if possible
        if (giFreeListItemNodes > 0) {
            // print "Reallocating Stack Nr " giFreeListItemNodes "\n"
            if (!find(skFreeListItemNodes, giFreeListItemNodes--, x)) error "ListItem memory error!"               
        } else {
        // allocate a new row: Note that a ListItem now is only a single number! 
            x = (addr_ (++giListItemHandleCount) ) ListItem;
        }   
        // print "Allocated ListItem node " ((addr_ x) int) "\n"    
        return x
    }
     
     
    void deleteListItem (ListItem &t) {
        // put in free list nodes
        ListItem deref = t
        put (skFreeListItemNodes, ++giFreeListItemNodes, deref, true)  
        // print "Freeing ListItem Slot: " (listItemHandle t)" in Stack Nr: " (giFreeListItemNodes-1) "\n"
        
        // Set all properties to zero here, so your array will be nice and clean!
        setValue (t, "")        
        setNext_ (t, null ListItem   
        t = null     
    }
     
    // ... implement append, delete, etc. ....
    



    Note that even if you decide, you need different 'memories' (Arrays) for storing different lists or list sets, this is still completely independed from the 'labels' that you put on the lists. If you decide you want to store a vast amount of items, and do not want that one huge array, this can be solved much more elegantly. With the above approach of making ListItem a separate struct a search can be done using the following code:



     

     

     

     

    ListItem I = myLinkedList["A"] 
    while (!null getNext I) { print "Value:" (getValue I) "\n"; I = getNext I }
    



    From the user code, no need to store the search values anymore. However it might be worth to discuss different approaches to storing the data. I have implemented three other datatypes which would allow to store the data that you store in the 'LinkedList':



     

     

     

    • Tree (A ordered Tree Structure like the Objects of a DOORS Module)
    • Map (Basically a M:N mapping using a Skip in Skip approach, which allows to store value pairs A:A, A:B, A:C, B:A and afterwards answers questions like "Give me the left side values of the right side value 'B',give me all left side values, etc.)
    • Sparse Array (Represents a very large array where all available indexes can be used without running into memory problems. The approach here is that the virtual array is partitioned into smaller rectangular arrays of size 64kb which are allocated on demand)


    Depending on what data you want to store and the performance you need one or the other data type might be beneficial. What data are you actually trying to store?

    Maybe that helps, Regards, Mathias

     

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

    Updated on 2014-01-06T17:30:55Z at 2014-01-06T17:30:55Z by iron-man
  • llandale
    llandale
    2972 Posts

    Re: LinkList

    ‏2012-02-20T17:52:15Z  

    Hi Louie,

    It is an honour for me to welcome you in this exciting age ;-) For starters: It seems to me you implemented more than a Linked List. You implemented a 'Linked List Container', which actually contains memory for a set of 'labeled' linked lists and contains functions to handle them. That maybe makes your code more complex than necessary.

    But first some code improvements:

    • do not use reference parameters for your LinkedList, if not necessary (e.g. 'fLList_Put'). Otherwise your 'null' checks will not work! the code if (null ref) {...} will actually not check the value of the reference, but the reference itself, i.e. if you passed a null reference. If you pass a variable with a null value, then the reference will not be null - you are still referencing an existing variable. Therefore in the 'fLList_Delete' you need to dereference the reference before checking for null. On the other functions I would just pass a normal variable.

     

    • Note that the global string parameters and the DxlObject are used all over the place in the file. That really makes the code hard to read and to change. Therefore I would always suggest the following pattern for a struct:

     

     

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">struct LinkedList {} // Turn the LinkList into a DxlObject DxlObject fl_LList_DxloOf (LinkedList in_LList) { return (DxlObject(addr_ in_LList)) } // constructor for DXL Object LinkedList fLList_Create_ () { DxlObject dx = new(); return ((addr_ dx) LinkedList) } // struct properties void set_FieldArray (LinkedList L, Array ar) { (fl_LList_DxloOf L)->"FieldArray" = ar } Array get_FieldArray (LinkedList L ) { return ((fl_LList_DxloOf L)->"FieldArray") Array } void set_FieldTally (LinkedList L, int ar) { (fl_LList_DxloOf L)->"FieldTally" = ar } int get_FieldTally (LinkedList L ) { return ((fl_LList_DxloOf L)->"FieldTally") int } void set_FieldSkip (LinkedList L, Skip ar) { (fl_LList_DxloOf L)->"FieldSkip" = ar } Skip get_FieldSkip (LinkedList L ) { return ((fl_LList_DxloOf L)->"FieldSkip") Skip } void set_sFieldLast (LinkedList L, string ar) { (fl_LList_DxloOf L)->"sFieldLast" = ar } string get_sFieldLast (LinkedList L ) { return ((fl_LList_DxloOf L)->"sFieldLast") string } void set_iFieldLast (LinkedList L, int ar) { (fl_LList_DxloOf L)->"iFieldLast" = ar } int get_iFieldLast (LinkedList L ) { return ((fl_LList_DxloOf L)->"iFieldLast") int } </pre>



    It makes the code much easier to read, and separates the internal storage (DxlObject) completly from the rest of the code. This way if you later decide to add functionality and therefore decide that you would want to replace one property by a function that not just stores stuff, but maybe implements a more complex functionality, you already have this function and only replace the code. There are more advantages, e.g. that in an editor with 'auto complete' you will always have the function definitions of your properties if you type 'set_' including the datatype. You cannot store the wrong datatype in your DxlObject anymore... And so on. Note that this way, you can get rid of the string constants, you can embed them directly in the functions.



     

     

     

    • You should really not ignore if someone passes a non-null LinkedList with a null Array List or Skip List to your function:

     

     

     

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">void fLList_Put(LinkedList in_LList, string in_NameList, in_Item) { ...if (null in_LList or ...) return // this is for sure a programming error! Make it obvious to the programmer by explicitly raising an error! if (null arr_List or null skp_Index) return </pre>



    The interface to your data structures seems not optimal. You are mixing two data types in one type. Actually the data structures that you have are:

    ListItem: one item in a list, with a successor, which builds together with other ListItems a linked list.
    ListContainer / LabeledLists: a Skip of 'labels/columns' with a root element of a linked list each.

    Therfore your class interface should probably look like this:



     

     

     

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">struct ListContainer {} // Properties: // Key: list label (string) Value: Root Item (LinkedList) // stores the column heads and the root list items Skip get_RootItems (LinkedList) { ... } void set_RootItems_(LinkedList, Skip) {... } // set the root element for list with label 'sLabel' void setRootItem (LinkedList, string sLabel, ListItem) { ... } // allows you to write insertItem( MyList["column"], "A") ListItem ::[] (LinkedList L, string label) { ...} // how about some syntactic sugar? myLinkedList["A"] <- "New Item" struct ListItem {} Properties: ListItem get_nextItem(ListItem) string get_Value(ListItem) Methods: // inserts the element sItem in the list starting at listStart insertItem (ListItem listStart, string sItem) </pre>


    Regarding the storage of the list items, you can use a global array for all list items (which makes the implementation easy and will work for large item counts). In this case a 'ListItem' is only a row number in the global array, which gets rid of DxlObjects altogether (remember the allocation list!). The basic approach for this that I always use is:

     

     

     

     

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">// Allocate initial memory for 10000 list items // one row is one ListItem, columns store the properties Array garListItemMemory = create(10000, 3 ) // stores the next row in the list memory array to be allocated int giListItemHandleCount = 0 // This skip stores the rows that have been invalidated, i.e. deleted and can be reused Skip skFreeListItemNodes = create() int giFreeListItemNodes = 0 struct ListItem {} // ... Properties ... ListItem getNext (ListItem x) { return (get(garListItemMemory, (addr_ x) int, 0)) ListItem } void setNext_ (ListItem x, ListItem val ) { put(garListItemMemory, val, (addr_ x) int, 0) } string getValue (ListItem x) { return (get(garListItemMemory, (addr_ x) int, 1)) ListItem } void setValue (ListItem x, ListItem val ) { put(garListItemMemory, val, (addr_ x) int, 1) } // constructor & destructor for List ListItem createListItem_ () { ListItem x = null // reuse an existing list nodem if possible if (giFreeListItemNodes > 0) { // print "Reallocating Stack Nr " giFreeListItemNodes "\n" if (!find(skFreeListItemNodes, giFreeListItemNodes--, x)) error "ListItem memory error!" } else { // allocate a new row: Note that a ListItem now is only a single number! x = (addr_ (++giListItemHandleCount) ) ListItem; } // print "Allocated ListItem node " ((addr_ x) int) "\n" return x } void deleteListItem (ListItem &t) { // put in free list nodes ListItem deref = t put (skFreeListItemNodes, ++giFreeListItemNodes, deref, true) // print "Freeing ListItem Slot: " (listItemHandle t)" in Stack Nr: " (giFreeListItemNodes-1) "\n" // Set all properties to zero here, so your array will be nice and clean! setValue (t, "") setNext_ (t, null ListItem t = null } // ... implement append, delete, etc. .... </pre>



    Note that even if you decide, you need different 'memories' (Arrays) for storing different lists or list sets, this is still completely independed from the 'labels' that you put on the lists. If you decide you want to store a vast amount of items, and do not want that one huge array, this can be solved much more elegantly. With the above approach of making ListItem a separate struct a search can be done using the following code:



     

     

     

     

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">ListItem I = myLinkedList["A"] while (!null getNext I) { print "Value:" (getValue I) "\n"; I = getNext I } </pre>



    From the user code, no need to store the search values anymore. However it might be worth to discuss different approaches to storing the data. I have implemented three other datatypes which would allow to store the data that you store in the 'LinkedList':



     

     

     

    • Tree (A ordered Tree Structure like the Objects of a DOORS Module)
    • Map (Basically a M:N mapping using a Skip in Skip approach, which allows to store value pairs A:A, A:B, A:C, B:A and afterwards answers questions like "Give me the left side values of the right side value 'B',give me all left side values, etc.)
    • Sparse Array (Represents a very large array where all available indexes can be used without running into memory problems. The approach here is that the virtual array is partitioned into smaller rectangular arrays of size 64kb which are allocated on demand)


    Depending on what data you want to store and the performance you need one or the other data type might be beneficial. What data are you actually trying to store?

    Maybe that helps, Regards, Mathias

     

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

    So I dipped my toes in the water and you threw me into the deep end; but I figured that you would, thanks. You know, back in school I was head of my class on this data structure stuff. Never used it since and its not like riding a bike.

    Anyway, the underlying "Array" inside a "DxlObject" equated to some new "struct" is suitable for this task?

    Preamble
    My immediate task is this: given an interface from equipment eS (source) to equipment eD (destination) that may be along circuit cI, I want to associate cI both eS and eD. Both eS and eD are involved in other interfaces along other circuits. After parsing all the interfaces, I want to get the list of all circuits associated with each equipment. I see 50,000 pieces of equipment making the natural Skip List for each equipment approach unmanageable. Having an Array with 50,000 rows and X columns; where "X" is the most circuits associated with any equipment (45); a 50,000 X 45 Array is exceeding memory.

    So I figured I needed user functions that use memory linearly:
    • Declare intention to associate things like "X" with things like "Y"
    • Associate X with Y. Repeat
    • Loop through all the associates of Y.
    Note that you can indeed do these:
    • Associate X with Y1 .. (circuit X is associated with another equipment)
    • Associate Y with X ... (circuits and equipment can be spelled the same way)
    • Associate Y with Y ... (ditto)
    • Associate X with Y in a completely different context such as "Associate Document X with Equipment Y", where a circuit and a document can be spelled the same way.

    So I believe I need one container for each kind of relationship; in the above case there would be two: "Equipment Circuits" and "Equipment Documents". The code fails to mention that and I guess therefor you missed that.

    Responses
    • I think you are saying remove the ampersand: void fLList_Put(LinkedList & in_LList, string in_NameList, in_Item)
      • what about in the delete function: void fLList_Delete(LinkedList &in_LList)
    • I suppose the 1st line is a little easier to read than the 2nd; although as an old-schooler the equal sign is within my comfort zone.
      • fLList_Set_Tally (LList, 0)
      • dxloList->c_LList_Field_Tally = 0
    • Programatic Error Handling is always my Achilies heel. I should have some sort of "Hey! Program coding bug, please notify Louie with this information"... I suppose I can hold my nose and just print the error.
    • I guess I don't need to put the root value into the Array; let the 'int' Data of the Skip point to the 1st element.
    • I may not be reading your response here correctly, but let me say
      • I do not want the user to say "Start a new list for equipment 'A'"; and then "make 'B' its 1st element". I want the user to say "'A' has associate 'B'" and not care if 'A' has any other associations (yet).
      • A straight Skip List for root values is sufficient; I see no particular reason to create a structure to simulate it. Keep in mind I do not want to be in the 1990s.
    • Your comment about a single Global List for Items doesn't work since I need separate contexts for relationships.
    • I like your reference to a "ListSet" and that's better than my "LinkedList", which is implementation the user need not be told about.
    • I got lost about half way down your post.
    • I think I need to add some form of "Loop through all the List names".

    I will say I care a great deal about "understandability". The user-interface to this suite needs to be "simple" and "elegant"; and the entire suite needs to be "understandable", not just the topmost get and put functions.

    I think I'll climb down the ladder into the deep end.

    -Louie

    Note: "Back in school" of course means before there were actual computers, just theoretical ones. A "monitor" was the dude with the notepad wandering the halls. "Download" was done with the bathroom door shut. A "bug" was a cockroach (really, stuck on the wiring shorting out the circuits).
  • Mathias Mamsch
    Mathias Mamsch
    1969 Posts

    Re: LinkList

    ‏2012-02-20T21:32:48Z  
    • llandale
    • ‏2012-02-20T17:52:15Z
    So I dipped my toes in the water and you threw me into the deep end; but I figured that you would, thanks. You know, back in school I was head of my class on this data structure stuff. Never used it since and its not like riding a bike.

    Anyway, the underlying "Array" inside a "DxlObject" equated to some new "struct" is suitable for this task?

    Preamble
    My immediate task is this: given an interface from equipment eS (source) to equipment eD (destination) that may be along circuit cI, I want to associate cI both eS and eD. Both eS and eD are involved in other interfaces along other circuits. After parsing all the interfaces, I want to get the list of all circuits associated with each equipment. I see 50,000 pieces of equipment making the natural Skip List for each equipment approach unmanageable. Having an Array with 50,000 rows and X columns; where "X" is the most circuits associated with any equipment (45); a 50,000 X 45 Array is exceeding memory.

    So I figured I needed user functions that use memory linearly:
    • Declare intention to associate things like "X" with things like "Y"
    • Associate X with Y. Repeat
    • Loop through all the associates of Y.
    Note that you can indeed do these:
    • Associate X with Y1 .. (circuit X is associated with another equipment)
    • Associate Y with X ... (circuits and equipment can be spelled the same way)
    • Associate Y with Y ... (ditto)
    • Associate X with Y in a completely different context such as "Associate Document X with Equipment Y", where a circuit and a document can be spelled the same way.

    So I believe I need one container for each kind of relationship; in the above case there would be two: "Equipment Circuits" and "Equipment Documents". The code fails to mention that and I guess therefor you missed that.

    Responses
    • I think you are saying remove the ampersand: void fLList_Put(LinkedList & in_LList, string in_NameList, in_Item)
      • what about in the delete function: void fLList_Delete(LinkedList &in_LList)
    • I suppose the 1st line is a little easier to read than the 2nd; although as an old-schooler the equal sign is within my comfort zone.
      • fLList_Set_Tally (LList, 0)
      • dxloList->c_LList_Field_Tally = 0
    • Programatic Error Handling is always my Achilies heel. I should have some sort of "Hey! Program coding bug, please notify Louie with this information"... I suppose I can hold my nose and just print the error.
    • I guess I don't need to put the root value into the Array; let the 'int' Data of the Skip point to the 1st element.
    • I may not be reading your response here correctly, but let me say
      • I do not want the user to say "Start a new list for equipment 'A'"; and then "make 'B' its 1st element". I want the user to say "'A' has associate 'B'" and not care if 'A' has any other associations (yet).
      • A straight Skip List for root values is sufficient; I see no particular reason to create a structure to simulate it. Keep in mind I do not want to be in the 1990s.
    • Your comment about a single Global List for Items doesn't work since I need separate contexts for relationships.
    • I like your reference to a "ListSet" and that's better than my "LinkedList", which is implementation the user need not be told about.
    • I got lost about half way down your post.
    • I think I need to add some form of "Loop through all the List names".

    I will say I care a great deal about "understandability". The user-interface to this suite needs to be "simple" and "elegant"; and the entire suite needs to be "understandable", not just the topmost get and put functions.

    I think I'll climb down the ladder into the deep end.

    -Louie

    Note: "Back in school" of course means before there were actual computers, just theoretical ones. A "monitor" was the dude with the notepad wandering the halls. "Download" was done with the bathroom door shut. A "bug" was a cockroach (really, stuck on the wiring shorting out the circuits).

    Hmm... I am not sure if I was helpful, or destructive. The former one was my intention ... Well nevertheless I will try to explain.

    The thing regarding references. I just wanted to ask, if you noticed that

    void func(Skip &ref) {
      if (null ref) print "Null Skip was passed!"
    }
     
    Skip sk = null; func (sk)
    

     


    will not print the message, since 'ref' is actually referencing to sk and therefore is not null. I noticed that code in the put function of the linked list. The delete function is the only place where you actually need the reference and there you need to dereference the reference first before checking for null:

     

     

    void delete (Skip &ref) {
       Skip sk = ref // dereference
       if (null sk) return 
       delete sk
       ref = null
    }
    



    I might have gone overboard with all that software design stuff, but when making library code I am a strong advocate maintainabiliy and reuse through 'divide and conquer'. The simple 'List' that you implemented in that array is actually a datatype that can be used for all kinds of stuff, without the need for tailoring to a specific purpose. Therefore it should go to its own library and to its own type.

    The relationships that you want to store in those lists, do not need to care about the implementation of the list anymore. They just use it. In my opinion that will make your code more readable, since you can have that list in its own include file, and only if the programmer wants to know, how to insert a new item to a list, he opens the file and actually reads the code. So I find that you DO want the programmer of the ListSet/LinkedList to say "Start a New List for Label 'A'" and append the values X,Y and Z to it. But then there is the 'user' of that ListSet/LinkedList and he will not care anymore on how the ListSet/LinkedList handles its relationships internally. So there are different 'layers' in your code, that, if you keep them separate, in my opinion makes your code better: more reusable, testable and maintainable.

    Since 100 lines of code say more than 10000 words, I have attached a refactored example of your code. Note how ListItem is completely separated and independend from LinkedList. If you later decide, you want to make ListItem a double linked list (storing predecessor and successor) then LinkedList can stay 100% the same. Notice how both Instances reside in their own global array. You can have as many ListItem instances as you want and as many LinkedLists as you want, which are completely independent from each other. You still have only 2 global arrays allocated and a skip list each for reusing deleted elements. Notice how small the user code of for example the put function has become, after using the very general insertedSortedString Function of ListItem. In my opinion while I did not spend a lot of accuracy in naming variables and making comments, the code is easy to understand and maintain, especially if you leave out the boilerplate code for the structures. Notice that the boilerplate for LinkedList and ListItem is completly equal, it is just the type name that changes and the set of properties.

    Maybe that explains more what I had in mind, regards, Mathias



     

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

    Updated on 2014-01-06T17:32:33Z at 2014-01-06T17:32:33Z by iron-man
  • llandale
    llandale
    2972 Posts

    Re: LinkList

    ‏2012-02-21T15:53:42Z  

    Hmm... I am not sure if I was helpful, or destructive. The former one was my intention ... Well nevertheless I will try to explain.

    The thing regarding references. I just wanted to ask, if you noticed that

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">void func(Skip &ref) { if (null ref) print "Null Skip was passed!" } Skip sk = null; func (sk) </pre>

     


    will not print the message, since 'ref' is actually referencing to sk and therefore is not null. I noticed that code in the put function of the linked list. The delete function is the only place where you actually need the reference and there you need to dereference the reference first before checking for null:

     

     

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">void delete (Skip &ref) { Skip sk = ref // dereference if (null sk) return delete sk ref = null } </pre>



    I might have gone overboard with all that software design stuff, but when making library code I am a strong advocate maintainabiliy and reuse through 'divide and conquer'. The simple 'List' that you implemented in that array is actually a datatype that can be used for all kinds of stuff, without the need for tailoring to a specific purpose. Therefore it should go to its own library and to its own type.

    The relationships that you want to store in those lists, do not need to care about the implementation of the list anymore. They just use it. In my opinion that will make your code more readable, since you can have that list in its own include file, and only if the programmer wants to know, how to insert a new item to a list, he opens the file and actually reads the code. So I find that you DO want the programmer of the ListSet/LinkedList to say "Start a New List for Label 'A'" and append the values X,Y and Z to it. But then there is the 'user' of that ListSet/LinkedList and he will not care anymore on how the ListSet/LinkedList handles its relationships internally. So there are different 'layers' in your code, that, if you keep them separate, in my opinion makes your code better: more reusable, testable and maintainable.

    Since 100 lines of code say more than 10000 words, I have attached a refactored example of your code. Note how ListItem is completely separated and independend from LinkedList. If you later decide, you want to make ListItem a double linked list (storing predecessor and successor) then LinkedList can stay 100% the same. Notice how both Instances reside in their own global array. You can have as many ListItem instances as you want and as many LinkedLists as you want, which are completely independent from each other. You still have only 2 global arrays allocated and a skip list each for reusing deleted elements. Notice how small the user code of for example the put function has become, after using the very general insertedSortedString Function of ListItem. In my opinion while I did not spend a lot of accuracy in naming variables and making comments, the code is easy to understand and maintain, especially if you leave out the boilerplate code for the structures. Notice that the boilerplate for LinkedList and ListItem is completly equal, it is just the type name that changes and the set of properties.

    Maybe that explains more what I had in mind, regards, Mathias



     

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

    Dang, had already re-written it. I can see your brilliance here on the Horizon, but I'm not ready for that yet; psycologically I'm still "inside the box".

    Renamed "List" to "Key" and "LinkList" to "ListSet". Along with a "GetNextItem(LSet, NameKey)" function I tried to add a "GetNextKey(LSet)" function. I implemented it poorly, browsing the underlying Skip of Keys continually looking for the last one returned then returning the next one. I figure to implement it with a 2nd Skip list and figuring to add the Keys themselves to their own linked list in the Array.

    For a ListSet of Teachers for each Student, the psuedo code for using it would be:
    NameStudent = fListSet_GetNext_Key (LSet_Teachers)
    while(not null NameStudent)
    {

    • NameTeacher = fListSet_GetNext_Item (LSet_Teachers, NameStudent)
    • while(!null NameTeacher)
    • {
      • Deal with this NameStudent -> NameTeacher relationship
      • NameTeacher = fListSet_GetNext_Item (LSet_Teachers, NameStudent) // Get next Teacher
    • } // end teachers for this student
    • NameStudent = fListSet_GetNext_Key (LSet_Teachers) // Get next Student

    } // end for every student

    Unless of course someone can show my how to implement this "do" loop:
    void ::do(string, ListSet,void); which looks like:

    • for NameStudent in LSet_Teachers do

    of perhaps also:

    • for NameTeacher in current(LSet_Teachers) do

    Making the code rather "elegant":

    for NameStudent in LSet_Teachers do
    {  for NameTeacher in current(LSet_Teachers) do
       {  Report Student-Teacher relationship
       }
    }
    


    -Louie

    I strangely recall the time my Mom dragged me "Kicking and Screaming" to Kindergarten...

    Updated on 2014-01-06T17:33:22Z at 2014-01-06T17:33:22Z by iron-man
  • llandale
    llandale
    2972 Posts

    Re: LinkList

    ‏2012-02-21T16:35:33Z  

    Hmm... I am not sure if I was helpful, or destructive. The former one was my intention ... Well nevertheless I will try to explain.

    The thing regarding references. I just wanted to ask, if you noticed that

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">void func(Skip &ref) { if (null ref) print "Null Skip was passed!" } Skip sk = null; func (sk) </pre>

     


    will not print the message, since 'ref' is actually referencing to sk and therefore is not null. I noticed that code in the put function of the linked list. The delete function is the only place where you actually need the reference and there you need to dereference the reference first before checking for null:

     

     

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">void delete (Skip &ref) { Skip sk = ref // dereference if (null sk) return delete sk ref = null } </pre>



    I might have gone overboard with all that software design stuff, but when making library code I am a strong advocate maintainabiliy and reuse through 'divide and conquer'. The simple 'List' that you implemented in that array is actually a datatype that can be used for all kinds of stuff, without the need for tailoring to a specific purpose. Therefore it should go to its own library and to its own type.

    The relationships that you want to store in those lists, do not need to care about the implementation of the list anymore. They just use it. In my opinion that will make your code more readable, since you can have that list in its own include file, and only if the programmer wants to know, how to insert a new item to a list, he opens the file and actually reads the code. So I find that you DO want the programmer of the ListSet/LinkedList to say "Start a New List for Label 'A'" and append the values X,Y and Z to it. But then there is the 'user' of that ListSet/LinkedList and he will not care anymore on how the ListSet/LinkedList handles its relationships internally. So there are different 'layers' in your code, that, if you keep them separate, in my opinion makes your code better: more reusable, testable and maintainable.

    Since 100 lines of code say more than 10000 words, I have attached a refactored example of your code. Note how ListItem is completely separated and independend from LinkedList. If you later decide, you want to make ListItem a double linked list (storing predecessor and successor) then LinkedList can stay 100% the same. Notice how both Instances reside in their own global array. You can have as many ListItem instances as you want and as many LinkedLists as you want, which are completely independent from each other. You still have only 2 global arrays allocated and a skip list each for reusing deleted elements. Notice how small the user code of for example the put function has become, after using the very general insertedSortedString Function of ListItem. In my opinion while I did not spend a lot of accuracy in naming variables and making comments, the code is easy to understand and maintain, especially if you leave out the boilerplate code for the structures. Notice that the boilerplate for LinkedList and ListItem is completly equal, it is just the type name that changes and the set of properties.

    Maybe that explains more what I had in mind, regards, Mathias



     

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

    As far as noticing that reference thing...

    No I hadn't noticed that. And yes I've got that all over the place. Makes me wonder how I managed to write 100 or so such functions and not actually test an actual null input structure. (OK, so all my production code always DOES correctly create the Skip lists before trying to delete them.)

    Somehow I got the notion that since the calling parameter was already a reference, the ampersand did nothing. Have reviewed your superior thread on that subject here, thanks:
    https://www.ibm.com/developerworks/forums/message.jspa?messageID=14683292#14683292

    Gads. Good new is that I can easily search for "&" in all my library and fix it.

    Is this a reasonable solution? Write an "isNull" function for each of the various datatypes:

    bool isNull(Skip skp)   {  return(null skp) }
     
    void deleteSkip (Skip &ref) {
       if (isNull ref) {print "cannot delete a null Skip\n"; return}
       delete ref
       ref = null
    }
    Skip sk = null; deleteSkip (sk)
    print "Done.  now null: " (null sk) "\t" (isNull sk) "\n"
    sk = create(); deleteSkip (sk)
    print "Done.  now null: " (null sk) "\t" (isNull sk) "\n"
    


    -Louie

    Updated on 2014-01-06T17:34:03Z at 2014-01-06T17:34:03Z by iron-man
  • llandale
    llandale
    2972 Posts

    Re: LinkList

    ‏2012-02-21T19:46:31Z  
    • llandale
    • ‏2012-02-21T16:35:33Z

    As far as noticing that reference thing...

    No I hadn't noticed that. And yes I've got that all over the place. Makes me wonder how I managed to write 100 or so such functions and not actually test an actual null input structure. (OK, so all my production code always DOES correctly create the Skip lists before trying to delete them.)

    Somehow I got the notion that since the calling parameter was already a reference, the ampersand did nothing. Have reviewed your superior thread on that subject here, thanks:
    https://www.ibm.com/developerworks/forums/message.jspa?messageID=14683292#14683292

    Gads. Good new is that I can easily search for "&" in all my library and fix it.

    Is this a reasonable solution? Write an "isNull" function for each of the various datatypes:

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">bool isNull(Skip skp) { return(null skp) } void deleteSkip (Skip &ref) { if (isNull ref) {print "cannot delete a null Skip\n"; return} delete ref ref = null } Skip sk = null; deleteSkip (sk) print "Done. now null: " (null sk) "\t" (isNull sk) "\n" sk = create(); deleteSkip (sk) print "Done. now null: " (null sk) "\t" (isNull sk) "\n" </pre>


    -Louie

    actually:
    • if ( null ref or isNull ref) {print "cannot delete a null Skip\n"; return}
  • Mathias Mamsch
    Mathias Mamsch
    1969 Posts

    Re: LinkList

    ‏2012-02-22T16:08:28Z  
    • llandale
    • ‏2012-02-21T16:35:33Z

    As far as noticing that reference thing...

    No I hadn't noticed that. And yes I've got that all over the place. Makes me wonder how I managed to write 100 or so such functions and not actually test an actual null input structure. (OK, so all my production code always DOES correctly create the Skip lists before trying to delete them.)

    Somehow I got the notion that since the calling parameter was already a reference, the ampersand did nothing. Have reviewed your superior thread on that subject here, thanks:
    https://www.ibm.com/developerworks/forums/message.jspa?messageID=14683292#14683292

    Gads. Good new is that I can easily search for "&" in all my library and fix it.

    Is this a reasonable solution? Write an "isNull" function for each of the various datatypes:

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">bool isNull(Skip skp) { return(null skp) } void deleteSkip (Skip &ref) { if (isNull ref) {print "cannot delete a null Skip\n"; return} delete ref ref = null } Skip sk = null; deleteSkip (sk) print "Done. now null: " (null sk) "\t" (isNull sk) "\n" sk = create(); deleteSkip (sk) print "Done. now null: " (null sk) "\t" (isNull sk) "\n" </pre>


    -Louie

    Funny thing. This seems to work, although I really cannot tell why on the first glance. It seems the DXL interpreter will dereference automatically here, before calling null. Seems to have problems casting from _y& to _n ;-)
     

    // I am sure I have seen references to underscore types work! 
    // The DXL interpeter seems to do its magic dereferencing before passing to 'null'. 
    bool isNull (_y &ref) { return null ref }
     
    bool func(Skip &ref) { return isNull ref }
    bool func2(Skip sk) { return isNull sk }
     
    Skip sk = null
     
    print "Null: " (isNull sk) "\n"
    print "Null: " (func   sk) "\n"
    print "Null: " (func2  sk) "\n"
     
    sk  = create() 
     
    print "Not Null: " (isNull sk) "\n"
    print "Not Null: " (func   sk) "\n"
    print "Not Null: " (func2  sk) "\n"
     
     
    delete sk
     
    Skip n () { return null Skip }
     
    // print (isNull (null Skip))  // this is not possible! DXL interpreter jumps in here!
    // print (isNull ( n() ))  // this neither! DXL interpreter jumps in here!
    

     

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

     

    Updated on 2014-01-06T17:34:45Z at 2014-01-06T17:34:45Z by iron-man
  • llandale
    llandale
    2972 Posts

    Re: LinkList

    ‏2012-02-22T18:41:27Z  

    Funny thing. This seems to work, although I really cannot tell why on the first glance. It seems the DXL interpreter will dereference automatically here, before calling null. Seems to have problems casting from _y& to _n ;-)
     

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">// I am sure I have seen references to underscore types work! // The DXL interpeter seems to do its magic dereferencing before passing to 'null'. bool isNull (_y &ref) { return null ref } bool func(Skip &ref) { return isNull ref } bool func2(Skip sk) { return isNull sk } Skip sk = null print "Null: " (isNull sk) "\n" print "Null: " (func sk) "\n" print "Null: " (func2 sk) "\n" sk = create() print "Not Null: " (isNull sk) "\n" print "Not Null: " (func sk) "\n" print "Not Null: " (func2 sk) "\n" delete sk Skip n () { return null Skip } // print (isNull (null Skip)) // this is not possible! DXL interpreter jumps in here! // print (isNull ( n() )) // this neither! DXL interpreter jumps in here! </pre>

     

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

     

    As for the body of your example.
    [1] When I re-word the text of the last 3 print statements:

    • print "create: " (isNull sk) "\n"
    • print "create: " (func sk) "\n"
    • print "create: " (func2 sk) "\n"

    I get this incorrect output:

    • Null: true
    • Null: true
    • Null: true
    • create: true
    • create: true
    • create: true

    [2] When I replace the isNull function to be specifically for Skips

    • bool isNull(Skip &ref) {return null ref}

    I get this incorrect output:

    • Null: false
    • Null: false
    • Null: false
    • create: false
    • create: false
    • create: false

    So neither your "_y" generic nor my "Skip" specific isNull works.
    [3] When I type randomly and eventually come up with this version:

    • bool isNull_DeRef (Skip ref) {return null ref}
    • bool isNull(Skip &ref) {return (null ref or isNull_DeRef (ref))}

    I get this correct output:

    • Null: true
    • Null: true
    • Null: true
    • create: false
    • create: false
    • create: false


    Seems to be a winner, but I don't understand [1] nor [3] :); and only understand [2] because I keep re-reading your tutorial post over and over.

    As for your last two error lines: Seems to me that a function that uses "&" to Call-By-Reference requires the calling parameter to be a variable since the function is announcing its intention to modify it. You should not send a constant nor the output of a function since these cannot realistically be modified. I therefore suggest the DXL errors are appropriate.

     

    int  Get(int i){return i++}
    void Set(int &i) {i++}
    int j = 0
    Set(j)      // OK; Set() can change the value of a variable
    Set(10)     // Interpret Errors; Set() cannot modify a constant
    Set(Get(j)) // Interpret Errors; Set() cannot modify the output of some function
    


    -Louie

     

    Updated on 2014-01-06T17:35:26Z at 2014-01-06T17:35:26Z by iron-man
  • Mathias Mamsch
    Mathias Mamsch
    1969 Posts

    Re: LinkList

    ‏2012-02-22T19:25:59Z  
    • llandale
    • ‏2012-02-22T18:41:27Z

    As for the body of your example.
    [1] When I re-word the text of the last 3 print statements:

    • print "create: " (isNull sk) "\n"
    • print "create: " (func sk) "\n"
    • print "create: " (func2 sk) "\n"

    I get this incorrect output:

    • Null: true
    • Null: true
    • Null: true
    • create: true
    • create: true
    • create: true

    [2] When I replace the isNull function to be specifically for Skips

    • bool isNull(Skip &ref) {return null ref}

    I get this incorrect output:

    • Null: false
    • Null: false
    • Null: false
    • create: false
    • create: false
    • create: false

    So neither your "_y" generic nor my "Skip" specific isNull works.
    [3] When I type randomly and eventually come up with this version:

    • bool isNull_DeRef (Skip ref) {return null ref}
    • bool isNull(Skip &ref) {return (null ref or isNull_DeRef (ref))}

    I get this correct output:

    • Null: true
    • Null: true
    • Null: true
    • create: false
    • create: false
    • create: false


    Seems to be a winner, but I don't understand [1] nor [3] :); and only understand [2] because I keep re-reading your tutorial post over and over.

    As for your last two error lines: Seems to me that a function that uses "&" to Call-By-Reference requires the calling parameter to be a variable since the function is announcing its intention to modify it. You should not send a constant nor the output of a function since these cannot realistically be modified. I therefore suggest the DXL errors are appropriate.

     

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">int Get(int i){return i++} void Set(int &i) {i++} int j = 0 Set(j) // OK; Set() can change the value of a variable Set(10) // Interpret Errors; Set() cannot modify a constant Set(Get(j)) // Interpret Errors; Set() cannot modify the output of some function </pre>


    -Louie

     

    LoL. Okay that explains it. I misread the output, it did NOT work. So as I intended to write in the first place you need the following function:
     

    // dereference the reference before null checking ...  
    bool isNull (_y &ref) { 
        int &a = addr_ ref;  // cast to int, otherwise the DXL interpeter goes berserk
        int b = a;    // dereference
        return null b  // now do the null check 
    }
    

     


    Regards, Mathias

     

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

    Updated on 2014-01-06T17:35:56Z at 2014-01-06T17:35:56Z by iron-man
  • llandale
    llandale
    2972 Posts

    Re: LinkList

    ‏2012-02-22T20:29:26Z  

    LoL. Okay that explains it. I misread the output, it did NOT work. So as I intended to write in the first place you need the following function:
     

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">// dereference the reference before null checking ... bool isNull (_y &ref) { int &a = addr_ ref; // cast to int, otherwise the DXL interpeter goes berserk int b = a; // dereference return null b // now do the null check } </pre>

     


    Regards, Mathias

     

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

    Seems to work for "int", "char", "Object", and "Array", but not for "string"

    bool isNull (_y &ref) { 
        int &a = addr_ ref;  // cast to int, otherwise the DXL interpeter goes berserk
        int b = a;    // dereference
        return null b  // now do the null check 
    }
     
    bool    isNullRef(string &s) {return isNull s}
    bool    IsNullVal(string s)  {return isNull s}
     
    string s
    s = " ";      print "Null s=space\t" (isNull s) "\t" (isNullRef s)"\t" (IsNullVal s) "\n"
    s = "";       print "Null s=\"\"\t"   (isNull s) "\t" (isNullRef s)"\t" (IsNullVal s) "\n"
    s = null;       print "Null s=null\t"   (isNull s) "\t" (isNullRef s)"\t" (IsNullVal s) "\n"
    


    I get these results; the last two lines should all be "true"

     

    • Null s=space false false false
    • Null s="" false false false
    • Null s=null false false false

    -Louie

     

    Updated on 2014-01-06T17:36:35Z at 2014-01-06T17:36:35Z by iron-man
  • Mathias Mamsch
    Mathias Mamsch
    1969 Posts

    Re: LinkList

    ‏2012-02-22T20:48:21Z  
    • llandale
    • ‏2012-02-22T20:29:26Z

    Seems to work for "int", "char", "Object", and "Array", but not for "string"

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">bool isNull (_y &ref) { int &a = addr_ ref; // cast to int, otherwise the DXL interpeter goes berserk int b = a; // dereference return null b // now do the null check } bool isNullRef(string &s) {return isNull s} bool IsNullVal(string s) {return isNull s} string s s = " "; print "Null s=space\t" (isNull s) "\t" (isNullRef s)"\t" (IsNullVal s) "\n" s = ""; print "Null s=\"\"\t" (isNull s) "\t" (isNullRef s)"\t" (IsNullVal s) "\n" s = null; print "Null s=null\t" (isNull s) "\t" (isNullRef s)"\t" (IsNullVal s) "\n" </pre>


    I get these results; the last two lines should all be "true"

     

    • Null s=space false false false
    • Null s="" false false false
    • Null s=null false false false

    -Louie

     

    Ok, we are getting closer. Of course we need additional ones for real and string (as the perms list has), since they do not have a 0 null value, but a null constant (empty string / 0.0 real value):

    bool isNull (_y &ref) { 
        int &a = addr_ ref;  // cast to int, otherwise the DXL interpeter goes berserk
        int b = a;    // dereference
        return null b  // now do the null check 
    }
     
    bool isNull (string &ref) { 
        string b = ref;    // dereference
        return null b  // now do the null check 
    }
     
    bool isNull (real &ref) { 
        real b = ref;    // dereference
        return null b  // now do the null check 
    }
     
     
    bool func(Skip &ref) { return isNull ref }
    bool func2(Skip sk) { return isNull sk }
     
    Skip sk = null
     
    print "Null: " (isNull sk) "\n"
    print "Null: " (func   sk) "\n"
    print "Null: " (func2  sk) "\n"
     
    sk  = create() 
     
    print "Created: " (isNull sk) "\n"
    print "Created: " (func   sk) "\n"
    print "Created: " (func2  sk) "\n"
     
    delete sk
     
    {
      string s = null; 
      print "NullString: " (isNull s) "\n"
      s = "Hallo"
      print "Created String: " (isNull s) "\n"
    }
     
    {
      real s = null; 
      print "Null Real: " (isNull s) "\n"
      s = 1.0
      print "Created Real: " (isNull s) "\n"
    }
     
    Skip n () { return null Skip } 
    // print (isNull (null Skip))  // this is not possible! DXL interpreter jumps in here!
    // print (isNull ( n() ))  // this neither! DXL interpreter jumps in here!
    

     

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

     

    Updated on 2014-01-06T17:37:20Z at 2014-01-06T17:37:20Z by iron-man
  • llandale
    llandale
    2972 Posts

    Re: LinkList

    ‏2012-02-23T18:25:14Z  

    Ok, we are getting closer. Of course we need additional ones for real and string (as the perms list has), since they do not have a 0 null value, but a null constant (empty string / 0.0 real value):

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">bool isNull (_y &ref) { int &a = addr_ ref; // cast to int, otherwise the DXL interpeter goes berserk int b = a; // dereference return null b // now do the null check } bool isNull (string &ref) { string b = ref; // dereference return null b // now do the null check } bool isNull (real &ref) { real b = ref; // dereference return null b // now do the null check } bool func(Skip &ref) { return isNull ref } bool func2(Skip sk) { return isNull sk } Skip sk = null print "Null: " (isNull sk) "\n" print "Null: " (func sk) "\n" print "Null: " (func2 sk) "\n" sk = create() print "Created: " (isNull sk) "\n" print "Created: " (func sk) "\n" print "Created: " (func2 sk) "\n" delete sk { string s = null; print "NullString: " (isNull s) "\n" s = "Hallo" print "Created String: " (isNull s) "\n" } { real s = null; print "Null Real: " (isNull s) "\n" s = 1.0 print "Created Real: " (isNull s) "\n" } Skip n () { return null Skip } // print (isNull (null Skip)) // this is not possible! DXL interpreter jumps in here! // print (isNull ( n() )) // this neither! DXL interpreter jumps in here! </pre>

     

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

     

    I got the generic one to break.

    bool isNull (_y &ref) { 
        int &a = addr_ ref;  // cast to int, otherwise the DXL interpeter goes berserk
        int b = a;    // dereference
        return null b  // now do the null check 
    }
    struct CL {}
    CL    create() {int d = 1; CL cl = (CL addr_ d); return(cl)}
     
    CL      cl1 = null,
            cl2 = create(),
            cl3     // <<-- remains undefined
     
    print "cl1\t" (isNull(cl1)) "\n"    // true  OK
    print "cl2\t" (isNull(cl2)) "\n"    // false OK
    print "cl3\t" (isNull(cl3)) "\n"    // <Line:3> unassigned variable (a) <int b = a>
    


    Same results when using a Skip. That's unfair of me right?
    Can you think of any situation inserting this line is needed?

     

    • if (null ref) then return(false)


    -Louie

     

    Updated on 2014-01-06T17:38:06Z at 2014-01-06T17:38:06Z by iron-man
  • Mathias Mamsch
    Mathias Mamsch
    1969 Posts

    Re: LinkList

    ‏2012-02-24T12:21:47Z  
    • llandale
    • ‏2012-02-23T18:25:14Z

    I got the generic one to break.

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">bool isNull (_y &ref) { int &a = addr_ ref; // cast to int, otherwise the DXL interpeter goes berserk int b = a; // dereference return null b // now do the null check } struct CL {} CL create() {int d = 1; CL cl = (CL addr_ d); return(cl)} CL cl1 = null, cl2 = create(), cl3 // <<-- remains undefined print "cl1\t" (isNull(cl1)) "\n" // true OK print "cl2\t" (isNull(cl2)) "\n" // false OK print "cl3\t" (isNull(cl3)) "\n" // <Line:3> unassigned variable (a) <int b = a> </pre>


    Same results when using a Skip. That's unfair of me right?
    Can you think of any situation inserting this line is needed?

     

    • if (null ref) then return(false)


    -Louie

     

    Well I guess an unassigned variable would cause every function to break, that you pass that variable to? The question is would you want an not assigned variable to be reported as 'isNull'? I guess this would be doable:
     

    bool isNull (_y &ref) { 
        int &a = addr_ ref;  // cast to int, otherwise the DXL interpeter goes berserk
        int *ptr = &a; 
        if (*ptr == -2023406815) return true  // really?
        int b = a;    // dereference
        return null b  // now do the null check 
    }
     
    int c
     
    print (isNull c)
    

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

    Updated on 2014-01-06T17:38:42Z at 2014-01-06T17:38:42Z by iron-man
  • llandale
    llandale
    2972 Posts

    Re: LinkList

    ‏2012-02-24T15:53:08Z  

    Well I guess an unassigned variable would cause every function to break, that you pass that variable to? The question is would you want an not assigned variable to be reported as 'isNull'? I guess this would be doable:
     

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">bool isNull (_y &ref) { int &a = addr_ ref; // cast to int, otherwise the DXL interpeter goes berserk int *ptr = &a; if (*ptr == -2023406815) return true // really? int b = a; // dereference return null b // now do the null check } int c print (isNull c) </pre>

     


    Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

     

    Since an unassigned check is unreasonable, then your previous 3 functions cover everything, is that right?

    bool isNull (_y &ref) { 
        int &a = addr_ ref;  // cast to int, otherwise the DXL interpeter goes berserk
        int b = a;    // dereference
        return null b  // now do the null check 
    }
     
    bool isNull (string &ref) { 
        string b = ref;    // dereference
        return null b  // now do the null check 
    }
     
    bool isNull (real &ref) { 
        real b = ref;    // dereference
        return null b  // now do the null check 
    }
    
    Updated on 2014-01-06T17:39:19Z at 2014-01-06T17:39:19Z by iron-man