Function Overloading / ANYTYPE function inputs

PFollansbee
PFollansbee United States
edited July 27 in RAPID Programming
I am seeking to create a logging function that can accommodate any data type. As I know that traditional function overloading is not a thing in RAPID, I would like to be able to take in data types of "anytype" (similar to Type and ValToStr). The intention is to be able to split up composite data types into columns for placing in a CSV. This enables easy loading into a database or otherwise without post processing.

I see some workarounds here. Mutually exclusive optional parameters. ValToString used for all inputs followed by decomposition of brackets to pull out individual data. Individual functions based on type. Etc.

Function 'overloading' using anytype seems like it would be a much cleaner implementation though. Also anytype is used several times by system functions, so it would be nice to take advantage of it. Any way to accomplish function overloading in RS/RAPID?

Implementation would look something like below. I see the issue that would be flagged at runtime wherein calling attributes of value would not be so kosher because it is type-less until specified.

        string stLog,
        string stValueName,
        \num2 nDate,
        \num2 nTime,
        ANYTYPE value)
        
        VAR string stValueType;
        VAR string stDataLabel{4};
        VAR string stDataValue{4};
        VAR orient or1;
        
        stValueType := Type(value);
        
        TEST stValueType
        CASE "num": 
            stDataLabel{1} := stValueType;
            stDataValue{1} := ValToStr(value);
        CASE "dnum": 
            stDataLabel{1} := stValueType;
            stDataValue{1} := ValToStr(value);
        CASE "bool": 
            stDataLabel{1} := stValueType;
            stDataValue{1} := ValToStr(value);
        CASE "orient": 
            stDataLabel{1} := "orient Q1";
            stDataLabel{2} := "orient Q2";
            stDataLabel{3} := "orient Q3";
            stDataLabel{4} := "orient Q4";
            stDataValue{1} := ValToStr(value.q1);
            stDataValue{2} := ValToStr(value.q2);
            stDataValue{3} := ValToStr(value.q3);
            stDataValue{4} := ValToStr(value.q4);
        CASE "pos":
            stDataLabel{1} := "pos x";
            stDataLabel{2} := "pos y";
            stDataLabel{3} := "pos z";
            stDataValue{1} := ValToStr(value.x);
            stDataValue{1} := ValToStr(value.y);
            stDataValue{1} := ValToStr(value.z);
        DEFAULT: RETURN;
        ENDTEST
        !CODE GOES HERE - Output strings to CSV

Some threads that have asked similar but different questions:
https://forums.robotstudio.com/discussion/6677/function-overloading 
https://forums.robotstudio.com/discussion/12405/universal-data-type-function

Comments

  • Forge_Engineering
    Forge_Engineering Mackay, QLD, Australia
    edited July 28
    Hi PFollansbee, 

    I've seen those similar threads before as well, and looked into writing my own NumToString that allowed me to pad the string with 0's for printing purposes, amongst other wrapper functions as well.

    As far as I'm aware the #ANYTYPE datatype is unusable.
    I wonder whether you could create a custom addon that could use it if it is accessible to system functions and how hard that would be. 

    I can't see any perfect ways out of using switches or having individual functions or checks for every datatype, however here is a novel idea:

    The only way you can use the same command for any data type would be to use late binding, but then have a separate function to log each datatype, or just go with the function that has a switch for every datatype you need. 
    	PROC Main()
    		
    		VAR num n_foo := 1;
    		VAR dnum dn_bar := 3.14;
    		VAR string s_foobar := "qwerty";
    		VAR bool b_var := FALSE;
    		VAR pose ps_disp := [[1,2,3],[1,0,0,0]];
    		
    		TPErase;
    		
    		! log data 
    		%"log_"+Type(n_foo)% n_foo;
    		
    		%"log_"+Type(dn_bar)% dn_bar;
    		
    		%"log_"+Type(s_foobar)% s_foobar;
    		
    		%"log_"+Type(b_var)% b_var;
    		
    		%"log_"+Type(ps_disp)% ps_disp;
    		
    	ENDPROC
    		
    	PROC log_num(num Value)
    		TpWrite CDate() + " " + CTime() + ": " + ValToStr(Value);
    	ENDPROC
    	
    	PROC log_dnum(dnum Value)
    		TpWrite CDate() + " " + CTime() + ": " + ValToStr(Value);
    	ENDPROC
    	
    	PROC log_string(string Value)
    		TpWrite CDate() + " " + CTime() + ": " + ValToStr(Value);
    	ENDPROC
    	
    	PROC log_bool(bool Value)
    		TpWrite CDate() + " " + CTime() + ": " + ValToStr(Value);
    	ENDPROC
    	
    	PROC log_pose(pose Value)
    		TpWrite CDate() + " " + CTime() + ": " + ValToStr(Value);
    	ENDPROC

    RAPID falls short of a lot of languages, I had to write my own code to turn a datetime into a unix timestamp, and then to convert back again. but that's what makes it fun . . .

    Good Luck, 

    Harry