|
|||
|
Hi,
Basically, you cannot intermix macro goodies and datastep goodies. I will explain. The %IF GRD = 'D' is where the misperception is. All macro goodies, i.e. macro variables, macro expressions, macro evaluations is all character string text -and- ALL macro environment stuff. In other words, you cannot use datastep variables and datastep goodies in the %IF expression. It is easier to interpret macro handling as text substitution. See post: http://listserv.uga.edu/cgi-bin/wa?A...sas-l&P=R29031 Let us see what your example is doing with that in mind. Take your sample code: %MACRO GRADE; %IF GRD = 'D' | GRD = 'F' %THEN POOR = 1; %ELSE POOR = 0; %MEND GRADE; DATA F2; SET F1; %GRADE run; The macro pre-processor is going to make as many passes through the text until it resolves as much as it can. So the first thing we can do is use our editor by hand to simulate what the macro pre-processor "results with if we were hand do it by hand". Of course this is not exact per se, but you will get the missing piece of your understanding if we do this. Therefore, if text-substitution is the name of the game... (and by the way, it may prove helpful to review the linked post referenced above before you continue on here. First understand the SAS macro stuff doesn't really execute anything, it's more like a code parser and re-writer. Everyone has their way of thinking what it is, but if you use this interpretation for a couple minutes, at least you will understand what functionality you are going to get. Okay, if we have: DATA F2; SET F1; %GRADE run; if we grab all the text that was (imaginarily) saved off. i.e. take all the text between the MACRO and MEND and replace it where the %GRADE was located. Replace %GRADE with contents of MACRO/MEND: so our code text in our editor buffer is now: DATA F2; SET F1; %IF GRD = 'D' | GRD = 'F' %THEN POOR = 1; %ELSE POOR = 0; run; So far, so good, just keep thinking text-substitution. Now remember that the macro expressions, such as the goodies between the %IF and the %THEN are *not* datastep objects! Just macro environment string text characters. In other words, the GRD = 'D' is *not* the datastep variable named GRD and the 'D' is *not* a datastep string literal. It is merely macro environment text characters. The whitespace will be ignored and the text characters "GRD" and the text characters "<singlequote>D<singlequote>" will be compared for equality due to the = operator. So yes, 3 characters is being compared to 3 characters "GRD" eq "'D'" and the match of 3 chars to 3 chars fails so this portion of the true/false checking in the expression resolves to 0 (zero) for false. So now we have: %IF GRD = 'D' | GRD = 'F' %THEN becoming %IF 0 | GRD = 'F' %THEN then the next comparison of macro environment text characters GRD = 'F' get evaluated in the same way and we then result in %IF 0 | 0 %THEN which then evaluates the 0 | 0 as false or false which yeilds a resulting FALSE. So the completed expression now is: DATA F2; SET F1; %IF 0 %THEN POOR = 1; %ELSE POOR = 0; run; Now all the text characters found between the %THEN and the following semicolon, or all the text characters found between the %ELSE and the following semicolon, BUT NOT INCLUDING THE SEMINCOLON is indeed placed into the editor buffer resulting in: DATA F2; SET F1; POOR = 0 run; At this point, there are no more % or & macro notations and the substituted/replaced text is submitted to the runtime compiler for execution. The compiler will give you the expected error of a missing semicolon after the POOR = 0 line. If a semicolon was added after the %GRADE, such as %GRADE; then this error will go away. So the logic of the macro %IF statement is more along the lines of: %IF<macro text expression>%THEN<return_this_text_if_ the_expression_is_true>;%ELSE<return_this_text_if_ the_expression_is_false>; Think of SAS macros as a way to "assist" writing code especially when repetitiousness or dynamic code variations are needed. Your macro should really not intermix datastep and macro, since it really can't, so you would have: %MACRO GRADE; IF GRD = 'D' | GRD = 'F' THEN POOR = 1; ELSE POOR = 0; %MEND GRADE; DATA F2; SET F1; %GRADE run; Which has no % characters, meaning ALL text found between MACRO and MEND will be replaced where %GRADE is located, resulting in: DATA F2; SET F1; IF GRD = 'D' | GRD = 'F' THEN POOR = 1; ELSE POOR = 0; run; which is indeed proper syntax for the datastep and the compiler would like this. However, you see that since there is no repetition, having two lines in the macro really doesn't save you anything. Now if dynamic text content changes were passed to the macro via arguments to the macro, or you needed a %DO loop to make you multiple copies, then using a macro would come into play. Hope this is helpful. Mark Terjeson Senior Programmer Analyst, IM&R Russell Investment Group Russell Global Leaders in Multi-Manager Investing -----Original Message----- From: SAS(r) Discussion [mailto:SAS-L@LISTSERV.UGA.EDU] On Behalf Of Pitruzzello, Anthony J Sent: Friday, March 24, 2006 2:44 PM To: SAS-L@LISTSERV.UGA.EDU Subject: Understanding How Macro Processor Works I would like to get a better understanding of how the input stack, word scanner, compiler, symbol table, and macro processor interact. SAS Macro Language: Reference, V.8, provides a very simple example, based on a single global macro variable. I would like to be able to extend that to something one step more complicated, like the code below. (I realize that there is no reason to use a macro in this code and that, because the macro is processed before the data step, the conditions that execute in DATA F2 are empty. I'm just trying to understand exactly how this code is processed.) __________________________________________________ ____________ %MACRO GRADE; %IF GRD = 'D' | GRD = 'F' %THEN POOR = 1; %ELSE POOR = 0; %MEND GRADE; DATA F1; INPUT @1 SID 1. @2 GRD $1. @4 X $2.; CARDS; 1F MN 1B OP 2C QR 3D ST 3F UV RUN; DATA F2; SET F1; %GRADE PROC PRINT; __________________________________________________ ___ The first thing I noted is that, without a semicolon following the macro call, %GRADE generates the following: ERROR 388-185: Expecting an arithmetic operator. Put a semicolon after %GRADE and it runs, but it produces this: Obs SID GRD X POOR 1 1 F MN 0 2 1 B OP 0 3 2 C QR 0 4 3 D ST 0 5 3 F UV 0 __________________________________________________ ____ This is my understanding of what is happening: 1) The word scanner first encounters "%" and triggers the macro processor (MP), which assumes control. 2) The MP inserts GRADE into the symbol table. It continues to process the macro. 3) I want to say that because "GRD" is not a macro variable, control is passed back to the word scanner at that point. However, if that occurred, and if the word scanner placed "GRD = 'D' | GRD = 'F'" into the input stack before the "DATA" statement, it would be rejected by the compiler. 4) From the output, It's obvious that first "POOR = 1" and then "POOR = 0" are being placed in the input stack after the "DATA" statement, and they are being compiled, so that the last value ("POOR = 0") is retained. But I really don't see exactly how control is passed to and from the macro processor in that "%IF GRD = 'D' | GRD = 'F' %THEN POOR = 1; %ELSE POOR = 0;" segment. Can anyone clue me in? |
|
|
||||
|
||||
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Re: Macro Quoting Question | Kevin Morgan | Newsgroup comp.soft-sys.sas | 1 | 07-06-2007 02:47 AM |
| SCL Joe (was RE: macro structure) | Gregg P. Snell | Newsgroup comp.soft-sys.sas | 0 | 06-27-2006 07:59 PM |
| Re: Understanding macro quoting (WAS: enterprise guide | Jiann-Shiun Huang | Newsgroup comp.soft-sys.sas | 0 | 05-25-2006 05:27 PM |
| Re: Understanding macro quoting (WAS: enterprise guide | Hans Schneider | Newsgroup comp.soft-sys.sas | 0 | 05-25-2006 05:19 PM |
| Re: MAcro Design was (Re: Macro quoting essentials) | Ian Whitlock | Newsgroup comp.soft-sys.sas | 3 | 12-11-2005 11:18 PM |