Search notes:

SAS: proc fcmp

fcmp is the function compiler. It allows to create user defined SAS functions.

Subroutine (procedures)

proc fcmp outlib=work.funcs.tq84;
  
  subroutine tq84_sub(txt$, num);
    put "txt = " txt;
    put "num = " num;
  endsub;
  
run;

options cmplib=work.funcs;

data _null_;
  call tq84_sub('foo', 42);
run;

%sysfunc(tq84_sub(bar, 99));
Github repository about-SAS, path: /programming/proc/fcmp/subroutine.sas

Functions

In order to return a value, a function rather than a procedure is needed.
proc fcmp outlib=work.funcs.tq84;
  function tq84_max(a, b);
    if a > b then return (a);
    return (b);
  endsub;
run;


data _null_;

  v =    7;
  w =    3;
  x =   42;
  y  = 999;

  max_vw = tq84_max(v, w);
  max_xy = tq84_max(x, y);

  put max_vw=;
  put max_xy=;
run;
Github repository about-SAS, path: /programming/proc/fcmp/max.sas
By default, the returned data type of a function is numeric. To change that, a $ with an optional length is needed:
proc fcmp outlib=work.funcs.tq84;

  function returnChar(text$) $ 100; /* $ indicates that char type is returned */
       return(cat(text, '-', text));
  endsub;
run;

%put returned text is: %sysfunc(returnChar(hello)); /* returned text is: hello-hello */
Github repository about-SAS, path: /programming/proc/fcmp/return-char.sas

varargs

Pass a variable number of arguments/parameters to the function.
proc fcmp outlib=work.funcs.tq84;
  function tq84_sum(s[*]) varargs;
    sum_ = 0;
    do i = 1 to dim(s);
       sum_ = sum_ + s[i];
    end;
    return(sum_);
  endsub;

run;

data _null_;

  array ac[3] a b c;
  array dh[5] d e f g h;

  a = 1;
  b = 2;
  c = 3;
  d = 4;
  e = 5;
  f = 6;
  g = 7;
  h = 8;

  sum_ac = tq84_sum(ac);
  sum_dh = tq84_sum(dh);

  put sum_ac=;
  put sum_dh=;
run;
Github repository about-SAS, path: /programming/proc/fcmp/varargs.sas

run_macro

%macro tq84_add;
  %put in tq84_macro;
  %let result = %eval(&p1 + &p2);
%mend  tq84_add;

proc fcmp outlib=work.funcs.tq84;
  function callMacro(p1, p2);
    rc = run_macro('tq84_add', p1, p2, result);

    if rc = 0 then return (result);
     
    return(.);
  endsub;
run;

options cmplib=work.funcs;

%put result = &result;                               /* result = &result      */
%put callMacro returned %sysfunc(callMacro(39, 3));  /* callMacro returned 42 */
%put result = &result;                               /* result = &result      */
Github repository about-SAS, path: /programming/proc/fcmp/run_macro.sas
In order to use character parameters, it seems advisable to use dequote because apparently, SAS passes the parameters within quotes.
%macro tq84_cat;
   %put in tq84_cat;

/* Note the dequote here. */
   %let result = %sysfunc(dequote(&p1)) %sysfunc(dequote(&p2));
%mend  tq84_cat;

proc fcmp outlib=work.funcs.tq84;

  function callMacroCharParams(p1$, p2$) $50;

    length result $50;
    
    rc = run_macro('tq84_cat', p1, p2, result);

    if rc = 0 then return (result);
     
    return('error');
  endsub;
run;


options cmplib=work.funcs;

%put result = &result;                         /* result = &result  */
%put %sysfunc(callMacroCharParams(foo, bar));  /* foo bar           */
%put result = &result;                         /* result = &result  */
Github repository about-SAS, path: /programming/proc/fcmp/run_macro-char-params.sas

See also

SAS programming: proc
cmplib

Index