|
Hi,
I'm confused by your description.
You had a legacy macro:
> %macro CreateA (dsn = A);
> Data &dsn.;
> Set B;
> /* extra code */
> Run;
> %mend;
Which was updated to be:
> %macro CreateA (dsn = A, dsn_input = B);
> Data &dsn.;
> Set &dsn_input.;
> /* extra code */
> Run;
> %mend;
And now you say that that legacy calls to the macro %CreateA (dsn =
A) are resulting in &dsn_input being null.
But it looks to me like whoever did the updates to the macro
definition did a good job of following one of the primary rules of
macro revision: first do no harm.
They increased the functionality of the macro by adding a parameter to
name the input dataset, and (importantly) they made the default value
of the new parameter the same as the value in the old macro (B).
So to my eyes, these updates shouldn't be causing the problem you describe.
With the new macro, any legacy calls that look like:
%CreateA (dsn = A)
Will have &dsn_input=B.
The only way someone could trick the new macro into having a null
value value for &dsn_input is if they specified a null value for
dsn_input when they invoke the macro, e.g.:
%CreateA (dsn = A, dsn_input=)
But of course that couldn't happen in any legacy code, since dsn_input
was not a parameter in the legacy macro.
So it seems to me that if the example you gave is accurate, the
problem you are seeing more likely lies with the macro user, rather
than the macro writer.
On the other hand, if in fact the person who updated the macros coded
the updated version as:
%macro CreateA (dsn = A, dsn_input = );
Data &dsn.;
Set &dsn_input.;
/* extra code */
Run;
%mend;
then I would blame the macro programmer, because they broke the
implicit contract with the macro user, which puts the onus on the
macro writer to maintain backwards compatibility. And I think the
safest solution would be to go back and fix the macros.
Kind Regards,
--Quentin
On Tue, Nov 1, 2011 at 5:18 PM, Bolotin Yevgeniy
<YBolotin@schools.nyc.gov> wrote:
> If you do something along the lines of
>
> Data WANT1;
> a = 1;
> Run;
>
>
> Data WANT2;
> Set /* missing HAVE */ ;
> Run;
>
>
> instead of throwing up an error, SAS uses WANT1 in the SET statement for
> WANT2, even though it is totally not what I want.
>
> Is it possible to print an error to the log instead, or otherwise detect
> missing dataset names?
>
>
>
>
>
> background: a large number of macros has been refactored to be more
> reusable, so e.g.
> %macro CreateA (dsn = A);
> Data &dsn.;
> Set B;
> /* extra code */
> Run;
> %mend;
>
> Now looks like
> %macro CreateA (dsn = A, dsn_input = B);
> Data &dsn.;
> Set &dsn_input.;
> /* extra code */
> Run;
> %mend;
>
> However, some legacy code uses the old version of the macro invocation
> (from the same shared folder >.<), so after a call to %CreateA (dsn =
> A); &dsn_input. resolves to nothing and the above error strikes
>
> It's not particularly feasible to look through/update all 600+ macros
> that this can affect, or worse yet trace through tens of thousands of
> lines of code that invoke these macros to make sure they are used
> correctly, so if there is an option or something to make this an error
> (similarly to MERGENOBY option) that would be grand.
>
> (fortunately, if the DATA dataset is missing, the output dataset is
> named DATA[#] rather than after the last-used dataset, so these are
> easier to spot, but the SET dataset being missing is still
> indistinguishable from a properly-coded DATA step)
>
|