st: re: getting the quotes right

Thanks to Zhiqiang Wang, Bill Gould, Thomas Steichen, Nick Cox, and Nick
Winter for contributing to getting the quotes right. (Quite a roster, that!)
The advice did not converge so here is an attempt at a synthesis with an
outcome that surprised me.
My original faulty construct (I have added line numbers and also added a
variable in the list command for improved troubleshooting):
1: local buicks (make=="Buick Century" | make=="Buick Electra" |
make=="Buick Opel")
2: local datsuns (make=="Datsun 200" | make=="Datsun 210")
3: local vws (make=="VW Dasher" | make=="VW Rabbit" | make=="VW Scirocco")
4: local brands `buicks' `datsuns' `vws'
5: foreach brand of local brands {
6: list make price if `brand'
7: }
Zhiqiang suggested to use compound double quotes in each case of lines 1-3,
e.g.:
(make==`"Buick Century"' etc. These are superfluous because they are at the
innermost level of nesting quotes but they do no harm. (He then gave the
substantive question an interpretation different from the one I had in mind
and changed the code accordingly.) Finally, he crucially introduced nested
single quotes. I called it recursive macro substitution when I thanked him.
Actually, in this context it probably functions as _delayed substitution_
(see [U] v. 7 p. 195 with an example involving global and local macros.) In
my code Zhiqiang's advice translates to an amended line 6:
6: list make price if ``brand''
What this does is to first substitute:
list make price if `<the first element of the macro brands>'
because it is in the context of -foreach-. Then this translates to:
list make price if `buicks'
which expands in the normal way to
list make price if (make=="Buick .... Opel")
At least I _think_ that is what is happening! With line 6 thus amended my
code works as intended.
Bill very logically explained the use of compound double quotes. As he said,
"because -foreach- parses on spaces and binds on quotes". His concrete
solution boils down to an amended line 4:
4: local brands `"`buicks'"' `"`datsuns'"' `"`vws'"'
and everything else as in the original (at least that's my interpretation).
Thomas tested Bill's variant with some modifications. He amended lines 1 to
3 so that they would look like this:
1: local buicks `"(make=="Buick .... Opel")"'
etc. (He added compound double quotes before and after the entire string
contained in the macro.) I tested this and it makes no difference. He also
used the following variation to line 6:
6: list make price if `"`brand'"'
which resulted in the error message
local macro name "(make=="Buick Century" | make=="Buick Electra |
make=="Buick Opel") too long
r(198);
(Nick helped identify this error correctly.) I think what happens is that
the compound double quotes here make -list- and -foreach- together
substitute
list make price if <macro with the name given by the first element
of the macro brands>
This macro has the following name, not content (according to the error
message):
"(make=="Buick Century" | make=="Buick Electra | make=="Buick Opel")
and doesn't exist, but at least we can conclude that -foreach- parsed the
_first element_ of the macro brands roughly where it should: it ends where
it should, but it includes an extraneous double quote at the beginning. In
fact, running Bill's code without Thomas's variation results in the error
message
too few quotes
r(132);
because the if statement now includes five regular double quotes. I believe
this is consistent with what I said above about how -foreach- parses its
macros so that the _delayed substitution_ could take place.
True or false? I am happy to let it rest here, since I have solved my
problem. I am also happy to contribute further should that be requested. But
I think the various contributions to this thread indicate that getting the
quotes right is not just a beginners' problem (at least sometimes). For one
thing, the rules of their use seems to depend on the exact context in which
they are to be applied, which would mean that one must know the parsing
rules for each command if one is to get the quotes right.
-- Håkon
hakon.finne@sintef.no
*
* 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/