Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Ranges, Lambdas, on Fixed arrays of structs

hwillems
2023-08-31
2023-08-31
  • hwillems - 2023-08-31

    I do datastructures and algorithms in Codesys. For example a Struct of Person with thing's like IdNumber, Name, Age etc. as example.

    Now i do all kind of calculations, filters. So i have this pretty big Fixed Array with Structs. On this struct i want to do simple stuff you can do easily in C++/Python/Rust etc.

    For example i want to do this:
    AvererageAge := Average(Peoples.Age); Then it will return the average of all members ages. Or Sort struct on age etc. Or sort on alphabetical Name.

    Or use Lambda functions to filter/mutate out things like, filter out everybody above 18 years old. Or remove people who it's name start with "A".


    Currently i have to write my own custom function for example sorting on Age. And make a super specific function based on that particulare datastructure.

    Here an Example:

    (*Before calling this FIlter method, set the mNodeFilterSwitch to the desired filter.*)
    
    CASE mNodeFilterSelect OF
    
    
    (********************************[ Status Filters ]***********************************)
    
    NodeID:
        FOR x := ACS_OUT_BEGIN TO ACS_OUT_END BY 1 DO
            FOR y := ACS_IN_BEGIN TO ACS_IN_END BY 1 DO
                IF marrNode[y].Status.oiNodeID > marrNode[y + 1].Status.oiNodeID  THEN
                    mNodeTemp := marrNode[y + 1];
                    marrNode[y + 1] := marrNode[y];
                    marrNode[y] := mNodeTemp;
                END_IF;
            END_FOR;
        END_FOR;
    
    Started:
    FOR x := DES_OUT_BEGIN TO DES_OUT_END BY -1 DO
            FOR y := DES_IN_BEGIN TO DES_IN_END BY -1 DO
                IF marrNode[y].Status.oxStarted > marrNode[y - 1].Status.oxStarted THEN
                    mNodeTemp := marrNode[y - 1];
                    marrNode[y - 1] := marrNode[y];
                    marrNode[y] := mNodeTemp;
                END_IF;
            END_FOR;
        END_FOR;
    
    Starting:
    FOR x := DES_OUT_BEGIN TO DES_OUT_END BY -1 DO
            FOR y := DES_IN_BEGIN TO DES_IN_END BY -1 DO
                IF marrNode[y].Status.oxStarting > marrNode[y - 1].Status.oxStarting THEN
                    mNodeTemp := marrNode[y - 1];
                    marrNode[y - 1] := marrNode[y];
                    marrNode[y] := mNodeTemp;
                END_IF;
            END_FOR;
        END_FOR;
    
    END_CASE;
    

    I have like 30+ of these in the enum. Not really DRY code right?


    These are custom made bubble sort filters in a function. You pass in the Datastructure, and say what function you want. (This is an enum collection of sorting functions)
    And then the Array with Nodes of Structs gets ordered.

    Why can't we have Iterators and Lambda's and build in standard functions like regular languages?
    Also i use bubble sort because it's the easiest to implement because i can't get this to code DRY.

    Problem with ST (Even the new one with classes) that it's very limited for programming datastructures and algorithms. Yes you still not want dynamic memory and you need to choose the correct algorithm so you know the most extreme edge cases regarding the time it takes to execute the algorithms.(Real-time execution)

    How are other people dealing with this?

    Here for example saw some software using an adjusted ST language and having FOR EACH possibility:
    https://www.fernhillsoftware.com/help/iec-61131/structured-text/st-for-each.html

    You can then build your own custom Iterator functions.
    I wish the IEC 61131-3 standard would be more expressive and having more standard modern features, but still keep close to the fact of no dynamics memory and real-time systems.

     

    Last edit: hwillems 2023-08-31

Log in to post a comment.