Home AMX User Forum AMX Technical Discussion

Function parameter that can be either one device or an array of them?

I'm trying to write a function that I can call with either one dev or a dev array. I have some repetitive code that performs the same actions, but sometimes against a single device and sometimes against a device array. I'd like to be able to replace e.g.

on[dvTP_A,1];
send_command dvTP_A,"'^TXT',...";
...
on[dvAllTPs,1];
send_command dvAllTPs,"'^TXT',...";

with

fnFoo(dvTP_A);
fnFoo(dvAllTPs);

The body of the function only passes the parameter in question to built-ins like on, off, send_command, etc, and these can all take both dev and dev[] as the first argument, so I need a data type that can hold either.

Comments

  • SCamphaugSCamphaug Posts: 23

    I've always done it with two functions myself.

    DEFINE_FUNCTION TP_ShowPage(DEV Panel, Char PageName[]){
    SEND_COMMAND Panel, "'PAGE-', PageName";
    }

    DEFINE_FUNCTION TP_ShowPageAll(DEV Panels[], Char PageName[]){
    STACK_VAR Index;
    Index = 1;
    FOR(Index = 1; Index <= LENGTH_ARRAY(Panels); Index++){
    TP_ShowPage(Panels[Index],PageName);
    }
    }

  • HARMAN_icraigieHARMAN_icraigie Posts: 660
    edited June 2022
    define_function showpage(int panelIndex, char pageName[])
    {
      if(!panelIndex)
      {
         // Recursion
        stack_var integer i;
        for(i = length_array(panels); i; i--)
        {
            showpage(i, pageName);
        }
    
        // Device Array Command
       send_command panels,"'^PGE-',pageName";
    
      }
      else
      {
          send_command panels[panelIndex],"'^PGE-',pageName";
      }
    }
    
  • JamesBJamesB Posts: 10
    Thanks, guys, I was aware that I can iterate over the array, I was just hoping for a less verbose option.

    Does the language have array literals? I wouldn't mind writing something like `fnFoo({dvTP_A})` - that's not the syntax, apparently, but maybe there's something else?

    I'm coming to this from a variety of higher level languages, so my impulse is to solve problems like this with as little code as possible. That approach has, uh, hit a few snags...
  • HARMAN_ChrisHARMAN_Chris Posts: 598
    edited June 2022

    I tend to define constant index numbers for each panel, as well as one to represent ALL panels. My functions all expect an inbound index value, but within the function, you split out the two scenarios like Ian showed above.

    This is how AMX Pro Services writes the function:

    DEFINE_FUNCTION fnGUI_VText(DEV dvPanels[], INTEGER nPanel, INTEGER nAddress, CHAR sMessage[])
    {
        IF (nPanel == PANEL_ALL)
        {
            SEND_COMMAND dvPanels, "'^TXT-',ITOA(nAddress),',0,',sMessage";
        }
        ELSE
        {
            SEND_COMMAND dvPanels[nPanel], "'^TXT-',ITOA(nAddress),',0,',sMessage";
        }
    }
    
  • JamesBJamesB Posts: 10

    My reduced example was trivial, but consider the case where the function takes 4 arguments and performs 8-10 operations on the device(s). You're either duplicating a lot of code with your approach, which reduces maintainability and will introduce errors at some point, or you're creating two functions like SCamphaug suggested, where nesting function calls can lead to unexpected wait behavior.

    I guess this is just a language foible I'll have to get used to, then. I inherited a messy code-base and have been doing my best to reduce complexity and repetition, but I guess a certain amount of both is just going to be unavoidable.

Sign In or Register to comment.