LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous (more recent) messageNext (less recent) messagePrevious (more recent) in topicNext (less recent) in topicPrevious (more recent) by same authorNext (less recent) by same authorPrevious page (October 2005, week 3)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Sat, 15 Oct 2005 18:46:22 +0000
Reply-To:     toby dunn <tobydunn@HOTMAIL.COM>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         toby dunn <tobydunn@HOTMAIL.COM>
Subject:      Re: On "Call Execute" and "Resolve": Just Curious on a Friday
Comments: To: nospam@HOWLES.COM
In-Reply-To:  <200510151816.j9FGl2om016220@malibu.cc.uga.edu>
Content-Type: text/plain; format=flowed

I would have to agree with Howard on this one. If my understanding is correct call execute simply takes (data step code) that it is given to it in its argument and sticks it into a stack to be processed after SAS hits a boundary statement. If the code is pure macro code it should get executed inside of the data step.

Which is why one can do the following: data one ; infile cards ; input x ; cards ; 1 2 3 ; run ;

data _null_ ; set one ; call execute('data _null_;') ; call execute('x='||x||';'); call execute('put x=;') ; call execute('run;') ; run ;

data _null_ ; set one ; call execute('%let test='||x||';');

y = resolve('&test') ;

put x= y= ; run ;

Looking at the log you will see that when call execute is used data step code you get those '+' and the code that was submitted to the stack and executed after the step boundary 'run;' was encountered.

I am not totally sure how call symput and symputx got involved on this conversation. Both of which sole function is to take data step value(s) and add them to macro variable(s). Hence you can do the following:

data one ; infile cards ; input x ; cards ; 1 2 3 ; run ;

data _null_ ; set one ;

call symput(compress('mvar'||_n_),x) ;

y = resolve(compress('&mvar'||_n_)) ;

put x= y= ;

run ;

Toby Dunn

From: "Howard Schreier <hs AT dc-sug DOT org>" <nospam@HOWLES.COM> Reply-To: "Howard Schreier <hs AT dc-sug DOT org>" <nospam@HOWLES.COM> To: SAS-L@LISTSERV.UGA.EDU Subject: Re: On "Call Execute" and "Resolve": Just Curious on a Friday Date: Sat, 15 Oct 2005 14:16:04 -0400

I would say that in general, it does not generate any code. Rather, it passes along what it receives from the evaluated argument.

On Fri, 14 Oct 2005 16:30:22 +0000, Ian Whitlock <iw1junk@COMCAST.NET> wrote:

>Bora, > >Ron and others gave you a good explanations, but I would add that CALL >EXECUTE does not execute SAS code, it executes macro code, i.e. it >generates SAS code for later execution. > >The step: >> /*Conditional processing (DOES NOT GIVE ERROR BUT DOES NOT GIVE WHAT I >> WANT!):*/ >> data test_3; >> set test; >> call symput('my_pointer' || trim(left(my_index)), 'my_var' || >> trim(left(my_index))); >> >> dep_var = resolve('&my_pointer' || trim(left(my_index))); >> run; > >does not work. CALL SYMPUT does assign the macro variable, say MY_POINTER8 >the character string "MY_VAR8" and the RESOLVE function does evaluate the >variable passing back the character string, so you have > > dep_var = "my_var8" ; > >But you do not want the character string, you want the value that character >string would produce if it could be SAS executed during the DATA step. SAS >has not provided a means of SAS executing strings of SAS code within the >DATA step. Since SAS is step oriented language the whole philosophy is to >get the string and put it into code in the next step via the macro >facility. > >As you indicate array processing solves the problem. Arrays essentially >give you the ability to reference one of a group (array) of variables via a >data value rather than coded variable names. Now that is precisely what >you indicate that you want to do; hence it is by far the best solution for >the problem. > >If it were essential to use macro/DATA step interface to solve this problem >then consider: > > data w ( drop = i ) ; > set test ; > array my_var (9) ; > do i = 1 to dim ( my_var ) ; > call symputx ( "my_var" || put( my_index, 12. -l) > , my_var ( my_index ) ) ; > end ; > dep_var = input(symget( "my_var"||put(my_index, 12. -l)) > , best12. ) ; > run ; > >This code provides a solution, which, of course, is a gross misuse of the >language, but a correct one. This step still involved the use of array >processing. As a purist you might object and ask that arrays not be used. >Then one is forced to use a better data structure. > > data test1 ; > set test ; > obs + 1 ; > run ; > > proc transpose data = test1 out = t ; > by obs my_index ; > run ; > > data w ( drop = col1 _name_ ) ; > set t ; > by obs ; > if index( _name_ , put(my_index,1.) ) then > call symputx ( "value" , col1 ) ; > if last.obs ; > dep_var = input(symget("value"), best12.) ; > run ; > >If the original array is needed then it could be provided by replacing > > set t ; > >with > > merge t test1 ; > >This is still a misuse of the tools, but I hope the examples do illustrate >what the macro/DATA step functions accomplish for SAS and why ARRAY >processing should always be considered before a solution involving macro. >CALL EXECUTE can be used to write SAS code for future execution without >requiring a %INCLUDE, but I think its primary purpose should be to invoke >macros which generate this code. Use http://www.sas-l.com to search the >archives for the phrase "CALL EXECUTE" or the words "EXECUTE" and "NRSTR". >You should find a lot of examples of interest. Finally, use >http://www.lexjansen.com/sugi/index.htm to search the SUGI papers for "CALL >EXECUTE - How and Why" for a more examples and an explanation of what can >go wrong. > >Ian Whitlock >================= >Date: Fri, 14 Oct 2005 10:36:02 -0400 >Reply-To: "Fehd, Ronald J" <rjf2@CDC.GOV> >Sender: "SAS(r) Discussion" >From: "Fehd, Ronald J" <rjf2@CDC.GOV> >Subject: Re: On "Call Execute" and "Resolve": Just Curious on a Friday > Afternoon... >Content-Type: text/plain; charset="iso-8859-9" >the code you put into call execute is executed in the next step >data _Null_; >call execute('*comment in next step;'); >run;*call execute code happens here; >run; >you put data step statements onto the stack so you generated: >DATA X; >call execute('var = value;'); >run; >var = value; >which doesn't compute: no 'data x;set y;' >in front of the assignment statement. >Ron Fehd the call execute maven CDC Atlanta GA USA RJF2 at cdc dot gov > >> -----Original Message----- >> From: owner-sas-l >> [mailto:owner-sas-l] On Behalf Of >> BoraYavuz@hsbc.com.tr >> Sent: Friday, October 14, 2005 9:54 AM >> To: SAS-L >> Subject: On "Call Execute" and "Resolve": Just Curious on a >> Friday Afternoon... >> >> >> Hello dear SAS-L-ers, >> >> Just out of curiousity on a Friday afternoon... :-) >> >> I have a data set containing these 10 variables: >> >> "my_var1-my_var9" (numeric) and "my_index" (non-negative integers >> between 1 and 9). >> >> I'm trying to create a new column via making use of the "index" info >> contained in "my_index" -- e.g., if "my_index" happens to be >> 1 I'd like the >> new column "dep_var" to equal my_var1, if "my_index" happens >> to be 8 I'd >> like dep_var = my_var8, and so forth. >> >> Can anyone give me *clear* explanations as to why the >> non-working pieces of >> SAS code below do not work? Note that I have found a working >> solution by >> making use of array processing and "vname", however I'd very >> much like to >> find an easier, more intuitive and more "generalisable" >> solution on a shiny >> Friday afternoon! :-) >> >> Here comes my "playground": >> >> /*Create a test data set:*/ >> data test(drop= counter num_recs); >> array my_var[1:9]; >> >> do num_recs= 1 to 1000; >> my_index = floor(ranuni(1234) * 10) + 1; >> do counter= 1 to dim(my_var); >> my_var(counter) = round(ranuni(4321) * 10); >> end; >> output; >> end; >> run; >> >> /*Conditional processing (GIVES ERROR!):*/ >> data test_2a; >> set test; >> call execute('dep_var = ' || 'my_var' || >> trim(left(my_index)) || ';' >> ); >> run; >> >> Partial log: >> >> NOTE: CALL EXECUTE generated line. >> NOTE: Line generated by the CALL EXECUTE routine. >> 1 + dep_var = my_var3; >> 180 >> >> ERROR 180-322: Statement is not valid or it is used out of >> proper order. >> >> NOTE: Line generated by the CALL EXECUTE routine. >> 2 + dep_var = my_var1; >> 180 >> >> ERROR 180-322: Statement is not valid or it is used out of >> proper order. >> >> /*Conditional processing (GIVES ERROR!):*/ >> data test_2b; >> set test; >> dep_var = call execute('my_var' || trim(left(my_index)) || ';'); >> run; >> >> Partial log: >> >> 16 dep_var = call execute('my_var' || >> trim(left(my_index)) || >> ';'); >> 22 >> 68 >> ERROR 22-322: Syntax error, expecting one of the following: >> !, !!, &, (, *, >> **, +, -, /, ;, <, <=, <>, =, >, ><, >=, AND, EQ, GE, >> GT, LE, LT, MAX, MIN, NE, NG, NL, OR, [, ^=, {, >> |, ||, ~=. >> >> ERROR 68-185: The function EXECUTE is unknown, or cannot be accessed. >> >> /*Conditional processing (DOES NOT GIVE ERROR BUT DOES NOT GIVE WHAT I >> WANT!):*/ >> data test_3; >> set test; >> call symput('my_pointer' || trim(left(my_index)), 'my_var' || >> trim(left(my_index))); >> >> dep_var = resolve('&my_pointer' || trim(left(my_index))); >> run; >> >> /*Conditional processing (WORKS!):*/ >> data test_4(drop= counter); >> set test; >> array my_var[9] my_var1-my_var9; >> >> do counter= 1 to dim(my_var); >> if index(vname(my_var(counter)), >> trim(left(my_index))) > 0 then >> dep_var = my_var(counter); >> end; >> run; >> >> Thank you so much for taking your time and brains. >> >> Cheers, >> >> Bora Y. >> >...


Back to: Top of message | Previous page | Main SAS-L page