>>3: & the macro expansion feature is too often used where it is either not necessary or ther is a bettter way to accomplish the same goal.
>
>Macro expansion is sometimes the only possibility, and sometimes more readable. Suppose, I've the following to code snippets when lcAlias is the current alias:
>
>? &lcAlias..Field
>
>? EVALUATE(m.lcAlias+".Field")
>
I prefer the EVAL() approach, for a couple of reasons:
(1) You can't directly use macro expansion against an object reference or field; name expansion and evaluation both accomodate this.
Which of these is clearer:
myVar = EVAL(oApp.SomePropertyOrMethod+ 'a string literal')
or
lcExpression = oApp.SomePropertyOrMethod + 'a string literal'
myVar = &lcExpression
>Which one is more readable? Macro expansion should not be over-used, but it should not be avoided at any cost, neither. As a basic thumb of rule:
>
>a) Use naming expressions whenever possible. A naming expression can be used for all commands where a name is required as part of the command. A name is a tag name, a variable name, an alias, etc. For example:
>
>USE (cTable)
>REPLACE (cField) with Value IN (cAlias)
>SET ORDER TO (cTag)
>INDEX ON expression TAG (cTag)
>
And you can expand this utility to variable assignment by using STORE - while you can't legitmately say:
(cMyVar) = SomeValue
The following is valid:
STORE SomeValue TO (cMyVar)
>b) Use evaluation when you replace an expression that is not used directly by VFP. For example, you can use:
>
>STORE EVALUATE("expression") TO (cVarName)
>IF EVALUATE("expression")
>oRef = EVALUATE("expression")
>
>c) Use macro substitution for two reasons only: If the code actually substitutes part of a command, and not just a name or an expression. And if it increases readability. A typical usage can be:
>
>USE table &cOptions
>
I tend to restate this as use macro expansion where you need to have VFP's command parser get involved in handling the resultant statement.
>Be aware that in commands that evaluate the expression further, this expression is part of the command, and not an expression that can be replaced with EVALUATE(). This is true for
>
>SET FILTER TO &cFilter
>INDEX ON &cExpression...
>SELECT &cExpression FROM
>SCAN FOR &cExpression
>
Actually, you can use EVAL() in all but the SELECT statement. EVAL() can't be used in the SELECT example you give, because cExpression expands to a list of names.
In general, the cost of EVAL() is high in loop/repetition conditions; the macro-expansion is performed once for the statement as a whole, and not executed against each iteration. OTOH, using EVAL() within a loop generally is preferable because EVAL() has a lower cost of use on a one-time basis than macro expansion. Within the confines of the loop, EVAL() is strongly preferable to macro expansion. Name expansion is almost always preferable to macro-expansion where it fits; substitution for multiple names as in the SELECT &cExpression example is not one of them.