Re: st: Submitting a command in a couples of pieces

Adrian Sayers <Adrian.Sayers@bristol.ac.uk> asks,
> [...] i want stata to ask me a question, then i want to key the
> response, and then i want stata to run a program. It sounds a little
> pointless but i am trying read in 3000 odd data files plot them and then
> trim the file to the relevant section.
>
> eg.
> di "What is the first day of data collection?"
> Type 3
> di "Day of first data collection = 3"
> drop if day<3
Martin Weiss <martin.weiss1@gmx.de> replied,
> *************
> di "What is the first day of data collection?" _request(day)
> 3
> di "Day of first data collection =$day "
> drop if day<$day
> *************
Exactly right. Let me add a few details.
-_request()- will store the result in a local macro if you prefix its name
with an underscore, so Martin's answer could have read,
di "What is the first day of data collection?" _request(_day)
3
di "Day of first data collection =`day' "
drop if day<`day'
Note that I put -_day- in the -_request()-, but even so, after that, I
referred to -`day'- just as I usually would.
Here's Martin's answer put into a -program-, which might be an ado-file:
program trythis
version 11
di "What is the day of the data collection? " _request(_day)
di "Day of the first data collection = `day'"
drop if day<`day'
end
I next suggest to Adrian that if he is going to ask more than one question,
he must anticipate that users will sometimes mistype their answers.
Most commonly, they will hit Return before typing any answer. As I result,
I recommend creating a subroutine to get answers:
program trythis
version 11
askquestion "What is the day of the data collection?"
local day "`s(answer)'"
di "Day of the first data collection = `day'"
drop if day<`day'
end
program askquestion, sclass
args last_line_of_text
while (1) {
di as txt "`last_line_of_text' -> " _request(_answer)
if ("`answer'"=="") {
di as txt "Please answer question, or type" ///
as res "qq" as txt "to break."
}
else if ("`answer'"=="qq") {
exit 1
}
else {
sreturn local answer "`answer'"
exit
}
}
end
In the above code, if the user just presses Return, the question is asked
again. The user can type -qq- to have the code break (stop asking questions).
If I were Adrian, I would also check the lexical class of the answer in
subroutine -askquestion-. Sometimes answers can be text, even blank,
and other times they must be numbers, and even integers. Adrian needs
to think about the types of the answers he will need. As a simple example,
we might modify -askquestion- to allow the caller to specify one of the
following lexical types:
text (meaning a non-blank string)
number (any number, and only a number)
integer (any number that is an integer)
I would then construct code that looks something like this,
program askquestion, sclass
args lex_class last_line_of_text
while (1) {
sreturn clear
askqustion_ask "`last_line_of_text'"
local answer "`s(answer)'"
if ("`answer'"=="qq") {
exit 1
}
if ("`answer'"!="") {
askquestion_check `lex_class' "`answer'"
if (`"s(invalid)'"=="") {
sreturn local answer "`answer'"
exit
}
}
else {
di as txt "Please answer question, or type" ///
as res "qq" as txt "to break."
}
}
end
program askquestion_ask, sclass
args text
di as txt "`text'" -> " _request(_answer)
sreturn local answer "`answer'"
end
program askquestion_check, sclass
args lex answer
if ("`lex'"=="text") {
exit
}
if ("`lex'"=="number") {
capture confirm number `answer'
if (_rc) {
di "You must answer with a number"
sreturn local invalid invalid
}
exit
}
if "`lex'"=="integer") {
capture confirm number `answer'
if (_rc) {
di "You must answer with an integer"
sreturn local invalid invalid
}
exit
}
di as error "Invalid lexical class -`lex'-"
di as error "caller has error"
exit 198
end
All that said, there's nothing wrong with Martin's original answer if
Adrian will only be asking a few questions and asking them of himself.
-- Bill
wgould@stata.com
*
* For searches and help try:
* http://www.stata.com/help.cgi?search
* http://www.stata.com/support/statalist/faq
* http://www.ats.ucla.edu/stat/stata/