Stata The Stata listserver
[Date Prev][Date Next][Thread Prev][Thread Next][Date index][Thread index]

st: RE: macro loop embedded in macro loop


From   "Nick Cox" <[email protected]>
To   <[email protected]>
Subject   st: RE: macro loop embedded in macro loop
Date   Wed, 10 Jul 2002 17:54:57 +0100

Arthur Mu (Jun Xu)
>
> I am writing an ado program that one macro loop embedded in
> another one.  I have figured a way around it, but kind of awkward, not
sure if
> there is an easy way to do it.
>
> The command will be like:
>
> mycommand var1 var2 var3 var4, model(reg) compare(1 2; 4 2; 3 2)
>
> I just extracted part of the Program that I am having problems with:
>
> *******************************************************
> capture program drop mycommand
> program define mycommand
> 	syntax [varlist] ,model(string) compare(string)
> 	tokenize `compare', parse("  ;  ")
>         local i=1
>
> 	while "`1'"~=""{
> 		...Do whatever I want for the macro's in `compare'
>                 ...
>                 ...
> 		tokenize `varlist'
>                 while "`1'"~=""{
>
>                 ...Do whatever I want for the macro's in `varlist'
>                 }
>
>                 tokenize `compare', parse (" ; ")
>                 local i=`i'+2
> 		macro shift `i'
>            }
> end
> ****************************************************
>
> What I am trying to do with `varlist' within the while loop is to capture
> individual variable information and store it into a matrix.  While the
> `compare' macro list is to run through each pair within "compare
> (1 2; 4 2;
> 3 2)", in which "1 2" encodes two equations by a group variable
> like female
> vs. male or white vs. black.  The problem here is: first I
> tokenize compare
> before the first while loop, and within the while loop I have another
> tokenize and the second while loop, which will overwrite the info
> stored by
> the first tokenize of `compare'.  To restore the order of the tokenized
> `compare', I tokenize compare again and use local i=`i'+2 and macro shift
> `i' to get away with it.  I am not sure if I correctly explained my
> question, which is "is there an easy way around it?  Otherwise if
> I need to
> have several tokenize and while loop's, then I will have to restore them
> each time as I did?"

You put your finger directly on the problem. In general, don't ever
overwrite any macros you know you want to use again. One way
to tackle this would to copy the results of the first -tokenize-
into another set of macros, something

tokenize `compare' ...
local i = 0
while "`i'" != "" {
	local i = `i' + 1
	local c`i' "`1'"
	mac shift
}

That way, the tokens of `compare' are
copied into local macros c1 c2 etc. And you can pick
up however many there are and later cycle
through them with a -forval- loop. And cut the repeated -tokenize-
from the middle.

Somewhere in the Stata Corp suggestion database
is a thought that adding a stub option to -tokenize-
would be useful for problems like these.

That is

tokenize ... , ... stub(c)

would mean that the tokens go into local macros c1 c2 etc.,
not the default 1 2 etc.

However, this can be done for yourself with -tknz-, which
I will send to Kit Baum.

program def tknz, rclass
*! NJC 1.1.0 2 June 2000
	version 6.0
	gettoken list 0 : 0, parse(",")
	syntax , Stub(str) [ * ]
	tokenize `"`list'"' , `options'

	local i = 1
	while "``i''" != "" {
		c_local `stub'`i' `"``i''"'
		local i = `i' + 1
	}
end

----------------------------------------------------------------------------
-----------------------
help for tknz
----------------------------------------------------------------------------
-----------------------

Tokenize string into named macros
---------------------------------

    tknz ["][string]["] , stub(stub) [ parse(pchars) ]

Description
-----------

tknz tokenizes string into tokens, storing the results in the local
macros stub1, stub2, etc. Tokens are determined based on the parsing
characters pchars, which defaults to a space if not specified.


Options
-------

stub(stub) specifies a stub for the macro names. This stub should be
    short enough for the complete names all to be legal. This is a
    required option.

parse(pchars) specifies the parsing characters.  If parse() is not
    specified, parse(" ") is assumed, and thus string is split into words.


Examples
--------

    . tknz `varlist', s(v)


Author
------

         Nicholas J. Cox, University of Durham, U.K.
         [email protected]


Acknowledgements
----------------

Vince Wiggins made very useful suggestions.





Nick
[email protected]

*
*   For searches and help try:
*   http://www.stata.com/support/faqs/res/findit.html
*   http://www.stata.com/support/statalist/faq
*   http://www.ats.ucla.edu/stat/stata/



© Copyright 1996–2024 StataCorp LLC   |   Terms of use   |   Privacy   |   Contact us   |   What's new   |   Site index