Programming Statements
Programming Statements
Programming Statements
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
62
63
64
64
65
65
71
72
STOPPING EXECUTION
PAUSE Statement . . . . .
STOP Statement . . . . .
ABORT Statement . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
72
73
74
74
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
SUMMARY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
56
Chapter 5
Programming Statements
Overview
As a programming language, the Interactive Matrix Language has many features that
enable you to control the path of execution through the statements. The control statements in IML function in a way that is similar to the corresponding statements in the
SAS DATA step. This chapter presents the following control features:
IF-THEN/ELSE statements
DO groups
iterative execution
jumping (nonconsecutive execution)
module definition and execution
termination of execution.
IF-THEN/ELSE Statements
To perform an operation conditionally, use an IF statement to test an expression.
Alternative actions appear in a THEN clause and, optionally, an ELSE statement.
The general form of the IF-THEN/ELSE statement is
The IF expression is evaluated first. If the expression is true, execution flows through
the THEN alternative. If the expression is false, the ELSE statement, if present, is
executed. Otherwise, the next statement is executed.
The expression to be evaluated is often a comparison, for example,
if max(a)<20 then p=0;
else p=1;
58
When the condition to be evaluated is a matrix expression, the result of the evaluation
is a temporary matrix of 0s, 1s, and possibly missing values. If all values of the result
matrix are nonzero and nonmissing, the condition is true; if any element in the result
matrix is 0, the condition is false. This evaluation is equivalent to using the ALL
function.
For example, the statement
statement;
if x<y then
statement;
The expressions
if a^=b then
statement;
and
if ^(a=b) then
statement;
are valid, but the THEN clause in each case is executed only when all corresponding
elements of and are unequal.
If you require that only one element in not be equal to its corresponding element
in , use the ANY function. For example, evaluation of the expression
if any(a^=b) then
statement;
DO Groups
A set of statements can be treated as a unit by putting them into a DO group, which
starts with a DO statement and ends with an END statement. In this way, you can
submit the entire group of statements for execution as a single unit. For some programming applications, you must use either a DO group or a module. For example,
LINK and GOTO statements must be programmed inside of a DO group or a module.
The two principal uses of DO groups are
to group a set of statements so that they are executed as a unit
to group a set of statements for a conditional (IF-THEN/ELSE) clause
SAS OnlineDoc: Version 8
Iterative Execution
59
DO;
additional statements
END;
You can nest DO groups to any level, just like you nest IF-THEN/ELSE statements.
The following is an example of nested DO groups:
do;
statements;
do;
statements;
do;
statements;
end;
end;
end;
It is good practice to indent the statements in DO groups, as shown abovein the preceding statements so that their position indicates the levels of nesting.
For IF-THEN/ELSE conditionals, DO groups can be used as units for either THEN
or ELSE clauses so that you can perform many statements as part of the conditional
action. An example follows:
if x<y then
do;
z1=abs(x+y);
z2=abs(x-y);
end;
else
do;
z1=abs(x-y);
z2=abs(x+y);
end;
Iterative Execution
The DO statement also serves the feature of iteration. With a DO statement, you can
repeatedly execute a set of statements until some condition stops the execution. A
DO statement is iterative if you specify it with any of the following iteration clauses.
The type of clause determines when to stop the repetition.
60
DO Statement
DO DATA statement
iterative DO statement
DO WHILE statement
DO UNTIL statement
A DO statement can have any combination of these four iteration clauses, but a given
DO statement must be specified in the order listed in the preceding table.
DO DATA Statement
The general form of the DO DATA statement is
DO DATA;
The DATA keyword specifies that iteration is to stop when an end-of-file condition
occurs. The group is exited immediately upon encountering the end-of-file condition.
Other DO specifications exit after tests are performed at the top or bottom of the
loop. See Chapter 6, Working with SAS Data Sets, and Chapter 7, File Access,
for more information about processing data.
You can use the DO DATA statement to read data from an external file or to process
observations from a SAS data set. In the DATA step in base SAS software, the iteration is usually implied. The DO DATA statement simulates this iteration until the end
of file is reached.
The following example reads data from an external file named MYDATA and inputs
the data values into a vector. The data values are read one at a time into the dummy
variable XX and collected into the vector using the vertical concatenation operator
(//) after each value is read.
infile mydata;
do data;
input xx;
x=x//xx;
end;
/*
/*
/*
/*
/*
infile statement
begin read loop
read a data value
concatenate values
end loop
Iterative DO Statement
The general form of the iterative DO statement is
DO variable=start TO stop < BY increment > ;
The variable sequence specification assigns the start value to the given variable. This
value is then incremented by the increment value (or by 1 if increment is not specified)
until it is greater than or equal to the stop value. (If increment is negative, then the
iterations stop when the value is less than or equal to stop.)
For example, the following statement specifies a DO loop that executes by multiples
of 10 until I is greater than 100:
do i=10 to 100 by 10;
*/
*/
*/
*/
*/
Jumping
61
DO WHILE Statement
The general form of the DO WHILE statement is
DO WHILE expression;
With a WHILE clause, the expression is evaluated at the beginning of each loop, with
repetition continuing until the expression is false (that is, until the value contains a 0
or missing value). Note that if the expression is false the first time it is evaluated, the
loop is not executed.
For example, if the variable COUNT has an initial value of 1, the statements
do while(count<5);
print count;
count=count+1;
end;
DO UNTIL Statement
The general form of the DO UNTIL statement is
DO UNTIL expression;
The UNTIL clause is like the WHILE clause except that the expression is evaluated
at the bottom of the loop. This means that the loop always executes at least once.
For example, if the variable COUNT has an initial value of 1, the statements
do until(count>5);
print count;
count=count+1;
end;
Jumping
During normal execution, statements are executed one after another. The GOTO and
LINK statements instruct IML to jump from one part of a program to another. The
place to which execution jumps is identified by a label, which is a name followed
by a colon placed before an executable statement. You can program a jump by using
either the GOTO statement or the LINK statement:
GOTO label;
LINK label;
62
do;
if x<0 then link negative;
y=sqrt(x);
print y;
stop;
negative:
print "Using Abs. value of negative X";
x=abs(x);
return;
end;
The following is a comparable way to write the program on the left without using
GOTO or LINK statements:
if x<0 then print "Sorry, X is negative";
else
do;
y=sqrt(x);
print y;
end;
Modules
Modules are used for
creating groups of statements that can be invoked as a unit from anywhere in
the program, that is, making a subroutine or function
creating a separate (symbol-table) environment, that is, defining variables that
are local to the module rather than global
Nesting Modules
63
A module always begins with the START statement and ends with the FINISH statement. Modules can be thought of as being either functions or subroutines. When a
module returns a single parameter, it is called a function and is executed as if it were
a built-in IML function; a function is invoked by its name in an assignment statement
rather than in a CALL or RUN statement. Otherwise, a module is called a subroutine,
and you execute the module in either the RUN statement or the CALL statement.
START < name > < ( arguments ) > < GLOBAL( arguments ) > ;
Modules end with a FINISH statement, which has the general form
The RUN and CALL statements must have arguments to correspond to the ones defined for the modules they invoke. A module can call other modules provided that it
never recursively calls itself.
The RUN and CALL statements have orders of resolution that need to be considered
only when you have given a module the same name as a built-in IML subroutine. In
such cases, use the CALL statement to execute the built-in subroutine and the RUN
statement to execute the user-defined module.
The RUN statement is resolved in the following order:
1. user-defined module
2. IML built-in function or subroutine
The CALL statement is resolved in the following order:
1. IML built-in subroutine
2. user-defined module
SAS OnlineDoc: Version 8
64
Nesting Modules
You can nest one module within another. You must make sure that each nested module is completely contained inside of the parent module. Each module is collected
independently of the others. When you nest modules, it is a good idea to indent the
statements relative to the level of nesting, as shown in the following example:
start a;
reset print;
start b;
a=a+1;
finish b;
run b;
finish a;
run a;
In this example, IML starts collecting statements for a module called A. In the middle
of this module, it recognizes the start of a new module called B. It saves its current
work on A and collects B until encountering the first FINISH statement. It then
finishes collecting A. Thus, it behaves the same as if B were collected before A, as
shown below:
start b;
a=a+1;
finish;
start a;
reset print;
run b;
finish;
run a;
65
*/
*/
*/
*/
*/
*/
*/
*/
*/
run mod1;
print a b c p q;
A
10
B
20
C
40
P
30
Q
10
66
When a module is executed with either a RUN or a CALL statement, the value for
each argument is transferred from the global symbol table to the local symbol table.
For example, consider the module MOD2 defined in the following statements. The
first four statements are submitted in the global environment, and they define variables (A,B,C, and D): the values of these variables are stored in the global symbol
table. The START statement begins definition of MOD2 and lists two variables (X
and Y) as arguments. This creates a local symbol table for MOD2. All symbols used
inside the module (X, Y, P, Q, and C) are in the local symbol table. There is also a
one-to-one correspondence between the arguments in the RUN statement (A and B)
and the arguments in the START statement (X and Y). Also note that A, B, and D
exist only in the global symbol table, whereas X, Y, P, and Q exist only in the local
symbol table. The symbol C exists independently in both the local and global tables.
When MOD2 is executed with the statement RUN MOD2(A,B), the value of A is
transferred from the global symbol table to X in the local table. Similarly, the value
of B in the global table is transferred to Y in the local table. Because C is not an
argument, there is no correspondence between the value of C in the global table and
the value of C in the local table. When the module finishes execution, the final values
of X and Y in the local table are transferred back to A and B in the global table.
>
>
>
>
>
>
>
>
>
>
>
proc iml;
a=10;
b=20;
c=30;
d=90;
start mod2(x,y);
p=x+y;
q=y-x;
y=100;
c=25;
finish mod2;
/* begin module */
/* end module
*/
run mod2(a,b);
print a b c d;
A
10
B
100
C
30
D
90
The PRINT statement prints the values of variables in the global symbol table. Notice
that
A is still 10
B is changed to 100 since the corresponding argument Y was changed to 100
inside the module
SAS OnlineDoc: Version 8
67
C is still 30. Inside the module, the local symbol C was set equal to 25, but
there is no correspondence between the global symbol C and the local symbol
C.
D is still 90
Also note that, inside the module, the symbols A, B, and D do not exist. Outside the
module, the symbols P, Q, X, and Y do not exist.
proc iml;
a=10;
b=20;
c=30;
d=90;
start mod3(x,y);
p=x+y;
q=y-x;
y=100;
c=40;
return (c);
finish mod3;
z = mod3(a,b);
print a b c d z;
/* call function
A
10
B
100
C
30
*/
D
90
Z
40
68
Again note that, inside the module, the symbols A, B, D, and Z do not exist. Outside
the module, symbols P, Q, X, and Y do not exist.
In the next example, you define your own function ADD for adding two arguments:
>
>
>
>
>
>
proc iml;
reset print;
start add(x,y);
sum=x+y;
return(sum);
finish;
>
>
2
7
B
1
8
6
10
C
10
13
8
17
c=add(a,b);
Function modules can also be called inside each other. For example, in the following
statements, the ADD function is called twice from within the first ADD function:
>
>
d=add(add(6,3),add(5,5));
print d;
D
19
69
This means that you should not use a name for a function that is already the name of
an IML built-in function.
proc iml;
a=10;
b=20;
c=30;
d=90;
start mod4(x,y) global (c);
p=x+y;
q=y-x;
y=100;
c=40;
d=500;
finish mod4;
NOTE: Module MOD4 defined.
>
>
run mod4(a,b);
print a b c d;
A
10
B
100
C
40
D
90
Also note that every module with arguments has its own local table; thus it is possible
to have a global and many local tables. A variable can independently exist in one or
more of these tables. However, a variable can be commonly shared between the
global and any number of local tables when the GLOBAL clause is used.
70
>
>
>
>
>
>
>
>
start mod3(w,v);
w=w#v;
finish mod3;
NOTE: Module MOD3 defined.
The local symbol table of MOD1 in effect becomes the global table for MOD2. The
local symbol table of MOD2 is the global table for MOD3. The distinction between
the global and local environments is necessary only for modules with arguments. If a
module (say, A) calls another module (say, B) which has no arguments, B shares all
the symbols existing in As local symbol table.
For example, consider the following statements:
>
>
>
>
>
>
>
>
>
x=457;
start a;
print from a x;
finish;
start b(p);
print from b p;
run a;
finish;
run b(x);
from b
P
457
71
In this example, module A is called from module B. Therefore, the local symbol table
of module B becomes the global symbol table for module A. Module A has access to
all symbols available in module B. No X exists in the local environment of module B;
thus no X is available in module A as well. This causes the error that X is unvalued.
proc iml;
reset printall;
start square(a,b);
a=b##2;
finish;
/* create two data matrices
x={5 9 };
X
1 row
5
>
2 cols
(numeric)
y={10 4};
Y
>
>
>
>
>
*/
/*
do i=1
run
end;
/*
1 row
2 cols
(numeric)
10
4
pass matrices to module element-by-element
to 2;
square(x[i],y[i]);
RESET PRINTALL prints all intermediate results
I
1 row
1 col
*/
*/
(numeric)
#TEM1002
1 row
1 col
(numeric)
10
#TEM1001
1 row
1 col
(numeric)
72
1 row
1 col
(numeric)
100
#TEM1002
1 row
1 col
(numeric)
#TEM1001
1 row
1 col
(numeric)
9
A
1 row
1 col
(numeric)
16
>
>
X
5
*/
Y
10
The symbol X remains unchanged because the temporary variables that you generally
do not see are changed. Note that IML will properly warn you of any such instances
in which your results may be lost to the temporary variables.
Module Storage
You can store and reload modules using the forms of the STORE and LOAD statements as they pertain to modules:
STORE MODULE=name;
LOAD MODULE=name;
You can view the names of the modules in storage with the SHOW statement:
show storage;
See Chapter 14, Storage Features, for details on using the library storage facilities.
Stopping Execution
You can stop execution with a PAUSE, STOP, or ABORT statement. The QUIT
statement is also a stopping statement, but it immediately removes you from the IML
environment; the other stopping statements can be performed in the context of a program. Following are descriptions of the STOP, ABORT, and PAUSE statements.
SAS OnlineDoc: Version 8
PAUSE Statement
73
PAUSE Statement
The general form of the PAUSE statement is
A RESUME statement enables you to continue execution at the place where the most
recent PAUSE statement was executed.
You can use a STOP statement as an alternative to the RESUME statement to remove
the paused states and return to the immediate environment outside of the module.
You can specify a message in the PAUSE statement to display a message as the pause
prompt. If no message is specified, IML displays the following default message:
paused in module \ob XXX\obe
where XXX is the name of the module containing the pause. To suppress the display
of any messages, use the * option:
pause *;
When you use the PAUSE, RESUME, STOP, or ABORT statement, you should be
aware of the following details:
The PAUSE statement can be issued only from within a module.
IML diagnoses an error if you execute a RESUME statement without any
pauses outstanding.
You can define and execute modules while paused from other modules.
SAS OnlineDoc: Version 8
74
STOP Statement
The general form of the STOP statement is
STOP;
The STOP statement stops execution and returns you to immediate mode, where new
statements that you enter are executed. If execution is interrupted by a PAUSE statement, the STOP statement clears all pauses and returns to immediate mode of execution.
ABORT Statement
The general form of the ABORT statement is
ABORT;
The ABORT statement stops execution and exits from IML much like a QUIT statement, except that the ABORT statement is executable and programmable. For example, you may want to exit IML if a certain error occurs. You can check for the error
SAS OnlineDoc: Version 8
Summary
75
in a module and program an ABORT statement to execute if the error occurs. The
ABORT statement does not execute until the module is executed, while the QUIT
statement executes immediately and ends the IML session.
Summary
In this chapter you learned the basics of programming with SAS/IML software. You
learned about conditional execution (IF-THEN/ELSE statements), grouping statements as a unit (DO groups), iterative execution, nonconsecutive execution, defining
subroutines and functions (modules), and stopping execution. With these programming capabilities, you are able to write your own sophisticated programs and store
the code as a module. You can then execute the program later with a RUN or CALL
statement.
The correct bibliographic citation for this manual is as follows: SAS Institute Inc., SAS/
IML Users Guide, Version 8, Cary, NC: SAS Institute Inc., 1999. 846 pp.
SAS/IML Users Guide, Version 8
Copyright 1999 by SAS Institute Inc., Cary, NC, USA.
ISBN 1580255531
All rights reserved. Printed in the United States of America. No part of this publication
may be reproduced, stored in a retrieval system, or transmitted, in any form or by any
means, electronic, mechanical, photocopying, or otherwise, without the prior written
permission of the publisher, SAS Institute Inc.
U.S. Government Restricted Rights Notice. Use, duplication, or disclosure of the
software by the government is subject to restrictions as set forth in FAR 52.22719
Commercial Computer Software-Restricted Rights (June 1987).
SAS Institute Inc., SAS Campus Drive, Cary, North Carolina 27513.
1st printing, October 1999
SAS and all other SAS Institute Inc. product or service names are registered trademarks
or trademarks of SAS Institute Inc. in the USA and other countries. indicates USA
registration.
Other brand and product names are registered trademarks or trademarks of their
respective companies.
The Institute is a private company devoted to the support and further development of its
software and related services.