BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
rararayayayay
Fluorite | Level 6

 

I'm trying to create a read-only macro variable.  I can create a non-read-only macro variable that does what I need to do, but I prefer that the variable be read-only.  This is what I have that works:

 1          OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
 55         
 56         *works;
 57         %LET path1=%NRBQUOTE(/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS 9/Carpenter's Complete
 57       ! Guide to the SAS Macro Language);
 58         %LET path1test=&path1/test/location;
 59         %PUT &=path1test;
 PATH1TEST=/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS 9/Carpenter's Complete Guide to the SAS Macro 
 Language/test/location
 60         
 61         OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
 73         

I'm unable to create a read-only variable using the following %GLOBAL statement however:

 

 1          OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
 55         
 56         *doesn't work;
 57         %GLOBAL / READONLY path2=%STR(%NRBQUOTE(/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS
 57       ! 9/Carpenter's Complete Guide to the SAS Macro Language));
 58         %LET path2test=&path2/test/location;
 59         %PUT &=path2test;
 60         
 61         OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
 62         ODS HTML CLOSE;
 63         &GRAPHTERM; ;*';*";*/;RUN;QUIT;
 64         QUIT;RUN;
 65         ODS HTML5 (ID=WEB) CLOSE;
 66         
 67         ODS RTF (ID=WEB) CLOSE;
 68         ODS PDF (ID=WEB) CLOSE;
 69         FILENAME _GSFNAME;
 70         DATA _NULL_;
 71         RUN;
 72         OPTIONS NOTES STIMER SOURCE SYNTAXCHECK;

Does anybody know what I'm doing wrong?

 

Vic

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

It is definitely NOT storing the macro quoting. You can see this for yourself by looking at the value you can see in the dictionary tables.

 

%let x=%bquote(Don't);
%global /readonly y=%bquote(Don't);
data _null_;
  set sashelp.vmacro;
  where scope='GLOBAL' and name in ('X','Y');
  put name= value = $hex20. ;
run;

Results

name=X value=04446F6E117408202020
name=Y value=446F6E27742020202020

You will need to just be careful where you REFERENCE the value of the global macro variable you have created that has unbalanced quotes.

Or you could take more care in defining the global macro variable so that the stored value does not require macro quoting.

1    %global /readonly a=%qsysfunc(dequote('%bquote(Don''t)')) ;
2    %put Actual value = |%superq(a)| ;
Actual value = |%bquote(Don't)|
3    %put Resolves to  = |&a| ;
Resolves to  = |Don't|

 

View solution in original post

11 REPLIES 11
Quentin
Super User

When you make a macro variable read only, after that you cannot change the value of that macro variable. 

 

But in your test code, you are not testing whether you can change the value of of a read only macro variable.  First you make PATH2 and it is read only.  Then you make PATH2TEST and happen to resolve PATH2 in that assignment statement.  That is all allowed.  If you tried to change the value of PATH2, it should error.

 

So, this works:

33         %GLOBAL / READONLY path2=/some/location ;
34         %LET path2test=&path2/with/subdirectory ;
35         %put &=Path2 &=Path2test ;
PATH2=/some/location PATH2TEST=/some/location/with/subdirectory

But if you try to assign a new value to path2 it fails:

 

37         %let path2=/some/other/location ;
ERROR: The variable PATH2 was declared READONLY and cannot be modified or re-declared.
The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
rararayayayay
Fluorite | Level 6

Sorry, I didn't make my problem easy to reproduce.

 

No, I'm not trying to change the value of a read-only variable, and I can get the %GLOBAL statement with the READONLY option to work for most strings.  But when I use a particaular string that has an unmatched apostrophe, I have problems.  The string in question is

 

/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS 9/Carpenter's Complete Guide to the SAS Macro Language 

 

 

What's strange is that I don't have any problems when using a %LET statement.  I mask the string with a macro quoting function and it works.

%LET path1=%NRBQUOTE(/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS 9/Carpenter's Complete Guide to the SAS Macro Language);
%PUT &=path1;
%LET path1test=&path1/test/location;
%PUT &=path1test;

 

yields

 

56         %LET path1=%NRBQUOTE(/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS 9/Carpenter's Complete
 56       ! Guide to the SAS Macro Language);
 57         %PUT &=path1;
 PATH1=/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS 9/Carpenter's Complete Guide to the SAS Macro Language
 58         %LET path1test=&path1/test/location;
 59         %PUT &=path1test;
 PATH1TEST=/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS 9/Carpenter's Complete Guide to the SAS Macro Language/test/location

But if I use the same string with a %GLOBAL / READONLY macro-variable=value; statement 

 

%GLOBAL / READONLY path2=%NRBQUOTE(/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS 9/Carpenter's Complete Guide to the SAS Macro Language);
%PUT &=path2;
%LET path2test=&path2/test/location;
%PUT &=path2test;

 

it doesn't work, and I get this junk:

 

 56         %GLOBAL / READONLY path2=%NRBQUOTE(/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS
 56       ! 9/Carpenter's Complete Guide to the SAS Macro Language);
 57         %PUT &=path2;
 58         %LET path2test=&path2/test/location;
 59         %PUT &=path2test;
 60         
 61         OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
 62         ODS HTML CLOSE;
 63         &GRAPHTERM; ;*';*";*/;RUN;QUIT;
 PATH2=/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS 9/Carpenter's Complete Guide to the SAS Macro 
 Language;%LET path2test=&path2/test/location;%PUT &=path2test;OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;ODS HTML 
 CLOSE;&GRAPHTERM; ;*'
 64         QUIT;RUN;
 65         ODS HTML5 (ID=WEB) CLOSE;
 66         
 67         ODS RTF (ID=WEB) CLOSE;
 68         ODS PDF (ID=WEB) CLOSE;
 NOTE: ODS PDF(WEB) printed no output. 
       (This sometimes results from failing to place a RUN statement before the ODS PDF(WEB) CLOSE statement.)
 69         FILENAME _GSFNAME;
 NOTE: Fileref _GSFNAME has been deassigned.
 70         DATA _NULL_;
 71         RUN;
 
 NOTE: DATA statement used (Total process time):
       real time           0.01 seconds
       cpu time            0.01 seconds
       
 
 72         OPTIONS NOTES STIMER SOURCE SYNTAXCHECK;
 73  

 

Does that make any sense to you?

 

Vic

 

Quentin
Super User
Sorry,missed your point. Does it work with:
%GLOBAL / READONLY path2=%Str(/folders/myfolders/sasuser.v94/2 SAS Certified Advanced Programmer for SAS 9/Carpenter%'s Complete Guide to the SAS Macro Language);

?
I think %str is the proper quoting function to use outside of a macro definition, even though it requires marking the quote with a %. But agree %nrbquote() should work. 
Apparently something about readonly  is unquoting the value, which seems bad. So you end up with an unmatched single quote mark.  I'm away from sas but will play with this later. 

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
Quentin
Super User

Okay, came back to playing with it, and I think you should send this in to tech support.  Looks like /readonly is not honoring the macro quoting.

 

I ran this in EG with SAS 9.4M3, and didn't work:

%global /readonly y=%str(Carpenter%'s) ;
%put y=&y ;

Reaching for straws, I tried %SUPERQ, but it didn't help:

%let x=%str(Carpenter%'s) ;
%put x=&x ;
%global /readonly y=%superq(x);
%put y=&y ;

 

 

And trying it in a macro caused an ugly "CALL tech support" error:

%macro try(dummy) ;
 %global /readonly Z=%str(Carpenter%'s) ;
%mend try ;

%try()

Perhaps because EG gets tripped up by the unmatched quote and then not seeing the %mend and even EG's magic string doesn't save it.

 

Seems buggy to me.  Unless of course it's documented somewhere that you can't use quoting functions with /readonly.

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
rararayayayay
Fluorite | Level 6
Good morning Quentin, thanks for your help. I'm going to submit the macro quoting issue to tech support right now. The last error you're getting appears to be a known issue -- http://support.sas.com/kb/58/357.html. Bye 👋.
Tom
Super User Tom
Super User

It is definitely NOT storing the macro quoting. You can see this for yourself by looking at the value you can see in the dictionary tables.

 

%let x=%bquote(Don't);
%global /readonly y=%bquote(Don't);
data _null_;
  set sashelp.vmacro;
  where scope='GLOBAL' and name in ('X','Y');
  put name= value = $hex20. ;
run;

Results

name=X value=04446F6E117408202020
name=Y value=446F6E27742020202020

You will need to just be careful where you REFERENCE the value of the global macro variable you have created that has unbalanced quotes.

Or you could take more care in defining the global macro variable so that the stored value does not require macro quoting.

1    %global /readonly a=%qsysfunc(dequote('%bquote(Don''t)')) ;
2    %put Actual value = |%superq(a)| ;
Actual value = |%bquote(Don't)|
3    %put Resolves to  = |&a| ;
Resolves to  = |Don't|

 

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 11 replies
  • 1676 views
  • 4 likes
  • 4 in conversation