Record Buffer Rule 4: If you have a free reference to a buffer, the AVM tries to scope that buffer to the nearest enclosing block with record scoping properties (that is, a FOR EACH block, a DO FOR block, or a REPEAT block). If no block within the procedure has record scoping properties, then the AVM scopes the record to the entire procedure.

The FIND statements are called free references because they do not define a scope for the buffer, they just reference it. Therefore, the AVM has to identify some scope for the record beyond the FIND statement. When a block has record scoping properties, it is a block the AVM might try to scope a record to, when the record is referenced inside the block.

Here is another variation on the testscope.p procedure that demonstrates this rule:

DEFINE VARIABLE fLimit AS DECIMAL NO-UNDO.

FOR EACH Customer NO-LOCK WHERE Customer.State = "NH" 
  BY Customer.CreditLimit DESCENDING:
  IF fLimit = 0 THEN
    fLimit = Customer.CreditLimit.
  DISPLAY Customer.CustNum Customer.Name Customer.CreditLimit.   
END.

FIND FIRST Customer WHERE Customer.CreditLimit > fLimit.
DISPLAY Customer.CustNum Customer.Name Customer.CreditLimit.

This procedure is perfectly valid. The first time through the FOR EACH loop, the procedure saves off the CreditLimit for use later in the procedure. Because the fLimit variable is initialized to zero, checking for fLimit = 0 tells you whether it has already been set. When you run it, you see all the New Hampshire Customer records followed by the first Customer with a CreditLimit higher than the highest value for New Hampshire Customers. Because there is no conflict with two blocks trying to use the same buffer at the same time, it compiles and runs successfully.

But the rule that the AVM raises the scope in this situation is a critically important one. In complex procedures, the combination of buffer references you use might force the AVM to scope a record buffer higher in the procedure than you expect. Though this normally does not have a visible effect when you are just reading records, when you get to the discussion of transactions this rule becomes much more important. If you generate another listing file for this procedure, you see the effect of the FIND statement:

{} Line Blk
-- ---- ---
      1     DEFINE VARIABLE fLimit AS DECIMAL NO-UNDO.
      2     
      3     FOR EACH Customer NO-LOCK WHERE Customer.State = "NH" 
      4   1   BY Customer.CreditLimit DESCENDING:
      5   1   IF fLimit = 0 THEN
      6   1     fLimit = Customer.CreditLimit.
      7   1   DISPLAY Customer.CustNum Customer.Name Customer.CreditLimit.   
      8     END.
      9     
     10     FIND FIRST Customer WHERE Customer.CreditLimit > fLimit.
     11     DISPLAY Customer.CustNum Customer.Name Customer.CreditLimit.

     File Name       Line Blk. Type   Tran            Blk. Label            
-------------------- ---- ----------- ---- --------------------------------
.\testscope.p           0 Procedure   No                                    
    Buffers: Sports2020.Customer
    Frames:  Unnamed

.\testscope.p           3 For         No                                    
    Frames:  Unnamed

This tells you that the Customer buffer is scoped at line 0, that is, to the procedure itself. There is no reference to the Customer buffer in the information for the FOR block at line 3 because the AVM has already scoped the buffer higher than that block.

Next is the rule concerning combining FIND statements with strong-scoped, rather than weak-scoped references.