[fpc-pascal] with statement using mulltiple objects

johanns at nacs.net johanns at nacs.net
Mon Sep 15 16:42:28 CEST 2014

On Sun, Sep 14, 2014 at 02:30:01PM +0200, Marco van de Voort wrote:
>In our previous episode, J?rgen Hestermann said:
>>  > ---------------------------------------------------------
>>  > d:=TreeRoot.SubDirs[Low(TreeRoot.SubDirs)]; // local var d
>>  > d^.DirLogged             := true;
>>  > d^.DirHatFocus           := false;
>>  > d^.SubDirsExpanded       := true;
>>  > [...] ---------------------------------------------------------
>> Long-winded and still not the same clarity as in the with statement.
>But the important part is that it forces each property/field to be a member
>of T, or get a compiler error.
>WITH doesn't, and you risk that if your class or one of its ancestor has
>such property, and your error goes unnoticed.

I have to believe the WITH statement is more efficient 
than the C language equivalent where an extra 
convenience pointer is declared as a variable and 
allocated.  The WITH statement allows the compiler to 
generate the same code as a fully qualified variable name 
without extra overhead in the form of a dummy pointer.

Just as the GOTO statement needs to be used with careful, 
close locality of scope, the WITH statement should be used 
when the fields will all come from the same record 
definition and ideally have distinct names.  The safe 
approach would be to qualify all field references that are 
potentially ambiguous even while using a WITH statement.

The danger of surprises in scope evaluation for a simple 
and short variable name within a WITH statement scope are 
not that different from the danger of unit global 
variables.  Each unit creates its own local name space, 
which usually does the programmer a favor, but not always.
Now the order units are referenced in the USES statement 
of each individual unit matters.  What do you think 
happens when the programmer is casual about the USES order 
for helper utility units with duplicate global variable 

Unit FooUtil1;

var ErrorString : string;

Unit BarUtil2

var ErrorString : string;

Unit CodeSection;
uses FooUtil1, BarUtil1;

procedure Main
   ErrorString := ''; {Clears error string in last unit}

More information about the fpc-pascal mailing list