I don't know why this issue is a big issue. Personally I like "with" very much.
- Scoping and readability
Sometimes I was confused of "with" scope, and made some mistakes. But confusion is only when same identifiers are used within and outside "with" scope. Now I understand exactly how it works and love even using nested "with"s. Backward checking is all that is necessary.
I might have different attitude because I do not write many programs but use one program frequently. So once functions/procedures are written correctly, I seldom have to look into it again line by line. Instead, I only have to see it again to find out my "logic" or alrorithm of the routine. In this case, "with" improves readability by large, as I do not have to worry about any inconsistencies within there. Compare following example.
V1 := SQLQuery1.FieldByName('F1').AsString;
V2 := SQLQuery1.FieldByName('F2').AsString;
V3 := SQLQuery1.FieldByName('F3').AsString;
V4 := SQLQuery1.FieldByName('F4').AsString;
V5 := SQLQuery2.FieldByName('F5').AsString;
vs.
with SQLQuery1 do begin
V1 := FieldByName('F1').AsString;
V2 := FieldByName('F2').AsString;
V3 := FieldByName('F3').AsString;
V4 := FieldByName('F4').AsString;
end;
V5 := SQLQuery2.FieldByName('F5').AsString;
I can promptly see that V5 comes from different dataset from other variables.
- Regarding Temporary Storage
Function results are maintained temporarily. But this is not true if a memory space is allocated from heap, not local stack. Object Orinted Programming approach was not easy at first for me. It didn't have much meaning than simply collecting codes in one place. But now I came to a conclusion that it's not that superficial. Instances of classes, i.e. objects, exist at some place in a world created by me - my program space, until I destoy it. Function result is temporary but not the object (or any record or integer to which heap memory has been allocated). So in the case of
"with Test do ... " we are not accessing function result but the persistent object created by the function. The object created with "with" is temporary but not always if the object has reference to its container, etc. For example,
type
TMyObject = class
...
FPGMap: TFPGMapObject<integer, TMyObject>;
var1, var2: string;
..
end;
var
AFPTMapObject : TFPGMapObject<integer, TMyObject>;
implementation
constructor TMyObject.Create(AnIndex: integer; FMap: TFPGMapObject);
begin
inherited;
FPGMap := FMap;
FPGMap.Add(AnIndex, Self);
end;
begin
with DataSet do begin
First;
while not eof do begin
with TMyObject.Create(FieldByName('index').AsInteger, AFPGMapObject)
do begin
var1 := FieldByName('Title').AsString;
var2 := FieldByName('Description').AsString;
end;
Next;
end ; // while
end; // with DataSet
.........
AFPGMapObject.Free;
end.
I love this kind of codes, as this reduces the number of key typings, and is much easier to understand what this part of codes try to do.
- Overall trends
Recently popular programming languages seem to allow more features. The only other language I know than Pascal is javascript, but anyway its systax like
if (a=2) is valid and returns always true (which caused me many mistakes. I should have written "a==2"). Pascal has tradition but I believe we don't have to resist new trends too strongly. Further, sometimes I wish pascal had feature like :
with (aclass := TMyClass.Create) do begin
.......
end;
......
aclass.free;
Of course I can write
aclass := TMyClass.Create;
with aclass do begin
.....
end;
aclass.free;
But this requires reading whole routine to find where aclass is created.
Conclusion: I love "with" because it lessens my cognitive efforts, except at the first writing of codes.