Date: Fri, 22 Apr 2005 00:58:16 -0400
Reply-To: Don Hendereson <donaldjhenderson@HOTMAIL.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: Don Hendereson <donaldjhenderson@HOTMAIL.COM>
Subject: Re: SCL versus Macro
In-Reply-To: <20050422034552.THSB23292.imf23aec.mail.bellsouth.net@CHRISSY>
Content-Type: text/plain; charset="us-ascii"
Joe,
I will respond to your point #8 only (for now). That is not to say that I
cede any of your other points (I don't). It is simply that I point #8 is
very clear. I post an example and if you can't replace the exact
functionality, you have to cede the point. And once you cede the point, I
will then turn my attention to your other comments.
What follows is a gross oversimplification of a real-world problem I
recently solved with macro.
The problem: a JSP application accesses a data store maintained by
collection of SAS program. These programs populate a variety of data sets
that the end users of the JSP application will query and drill down thru.
The user has expressed the requirement that any report displayed back to the
UI needs to show a custom message with the date/time that data set was
loaded. There are few wrinkles here:
- the JSP application uses JDBC to access the SAS data. Thus the above
message text must be returned by a SQL query submitted via JDBC.
- the user/client is not willing to assume that the process that loads the
data can be counted on to update a SAS table with the appropriate message
text (there are lots of valid reasons for this that are way out of scope for
this discussion)
- the message text, except for the date/time, must be defined in metadata
- no JSP programming to parse the message text and insert the dynamic
content (e.g., the date/time)
And, yes, I will agree that this is a very special case. I maintain that you
can not provide a pure SCL solution to this. However, the macro solution is
quite simple.
At this point I would like to digress a bit and say that the solution was
motivated by the very insightful ideas that Jack Hamilton posted a while
back regarding the use of macro to generate data values in queries submitted
by htmSQL.
So here is the macro solution (macro code stripped down to the key
elements). Define a macro which will generate the text corresponding to the
date the data set was created:
%macro getDate(data=);
%local dsid;
%let dsid = %sysfunc(open(&data));
%sysfunc(attrn(&dsid,CRDTE),datetime.)
%let dsid = %sysfunc(close(&dsid));
%mend getDate;
And let me digress here to acknowledge that I am using functions that were
originally SCL functions (but are now more widely available). But without
macro, I simply could not meet the requirements - thus reinforcing my point
that having both sets of tools in our arsenal is a good thing.
Now, if I just call the macro in SAS code, e.g.,
%put sashelp.class created on %getDate(data=sashelp.class);
I get the following text:
sashelp.class created on 12MAY04:22:53:56
Now I create a data set, called libref.messages_data as (proc print
follows):
Obs message
1 sashelp.class created on %getDate(data=sashelp.class)
Next, I create a view of this data as follows:
proc sql;
create view messages as
select resolve(message) as Message
from libref.messages_data;
quit;
run;
The resolve function causes the text in the variable message to be submitted
to the macro processor. The resulting generated text becomes the value of
the variable (thus reinforcing another point about macro - it is simply
nothing more than a text manipulation language that has a number of hooks
that know about SAS, e.g., the %sysfunc macro that can call data step or scl
functions).
When I run proc print on this I get:
Obs Message
1 sashelp.class created on 12MAY04:22:53:56
Note that this is the same value return to the JSP app via JDBC. The JSP
application will query libref.messages and the fact that macro is involved
in completely transparent to the JSP application. In fact, it is transparent
to any program/process that accesses this data view.
Regards,
-don h
-----Original Message-----
From: SAS(r) Discussion [mailto:SAS-L@LISTSERV.UGA.EDU] On Behalf Of Joe
Whitehurst
Sent: Thursday, April 21, 2005 11:46 PM
To: SAS-L@LISTSERV.UGA.EDU
Subject: Re: SCL versus Macro
Don,
Glad to hear you couldn't resist anymore, and I welcome you to the
discussion. I think we are all likely to learn more from a vigorous
discussion among seasoned veterans like you, Ian and others. I have little
difficulty agreeing with some of what you had to say. On the other hand, I
am not prepared to agree with some other aspects of your commentary. I
assume you have read my responses to Ian, et al, so I will not repeat those
responses here although I think some of them are applicable, and I may refer
to them. What I will try to do instead is respond to those parts of your
commentary below with which I cannot agree at this time.
-----Original Message-----
From: SAS(r) Discussion [mailto:SAS-L@LISTSERV.UGA.EDU] On Behalf Of Don
Hendereson
Sent: Thursday, April 21, 2005 7:18 PM
To: SAS-L@LISTSERV.UGA.EDU
Subject: Re: SCL versus Macro
Joe (et al),
I have resisted weighing in on this thread, but I can not hold back any
more.
SCL is a great tool. As is macro. There is room for both. The example you
presented is one that is simply not appropriate for SCL for all the reasons
(and then some) that Ian stated so eloquently.
***************************************************************************
***************************************************************************
1) I think my response to Ian's critique is highly appropriate here. The
example was not intended to be anything other than a refutation of the
assertion that the functionality in Paul Thompson's Macro would "do things
that SCL has trouble with". I think my example achieved that limited goal
picayune criticisms notwithstanding.
***************************************************************************
***************************************************************************
Permit me to offer just one simple critique of your response. Ian's point
about clarity of the arguments is well stated. And let me use that to
motivate my point. If I call macro overrun and forget about the underscores
in the parameter names, or I provide a parameter name that is not a valid
macro parameter, I get a syntax error - as I should.
In your example, if I specify:
%let bs = .....
Instead of:
%let _bs = .....
I would presume that the process runs with the default parameter values. So
I might get something that gave me no indication whatsoever that I called
your SCL program incorrectly.
****************************************************************************
****************************************************************************
2) This particular picayune criticism would be easily handled in any real
world use of SAS Component Language by testing the values of the parameters
being passed and writing an appropriate message to the log, stopping the
program, or any other action a programmer might wish to take.
****************************************************************************
****************************************************************************
Next, you talk about the use of lists - very nice things indeed. But if you
add up all the various bits and pieces of things that you need to hook
together and assume in order to do things with SCL, you have a far more
complicated and dangerous environment than one that uses simple macro.
***************************************************************************
***************************************************************************
3) The real quarry I am after is not a simple macro, but one that has
constructions like: &&&&&&&zebra.&&&&&warpraptor&&&&&&&&&&&metope&&bullsht
for an extreme example.
***************************************************************************
***************************************************************************
Permit me to illustrate with another example. Consider wanting to call two
different modules one right after the other:
%one(data=a,vars=b)
Followed by:
%two(vars=c)
Where, for example for macro two, I want the default value for data. In your
example with %let statements (a macro language construct I might add), you
would have to know and remember to blank out the value before the second
call. The use of macro variables to pass parameters also means that the user
has to know all the parameters for every routine/module they call.
****************************************************************************
****************************************************************************
4) Point 2 applies here, and I'm aware that %LET is a Macro Language
construct, and I have stopped using them in all but trivial cases.
****************************************************************************
****************************************************************************
And yes, you can come back and tell me that LISTS and conventions (e.g., a
SCL entry gets its parameter values from a LIST with a name uniquely
determined by the SCL entry name) can solve all that - but that is not the
point.
****************************************************************************
****************************************************************************
5) I would say at least that and much more given a real world example, and
that is a great part of the point I wish to make.
****************************************************************************
****************************************************************************
The point is that some problems are better suited to macro and some
to SCL. The version 6 HTML formatting tools are a prime example. They are
mostly written in SCL - but the user/programmer interface is a macro call -
for many of the reasons Ian highlighted.
****************************************************************************
****************************************************************************
6) It is just as likely that the reason that the user/programmer interface
is a Macro call is that is what the programmer charged with the
responsibility knew how to do. In my experience, it is a rare event in
world history when any system building decisions are actually based on
rational considerations.
****************************************************************************
****************************************************************************
It should be very simple. Both SCL and macro are great tools to have in our
toolkit as SAS developers/users. But to make the claim that SCL is better
than macro or that macro is better than SCL simply can not be supported.
****************************************************************************
****************************************************************************
7) I can certainly "claim" that SAS Component Language is better for
organizing and controlling batch SAS programs than the SAS Macro Language
is, but what I intend to do instead is illustrate why with a series of
examples starting with the data mining simulation macro offered by Michael
Murff of Brigham Young University. In fact, what I would like to do is put
this dead horse aside so I can focus on that project
****************************************************************************
****************************************************************************
I am pretty sure either of us could provide any number of examples that
simply can not be done in macro, but can be in SCL. And I am almost positive
that I can provide macro examples that simply can't be done in SCL.
****************************************************************************
****************************************************************************
8) Even though I am not from Missouri, I will have to be shown a Macro
Language example whose functionality cannot be replicated with SAS Component
Language. I simply don't believe it is possible.
****************************************************************************
****************************************************************************
Why can't we leave the matter at the statement that both are great tools
that each have their place.
****************************************************************************
****************************************************************************
9) Now, that wouldn't be any fun would it? And members of this forum would
be deprived of the learning opportunities afforded when experts disagree
Publicly.
Kind Regards,
Joe
***************************************************************************
****************************************************************************
Regards,
-don h
-----Original Message-----
From: SAS(r) Discussion [mailto:SAS-L@LISTSERV.UGA.EDU] On Behalf Of Joe
Whitehurst
Sent: Thursday, April 21, 2005 2:30 PM
To: SAS-L@LISTSERV.UGA.EDU
Subject: Re: SCL versus Macro
Ian,
Like Richard, you have made some interesting comments which point out
further unwarranted assumptions I made in presenting what I meant to be just
a quick example to refute Frank's assertion, "OK, here's a good example of a
situation where macros do things that SCL has trouble with". I think my
example even with all its warts did do this. I did not intend anything more
than this for this example, and I certainly did not attempt to put "one...
in a position to make a reasonable judgment on the superiority of SCL code
to macro code in all cases" on the basis of this simple example.
Nevertheless, because you have been thoughtful enough to critique the
example, I will try to respond to your suggestions.
Just as Frank's Macro Language code presents a clear set of parameters which
are readily apparent to you, including which had default values and which
did not, an expert with the SAS Macro Language, I assert that the SAS
Component Language functionally equivalent code also presents a clear set of
parameters which are readily apparent to an expert with SAS Component
Language, including which had default values and which did not. I might say
that your construct subsystem for construing SAS Component Language code is
not nearly as elaborated as your construct subsystem for construing SAS
Macro Language code. Or, I could just say, you have vastly more experience
construing SAS Macro Language code than you do construing SAS Component
Language code. Or, even, you have developed cognitive structures for
assimilating Macro Language code while you still have to accommodate
Component Language code. From the standpoint of an expert with SAS Component
language:
%let _bs=1;
%let _es=2;
libname x "/users/x";
%let _vrun=a;
dm 'af=x._overrun.scl';
%let _vrun=b;
dm 'af=x._overrun.scl';
with knowledge of the details of the code in _overrun.scl is just as
informative as the corresponding Macro Language code details would be to an
expert with the SAS Macro Language.
As regards the user/tool communication problem for batch programs, the SAS
System comes with an editor/viewer for SAS Component Language stored Lists
(CatalogEntryType=SLIST) which obviates the need for any macro variables at
all. I considered it beyond the scope of this little example, but I will
include complete instructions on how to create, review, and revise SLISTs to
facilitate parameter passing to batch programs when I present the SAS
Component Language functional equivalent to the data mining simulation
Macro. To whet the appetites of any readers of this thread let me just ask
if you could use a data structure which can store items (32k max length) of
mixed data types including other lists and which can have item names of any
length (32k max) using any printable character and which allows these items
to be retrieved by name or position or index to control your batch
processing?
Joe Whitehurst
-----Original Message-----
From: SAS(r) Discussion [mailto:SAS-L@LISTSERV.UGA.EDU] On Behalf Of Ian
Whitlock
Sent: Thursday, April 21, 2005 12:44 PM
To: SAS-L@LISTSERV.UGA.EDU
Subject: SCL versus Macro
In response to Frank Ivis' macro example (proposed under the
subject line "Re: The advantage and disadvanatge of using SAS
Macros"),
fi> %macro _overrun(_bs=1,_es=2,_vrun=);
fi> %if (&_bs <= 1 & 1 <= &_es) %then %do;
fi> libname x "/users/x";
fi> proc format;value af 1='a' 2='b';run;
fi> %end;
fi> %if (&_bs <= 2 & 2 <= &_es) %then %do;
fi> proc means data=x.file;var &_vrun;
fi> run;
fi> %end;
fi> %mend _overrun;
and usage code
fi> %_overrun(_vrun=a);
fi> %_overrun(_vrun=b);
Joe Whitehurst posted an alternative using SCL. (I put
the SCL first, to parallel the macro code and to distinguish
the tool form the use of the tool.)
jw> init:
jw> _vrun=symget("_vrun");
jw> _bs=symget("_bs");
jw> _es=symget("_es");
jw>
jw> if _bs<=1 & 1<=_es then do;
jw> submit continue;
jw> proc format;value af 1='a' 2='b';run;
jw> endsubmit;
jw> end;
jw>
jw> if _bs<=2 & 2<=_es then do;
jw> submit continue;
jw> proc means data=x.file;var &_vrun;run;
jw> endsubmit;
jw> end;
jw> return;
Here is Joe's usage code.
jw> %let _bs=1;
jw> %let _es=2;
jw>
jw> libname x "/users/x";
jw>
jw> %let _vrun=a;
jw> dm 'af=x._overrun.scl';
jw>
jw> %let _vrun=b;
jw> dm 'af=x._overrun.scl';
One thing I find immediately apparent is the loss of a clear
set of parameters. When I read
libname x "/users/x";
%_overrun(_vrun=a);
I know that default parameter values are being used for all
parameters except _VRUN. When I read
%macro _overrun(_bs=1,_es=2,_vrun=);
I know exactly what the parameters are and how the default values
have been set.
When I read Joe's code I know none of this. In fact, I do not
even find an awareness that the example made use of default
parameters. For me the clarity of parameterization is essential!
Hence I think, Joe, should rewrite the code to show these
features and include the equivalent of the calls
%_overrun(_bs=0,_vrun=)
%_overrun(_es=3,_vrun=)
before one is in a position to make a reasonable judgment on the
superiority of SCL code to macro code in all cases.
I think this point is very important because my current
understanding of SAS/AF is that it was designed to interact with
a user providing information from a GUI-form. While I see an
important feature of macro as it's ability to organize a batch
SAS program in a structured manner.
Are global macro variables essential to fitting SAS/AF into macro
shoes? Joe suggested:
jw> If one wanted to avoid even Macro variables the key word
jw> parameters could be passed in a stored SCL list, text file,
jw> SAS dataset or almost any other file structure accessible
jw> to the SAS System. You could also eschew both of the PROCs
jw> in favor of SAS Component Language functions. Thanks for
jw> the example.
Since the point is important for program clarity, I think in the
example code, Joe should show exactly what is entailed adopting
each of these possibilities, particularly in a batch environment.
At present, I find it disturbing that for his first cut at this
example he chose global macro variables to solve the user/tool
communication problem.
Ian Whitlock
PS. Normally I would not want to change the subject line, but I
think it particularly important here to have a more meaningful
subject line, since these messages are not a simple answer to a
specific problem.