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

1. What makes null statement not just null ,global and executable?

 

I do not quite comprehend  executable nature of null statement in the 1st place though there is an example in the docs that seems rather in comprehensive to me at least. Also, I do not find  great utility to trust its executable component beyond its step boundary and specification of values embedded with semicolons . 2ndly, how does it become a global statement? So use anywhere as it says in the docs? How anywhere after all?

 

2. Alias for datalines are cards and lines: Is the use of alias just to remove the yellow color patch on the datalines? Well just curious though not important. Any other features?

See the yellow patch not coloring the datalines when you use lines. 🙂

 


data test1;
input a b;
cards;
1 2
;
data test2;
input a b;
datalines;
1 2
;
data test3;
input a b;
lines;
1 2
;

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Quentin
Super User

Hi,

 

Taking it in parts:

 


@novinosrin wrote:

Yes, that's a better way to describe it. The docs says

1. "Although the Null statement performs no action, it is an executable statement. Therefore, a label can precede the Null statement, or you can use it in conditional processing."[ examples to understand this statement in a meaningful is wanted ]

 

 

I think you already had an example of null statement being useful in conditional processing.  For example, I might code:

 

  if unit='inches' then height=height*2.54 ;
  else if unit='cm' then ; *do nothing cuz already in cm ;
  else put "ER" "ROR: (USER) " "unexpected unit!" unit= ;

 

 

That second statement works because SAS doesn't mind a null statement.  I suppose if SAS didn't accept a null statement I could do something like:

 

  if unit='inches' then height=height*2.54 ;
  else if unit='cm' then do ; end ; *do nothing cuz already in cm ;
  else put "ER" "ROR: (USER) " "bad unit!" unit= ;

 

So that has any empty do block with no statements in it, but is not actually a null statement (as per documentation; they may very well compile to the same byte code).

 

As for labels, if you look in the documentation on label: statement, it has more examples. I don't use the label statement much (ever?) in DATA step, but consider:

 

 

*list the female students ;
data want ;
  set sashelp.class ;
  if sex='M' then goto end;
  
  put (name sex)(=) ;

  end: ; *null statement;
run ;

The docs say END: is a label pointing to a null statement.  The docs say that the label: statement needs to point to a statement and end with a semicolon (like any other statement), so allowing a null statement before the semicolon is useful.  Allowing a null statement avoids the need to do something silly like:

 

 

*list the female students ;
data want ;
  set sashelp.class ;
  if sex='M' then goto end;
  
  put (name sex)(=) ;

  end: foo=1; *non-null statement;
run ;

That said, below code works (perhaps the label points to the RUN statement?):

 

 

data want ;
  set sashelp.class ;
  if sex='M' then goto end;
  
  put (name sex)(=) ;

  end: 
run ;

 

 

And so does the below, which doesn't have a statement after the label (other than an implied run):

 

data want ;
  set sashelp.class ;
  if sex='M' then goto end;
  
  put (name sex)(=) ;

  end: 

data foo ;
run ;

 

 

2. "The Null statement is useful while you are developing a program"[ The one example in the docs seems very inadequate to me]

 

I can imagine it might feel more useful if GOTO was more popular.  As in the example, you could have some rare condition you don't want to handle yet, and say:

 

data want ;
set have ; if condition then goto handler ; return ; handler: ; run ;

 

 

And you could write the handler section later.  I've never wanted to do that, but I think that's the case they're making.

 

Or I suppose with the conditional example, could code:

 

 

  if x=1 then y=1 ;
  else if x=2 then y=22 ;
  else if x=3 then /*do not know what to do yet, fill me in later*/ ;
else put "ERROR: bad value";

 

 

I don't know if there is too much to worry about in the tokenization of a null statement.  But I agree, the concept of a compiled/executable null statement in a data step would have a different "meaning" then a null statement in open code or proc step where it is interpreted rather than compiled.

 

Within the BASE SAS language, I've never seen a null statement cause a problem or anything interesting of note.  Well, here's one.   I suppose a null statement can "break" a code block, but that seems fair:

 

54   data _null_ ;
55     if sex='M' then foo=1;
56     ;
57     else if sex='F' then foo=2;
       ----
       160
ERROR 160-185: No matching IF-THEN clause.

58   run ;

NOTE: The SAS System stopped processing this step because of errors.

I suppose that is evidence that the data step compiler does not simply skip null statements, it sees them enough to break compilation.

 

 

In the macro language, a null SAS language statement can cause problems, as discussed.

 

Kind Regards,

--Q.

 

 

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.

View solution in original post

31 REPLIES 31
unison
Lapis Lazuli | Level 10

2. Interesting.. I don't see any coloring difference between lines and datalines in my IDE? Can you snapshot it? From what I understand, they are purely aliases.

 

-unison
novinosrin
Tourmaline | Level 20

In my PC SAS it does color distinction. However,l i am not allowed attachments on the internet at work. I may have to go home and upload it.  Sorry about that 

mkeintz
PROC Star

@novinosrin 

 

Regarding #2,  I  was not aware of (or perhaps completely forgot about) the existence of a LINES statement.  Only  CARDS and DATALINES have any space in my memory bank.   Although I reproduced what you describe (no yellow coloring for in-lline data when using the LINES statement), did you notice that  the rendering of the data in your inserted program is yellow for ALL the programs, even using LINES.

 

As to #1, can you tell me what part of the docs you are referring to?  I don't think I fully understand the question.

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
novinosrin
Tourmaline | Level 20

Thank you Mark, I am not too concerned about #2 and certainly doesn't require a wharton answer. It's just fun. However 1st one seems to apply to a context.

 

https://documentation.sas.com/?docsetId=lestmtsref&docsetTarget=n0grfgqwd2djh5n1ordogecfgu76.htm&doc...

 

This says 

Null Statement

Signals the end of data lines or acts as a placeholder.

Note: The Null Statement has moved to SAS Global Statements.

 

Next one(the full explanation here) http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000289429.htm

 

Null Statement



Signals the end of data lines or acts as a placeholder.

Valid: Anywhere
Category: Action
Type: Executable

 

Yes there is an example there, just not convincing to me and i felt I may as well ask here. 

mkeintz
PROC Star

Well if the null statement can be used anywhere, that's probably enough to classify is as global.  It's trivial below, but it is global:

 

proc freq data=sashelp.class;
  tables  sex;
run;
;
proc means data=sashelp.class;
   var age;
run;

I guess you can call it executable, because in the  presence of in-line data, it tells the data step to stop processing data - i.e. to stop executing.   But one could avoid it if one wanted to demonstrate especially bad programming practice:

 

data t1;
  input a b;
cards;
1 2
proc freq data=t1;   /* or proc freq data=t1;;;;*/
run;
--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
hashman
Ammonite | Level 13

@mkeintz:

Mark, ha-ha. It's a good thing you'd forgotten about LINES since this is a poison pill - if only the color thing discovered by @novinosrin were the problem. Try this:

data have ;                                                                                                                             
  infile lines ;                                                                                                                        
  input x ;                                                                                                                             
  lines ;                                                                                                                               
1                                                                                                                                       
2                                                                                                                                       
run ; 

What do you get? Right, this:

ERROR: No logical assign for filename LINES.

Huh? But now, try this:

data have ;                                                                                                                             
  infile cards ; * place 1 ;                                                                                                                        
  input x ;                                                                                                                             
  lines ;        * place 2 ;                                                                                                                                
1                                                                                                                                       
2                                                                                                                                       
run ;    

 And everything is hunky-dory. Bottom line (npi), LINES is never good in place 1, regardless of what is in place 2, even if it's LINES itself. However, CARDS and DATALINES are always good in place 1 irrespective of whether place 2 is occupied by CARDS, LINES, or DATALINES.

 

I have no first clue why it was necessary to create such a confusion, as if CARDS/CARDS4 weren't good enough. If it was just the desire to cater to a younger audience by shaking off the image of CARDS as something ancient harking back to the mainframe, the introduction of LINES and DATALINES was hardly worth the effort. SAS is still chock full of keywords, and indeed features, borrowed from the mainframe, and I find absolutely nothing wrong with it. Getting rid of them would be tantamount to throwing the baby away with the bathwater. Shall we get rid, just for starters, of:

  • MSGLEVEL LRECL RECFM DISP OLD NEW SHARE MOD 
  • & and && as symbolic references and . and .. as indicators of their termini
  • The concepts of STEP, PROCEDURE, LIBRARY, CATALOG
  • The entire PL/I syntax (including the macro language syntax) upon which the entire SAS language syntax is built
  • ...

I guess I'm asking a rhetorical question. I've always coded CARDS, code CARDS, and will always code CARDS - and nothing else. If it should offend some folks inheriting my code who have never seen a punch card, none of my business - they can replace it with DATALINES if they think it adds any value to their code. As far as LINES is concerned, see above.

 

Kind regards

Paul D.

 

Tom
Super User Tom
Super User

The Version 8 documentation (which in many ways is soo much easier to read) clearly shows that LINES is an alias for CARDS/DATALINES.  https://v8doc.sas.com/sashtml/lgref/z0188182.htm

 

DATALINES

 



Indicates that data lines follow

 

Valid: in a DATA step
Category: File-handling
Type: Declarative
Aliases: CARDS, LINES
Restriction: Data lines cannot contain semicolons. Use DATALINES4 when your data contain semicolons.

 

But does not show that INFILE LINES is a valid alias for INFILE DATALINES.

https://v8doc.sas.com/sashtml/lgref/z0146932.htm

 

DATALINES | DATALINES4 specifies that the input data immediately follows the DATALINES or DATALINES4 statement in the DATA step. This allows you to use the INFILE statement options to control how the INPUT statement reads instream data lines.

Alias: CARDS | CARDS4
Featured in:

Changing How Delimiters are Treated

 

 

 

mkeintz
PROC Star

@hashman 

 

I admit, I've gone over from CARDS to DATALINES, primarily because it is more self-descriptive, which is not entirely the same as catering to a younger audience.  So I hold my head high even as I recall dropping a program/data deck of 300 ordered cards.

 

@novinosrin   Nice topic!

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
hashman
Ammonite | Level 13

@mkeintz:

I wonder if LOSTLINE or LOSTDATALINE would be more, uh, descriptive than LOSTCARD or whether it was debated at some point. If so, I guess the decision was "nope". 

novinosrin
Tourmaline | Level 20

Thank you @hashman  and @mkeintz  for clarifying. I didn't even know what punch cards was/is. Did some google and youtube to learn about it. So question 2 is answered. As usual well done Guru for the attention to details that lines fails in infile reference. Gosh I can't believe you thought along those lines to test that. I can't mark yet as Part 1 the biggie is still pending. 🙂 Still not convinced though many gave their generous time.

novinosrin
Tourmaline | Level 20

hmm that's embarrassing, true. Sounds like one should not be totally honest. Haha!

 

It's funny to reveal I was/am rather more interested in aircraft/jet engines from Doctorate in Physics than SAS that he knows. Smiley Tongue Not so many hash questions anymore lol

mkeintz
PROC Star

@novinosrin wrote:

.... I can't mark yet as Part 1 the biggie is still pending. 🙂 Still not convinced though many gave their generous time.


 

@novinosrin:  If you're not on comfortable grounds regarding your first question (classification of the null statement as executable), then let me ask you:

 

  What is your concept of an executable statement?

 

 

In the Data Step Statements: Reference document there are two statement categories: declarative and executable.  The distinction is:

 

 

Executable statements result in some action [underscoring is mine]  during individual iterations of the DATA step. Declarative statements supply information to SAS and take effect when the system compiles program statements.

 

The null statement is included in the list of executable statements, even though it results in "inaction" rather than "action".  But it certainly doesn't qualify as a declarative statement.

 

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
novinosrin
Tourmaline | Level 20

@mkeintz   Yes I read that piece too. That was also the reason that prompted to me ask. Fair enough, the compiler does something " active in-activity" on every iteration of the datastep is a way to accept the design though with a faint smile. 

 

I agree it doesn't have to be declarative that a compiler should act on it once and only once.  But again "active in-activity" seems rather strange though if somebody of your grace and accomplishments stamp the authority that it is correct, I will take that. 

 

However, if you let us be unbiased, there is not one realistic or even unrealistic utility that i can clearly think of and on the contrary besides the grave macro call error ( ; ) potential  it can cause that @hashman  pointed out. Sincerely, my very intention is, if the docs claim a useful utility, all I am asking is some measurable examples though unrealistic. Of course, one would think why ponder for something so trivial, but it's just that I am curious after all. Nothing more, nothing less.

 

Not sure if you remember,  a year ago or more, I asked you to help me understand conditional SET statement  with examples and you gave me tons of it. This one seems heading toward utility by means of active-inactivity.  And to make the matters more ill, what about the same in open code

 

PS In essence, the spiral could go back to "what makes the null statement NOT null"

 

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
  • 31 replies
  • 2007 views
  • 15 likes
  • 10 in conversation