Hello,
I have a hard time understanding how the call vnext routine works. Can someone explain what is the logic
behind the output below ?
619
620
621 data _NULL_;
622 set sashelp.class;
623 length _VNAME_ $32.;
624
625 call vnext(_VNAME_);
626 put _N_ _VNAME_=;
627
628 call vnext(_VNAME_);
629 put _N_ _VNAME_=;
630
631 call vnext(_VNAME_);
632 put _N_ _VNAME_=;
633
634 run;
1 _VNAME_=Name
1 _VNAME_=Name
1 _VNAME_=Name
2 _VNAME_=Name
2 _VNAME_=Sex
2 _VNAME_=Sex
3 _VNAME_=Name
3 _VNAME_=Age
3 _VNAME_=Age
4 _VNAME_=Name
4 _VNAME_=Height
4 _VNAME_=Height
5 _VNAME_=Name
5 _VNAME_=Weight
5 _VNAME_=Weight
6 _VNAME_=Name
6 _VNAME_=_VNAME_
6 _VNAME_=_VNAME_
7 _VNAME_=Name
7 _VNAME_=_ERROR_
7 _VNAME_=_ERROR_
8 _VNAME_=Name
8 _VNAME_=_N_
8 _VNAME_=_N_
9 _VNAME_=Name
9 _VNAME_=
9 _VNAME_=Name
10 _VNAME_=Name
10 _VNAME_=Name
10 _VNAME_=Sex
11 _VNAME_=Name
11 _VNAME_=Sex
11 _VNAME_=Age
12 _VNAME_=Name
12 _VNAME_=Age
12 _VNAME_=Height
13 _VNAME_=Name
13 _VNAME_=Height
13 _VNAME_=Weight
14 _VNAME_=Name
14 _VNAME_=Weight
14 _VNAME_=_VNAME_
15 _VNAME_=Name
15 _VNAME_=_VNAME_
15 _VNAME_=_ERROR_
16 _VNAME_=Name
16 _VNAME_=_ERROR_
16 _VNAME_=_N_
17 _VNAME_=Name
17 _VNAME_=_N_
17 _VNAME_=
18 _VNAME_=Name
18 _VNAME_=
18 _VNAME_=Name
19 _VNAME_=Name
19 _VNAME_=Name
19 _VNAME_=Sex
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
Thanks.
Hello @gamotte,
Like @novinosrin this behavior of CALL VNEXT reminded me of the LAG function in that each occurrence of CALL VNEXT in the code seems to produce a separate "stream" of variable names (assumption 1). In addition, it seems that the routine returns a missing value after the last variable name and then starts another cycle with the first variable name (reminding me of the NEXT method of the hash iterator object) -- assumption 2 (edit: The first part of this assumption is also stated in the documentation). Together with these assumptions the two rules stated in the documentation (call them rule 1 and rule 2) explain the observed values (let's refer to the k-th row of the j-th _N_ value, i.e. j=_N_, k=1, 2, 3, as "j.k"):
HI @gamotte My guess is this logic is akin to how a lag function works- LAG1 seems fixed and is called for the same allocated queue, the item in the front of the queue is ejected (called dequeueing), and the value of the argument enters the rear of the queue (called enqueueing),
x = lag (x) ;
x = lag (x) ;
is not the same as:
do i = 1 to 2 ;
x = lag (x) ;
end ;
Disclaimer: It's a guess. I could be wrong!
Another guess:
1. Everytime a Call Vnext routine is executed, it probably increments an index variable by 1
2. The likelihood is that the variables are stored in a key indexed sequence.
3. The index variable ought to be automatic for processing and dropping
4. So for each independent Call Vnext routine, there's a unique index variable that is perhaps created
Hello @gamotte,
Like @novinosrin this behavior of CALL VNEXT reminded me of the LAG function in that each occurrence of CALL VNEXT in the code seems to produce a separate "stream" of variable names (assumption 1). In addition, it seems that the routine returns a missing value after the last variable name and then starts another cycle with the first variable name (reminding me of the NEXT method of the hash iterator object) -- assumption 2 (edit: The first part of this assumption is also stated in the documentation). Together with these assumptions the two rules stated in the documentation (call them rule 1 and rule 2) explain the observed values (let's refer to the k-th row of the j-th _N_ value, i.e. j=_N_, k=1, 2, 3, as "j.k"):
Here's some evidence related to a "queue per variable used" theory
176 data _NULL_; 177 set sashelp.class; 178 length _VNAME1 - _VNAME3 $32.; 179 180 call vnext(_VNAME1); 181 put _N_ _VNAME1=; 182 183 call vnext(_VNAME2); 184 put _N_ _VNAME2=; 185 186 call vnext(_VNAME3); 187 put _N_ _VNAME3=; 188 189 run; 1 _VNAME1=Name 1 _VNAME2=Name 1 _VNAME3=Name 2 _VNAME1=Name 2 _VNAME2=Name 2 _VNAME3=Name 3 _VNAME1=Name 3 _VNAME2=Name 3 _VNAME3=Name 4 _VNAME1=Name 4 _VNAME2=Name 4 _VNAME3=Name 5 _VNAME1=Name 5 _VNAME2=Name 5 _VNAME3=Name 6 _VNAME1=Name 6 _VNAME2=Name 6 _VNAME3=Name 7 _VNAME1=Name 7 _VNAME2=Name 7 _VNAME3=Name 8 _VNAME1=Name 8 _VNAME2=Name 8 _VNAME3=Name 9 _VNAME1=Name 9 _VNAME2=Name 9 _VNAME3=Name 10 _VNAME1=Name 10 _VNAME2=Name 10 _VNAME3=Name 11 _VNAME1=Name 11 _VNAME2=Name 11 _VNAME3=Name 12 _VNAME1=Name 12 _VNAME2=Name 12 _VNAME3=Name 13 _VNAME1=Name 13 _VNAME2=Name 13 _VNAME3=Name 14 _VNAME1=Name 14 _VNAME2=Name 14 _VNAME3=Name 15 _VNAME1=Name 15 _VNAME2=Name 15 _VNAME3=Name 16 _VNAME1=Name 16 _VNAME2=Name 16 _VNAME3=Name 17 _VNAME1=Name 17 _VNAME2=Name 17 _VNAME3=Name 18 _VNAME1=Name 18 _VNAME2=Name 18 _VNAME3=Name 19 _VNAME1=Name 19 _VNAME2=Name 19 _VNAME3=Name NOTE: There were 19 observations read from the data set SASHELP.CLASS. NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds
@ballardw: I think with a RETAIN _VNAME1-_VNAME3; statement added, the "evidence" will be more convincing because otherwise "rule 1" alone would already explain the result.
Thanks a lot @novinosrin and @FreelanceReinh for these insightful answers. It makes much more sense now.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.