Article ID: 125046
Article Last Modified on 2/18/2005
cClauses=" * FROM CUSTOMER WHERE cno='A'" SELECT &cClauses
-or-
cResetMenu="SET SYSMENU TO DEFAULT" &cResetMenu
cWindowName="test" DEFINE WINDOW (cWindowName) FROM 1,1 TO 20,50 SYSTEM
cScreen="Myscreen.spr" DO (cScreen)
cReport="Myreport.frx" REPORT FORM (cReport) PREVIEW ENVIRONMENTName expression compilation is optimized and does not require the creation of any "lookup" code, which makes it much more efficient than macro substitution. However, the limited scope of name expressions (they can only be used to evaluate variables used to name FoxPro components) required that another tool be used for evaluation of variables under other circumstances.
cCondition="CNO='A'"
@ 2,2 SAY "Type filter condition for appending records or hit <ENTER>:";
GET cCondition VALID CHECK()
READ
USE customer
APPEND FROM customer FOR EVALUATE(cCondition)
FUNCTION CHECK
* Validation code for expressions typed
RETURN .t. && or .f.
USE customer
cCondition = "CNO='A'"
SCAN FOR <condition>
* Processing code here>
ENDSCAN
In the above example, if &cCondition is used as the condition, the loop
will process one record only, because the condition is evaluated only when
the mini-compiler executes on-the-fly. Instead, the condition should be
"EVALUATE(cCondition)" (without the quotation marks), because EVALUATE()
can be called repeatedly because it is a native FoxPro function.
* Original code
...
IF CHECK() == .t.
WAIT WINDOW "This is the customer we're looking for"
ENDIF
FUNCTION CHECK
PRIVATE lRetVal
IF cno == 'A1592'
lRetval = .t.
ELSE
lRetVal = .f.
ENDIF
RETURN lRetVal
* Optimized code
IF CHECK()
WAIT WINDOW "This is the customer we're looking for"
ENDIF
FUNCTION CHECK
RETURN (cno=='A1592')
While it is true that reducing the size of the code in memory generally
helps speed up the code at runtime, it is not always true that reducing the
number of lines reduces the size of the application in memory, especially
when using macro substitution, because of the extra code that is built in
by the compiler. Also, even if the application size in memory is reduced,
the overhead incurred during macro evaluation slows the execution down
anyway. The following example illustrates this:
* Original code
* Parameter is numeric, determines which order to use
FUNCTION CustSort
PARAMETERS nSortType
DO CASE
CASE nSortType == 1
SELECT * FROM customer ORDER BY cno
CASE nSortType == 2
SELECT * FROM customer ORDER BY contact
CASE nSortType == 3
SELECT * FROM customer ORDER BY company
OTHERWISE
SELECT * FROM customer
END CASE
RETURN .t.
* Optimized code (but it will most likely not run faster)
* Parameter is character string, contains 'order by' clause
FUNCTION CustSort
PARAMETERS cOrderBy
IF !EMPTY(cOrderBy)
SELECT * FROM customer &cOrderBy
ELSE
SELECT * FROM customer
ENDIF
RETURN .t.
Note that these optimization concepts are fairly irrelevant with simplistic
examples like these. In a real-world application, the speed difference will
be more noticeable.
OVERLAPPING OF USAGE:
In some instances, EVALUATE() and name expressions can be interchanged. In
this case, there is no preferred method, although it would help the
developer to use name expressions whenever possible for consistency's sake.
Here is a situation where either method is acceptable:
cProc="Myproc.prg"
DO (cProc) && or DO EVALUATE("cProc")
Although macro substitution could also be used here, its use is not
demonstrated because of the reasons explained previously: speed,
efficiency, and consistency.
Keywords: kbinfo KB125046