communication between function and macro using run_macro

Accepted Solution Solved
Reply
New Contributor
Posts: 4
Accepted Solution

communication between function and macro using run_macro

Dear SAS community.  I have some issues with the communication between a function and a macro using run_macro.  I can't figure out what is going wrong.  Here is a small example I have built to illustrate my problem.  What the macro does is not really relevant, it just an example.  The problem is that I do not get anything back from the macro into the function so the second column is always empty.  What am I doing wrong ?

 

I have a dataset with one column and I want write an output dataset containing this column + one extra column filled with the result of a function.  This function uses the column of the input file  as parameter and calls a macro to do the manip.  Here is the code.

and the result where the second column is empty.

 

 

%macro getMacro();
	data _null_;
		calc=trim(&dosnr.)||'-1';      /* just doing something */
		put calc;                      /* checking if it is working */
		call symput('result',calc);
	run;
%mend getMacro;
options cmplib = _null_; /* to avoid annoying messages */ proc fcmp outlib=work.functions.wrapper; function getFunc(dosnr $) $; rc = run_macro('getMacro',dosnr,result); return(result); endsub; run; data in_test; input Dossier_Nr $; datalines; A1 B2 C3 D4 E5 ; run; options cmplib=work.functions; data out_test; set in_test; Dossier_Nr_Res = getFunc(Dossier_Nr); run;
proc print data = out_test;
run;

 

Result from proc print:

OBS Dossier_Nr Dossier_Nr_Res
1 A1 .
2 B2 .
3 C3 .
4 D4 .
5 E5 .

Accepted Solutions
Solution
‎10-27-2016 11:26 AM
Super User
Posts: 6,928

Re: communication between function and macro using run_macro

[ Edited ]

My example gave me a NOTE about a type conversion and an unitialized variable. Further research showed me that SAS will automatically put quotes around char type parameters when run_macro is used. But it gave me a hint. Now, when running your initial code:

%macro getMacro();
	data _null_;
		calc=trim(&dosnr.)||'-1';      /* just doing something */
		put calc;                      /* checking if it is working */
		call symput('result',calc);
	run;
%mend getMacro;
options cmplib = _null_;                       /* to avoid annoying messages  */
proc fcmp outlib=work.functions.wrapper;
	function getFunc(dosnr $) $;
		rc = run_macro('getMacro',dosnr,result);
		return(result);
	endsub;
run;
data in_test;
	input Dossier_Nr $;
	datalines;
A1
B2
C3
D4
E5
;
run;
options cmplib=work.functions;
data out_test;
	set in_test;
	Dossier_Nr_Res = getFunc(Dossier_Nr);
run;
proc print data = out_test;
run;

this is in the log:

25         proc fcmp outlib=work.functions.wrapper;
26         	function getFunc(dosnr $) $;
27         		rc = run_macro('getMacro',dosnr,result);
28         		return(result);
NOTE: Numeric value converted to character at line 28 column 10.
29         	endsub;
30         run;

NOTE: Function getFunc saved to work.functions.wrapper.
NOTE: PROCEDURE FCMP used (Total process time):
      real time           0.09 seconds
      cpu time            0.01 seconds
      

31         data in_test;
32         	input Dossier_Nr $;
33         	datalines;

NOTE: The data set WORK.IN_TEST has 5 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.02 seconds
      cpu time            0.00 seconds
      
39         ;

40         run;
41         options cmplib=work.functions;
42         data out_test;
43         	set in_test;
44         	Dossier_Nr_Res = getFunc(Dossier_Nr);
45         run;

NOTE: Numeric value converted to character at line 0 column 8.

See the two NOTEs about type conversion, which point to

return(result);

Since the function should return character, SAS must somehow made "result" numeric. And that's exactly what happens. Since "result" was never explicitly defined as character, SAS (as it does in a data step) will make it numeric. So it can't accept 'A1-1' as value, and is set to missing, and after conversion back to character you get the dot.

Do this in the function:

proc fcmp outlib=work.functions.wrapper;
  function getFunc(dosnr $) $;
    length result $100;
    rc = run_macro('getMacro',dosnr,result);
    return(result);
  endsub;
run;

and, voila, you get this output:

       Dossier_    Dossier_
Obs       Nr        Nr_Res

 1        A1         A1-1  
 2        B2         B2-1  
 3        C3         C3-1  
 4        D4         D4-1  
 5        E5         E5-1  

Moral of the story: NEVER accept NOTEs about implicit type conversion in your SAS log. Most of the times they're not critical, but sometimes they turn on you and bite you in your behind.

 

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers

View solution in original post


All Replies
Super User
Posts: 6,928

Re: communication between function and macro using run_macro

Since you are setting &result within the macro, it most probably will only be local to the macro itself.

use

 %global result;

within the macro to put it in the global macro variable table.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
New Contributor
Posts: 4

Re: communication between function and macro using run_macro

Hi Kurt,

 

I tried already but unfortunately it didn't change anything.

Super User
Posts: 6,928

Re: communication between function and macro using run_macro

Reduce complexity first.

Just run the macro on it's own, and then look at the log, and you will find a clue why it doesn't work:

%macro getMacro();
	data _null_;
		calc=trim(&dosnr.)||'-1';      /* just doing something */
		put calc;                      /* checking if it is working */
		call symput('result',calc);
	run;
%mend getMacro;

%let dosnr=Xxx;
%let result=1; *this statement just puts &result into the global macvar table;
%getmacro;

%put &result;

If the messages in the log do not immediately lead you in the right direction, come back here. But I want you to find the clue on your own.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
New Contributor
Posts: 4

Re: communication between function and macro using run_macro

Dear Kurt,

 

I tested the macro alone as well already.   If I just use the macro, the "result" macro variable is filled with 'Xxx-1' as in your example.  So the macro on it's own is working.   Still no clue why the symput doesn't return the parameter to the run_macro instruction.

 

Thanks for your help

 

Philippe

 

Solution
‎10-27-2016 11:26 AM
Super User
Posts: 6,928

Re: communication between function and macro using run_macro

[ Edited ]

My example gave me a NOTE about a type conversion and an unitialized variable. Further research showed me that SAS will automatically put quotes around char type parameters when run_macro is used. But it gave me a hint. Now, when running your initial code:

%macro getMacro();
	data _null_;
		calc=trim(&dosnr.)||'-1';      /* just doing something */
		put calc;                      /* checking if it is working */
		call symput('result',calc);
	run;
%mend getMacro;
options cmplib = _null_;                       /* to avoid annoying messages  */
proc fcmp outlib=work.functions.wrapper;
	function getFunc(dosnr $) $;
		rc = run_macro('getMacro',dosnr,result);
		return(result);
	endsub;
run;
data in_test;
	input Dossier_Nr $;
	datalines;
A1
B2
C3
D4
E5
;
run;
options cmplib=work.functions;
data out_test;
	set in_test;
	Dossier_Nr_Res = getFunc(Dossier_Nr);
run;
proc print data = out_test;
run;

this is in the log:

25         proc fcmp outlib=work.functions.wrapper;
26         	function getFunc(dosnr $) $;
27         		rc = run_macro('getMacro',dosnr,result);
28         		return(result);
NOTE: Numeric value converted to character at line 28 column 10.
29         	endsub;
30         run;

NOTE: Function getFunc saved to work.functions.wrapper.
NOTE: PROCEDURE FCMP used (Total process time):
      real time           0.09 seconds
      cpu time            0.01 seconds
      

31         data in_test;
32         	input Dossier_Nr $;
33         	datalines;

NOTE: The data set WORK.IN_TEST has 5 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.02 seconds
      cpu time            0.00 seconds
      
39         ;

40         run;
41         options cmplib=work.functions;
42         data out_test;
43         	set in_test;
44         	Dossier_Nr_Res = getFunc(Dossier_Nr);
45         run;

NOTE: Numeric value converted to character at line 0 column 8.

See the two NOTEs about type conversion, which point to

return(result);

Since the function should return character, SAS must somehow made "result" numeric. And that's exactly what happens. Since "result" was never explicitly defined as character, SAS (as it does in a data step) will make it numeric. So it can't accept 'A1-1' as value, and is set to missing, and after conversion back to character you get the dot.

Do this in the function:

proc fcmp outlib=work.functions.wrapper;
  function getFunc(dosnr $) $;
    length result $100;
    rc = run_macro('getMacro',dosnr,result);
    return(result);
  endsub;
run;

and, voila, you get this output:

       Dossier_    Dossier_
Obs       Nr        Nr_Res

 1        A1         A1-1  
 2        B2         B2-1  
 3        C3         C3-1  
 4        D4         D4-1  
 5        E5         E5-1  

Moral of the story: NEVER accept NOTEs about implicit type conversion in your SAS log. Most of the times they're not critical, but sometimes they turn on you and bite you in your behind.

 

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
New Contributor
Posts: 4

Re: communication between function and macro using run_macro

Dear Kurt,

Shame on me... I wonder how many times I overlooked it !   This is typical when you have your nose on the steering...

 

Thanks for your help

 

Philippe

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 6 replies
  • 339 views
  • 3 likes
  • 2 in conversation