0

I have a problem with some simple code I simply cannot resolve. I'm using Delphi 5 with all updates applied.

I have this code block:

procedure TForm1.LoadBtnClick(Sender: TObject);
var
   s1, s2, s3 : Textfile;
   sa, sb, RString, SQLString : string;
begin
  with sourcequery do begin
     Close;
     SQL.Clear;
     SQL.Add('delete * from source');
     ExecSQL;
     Close;
     AssignFile(S2, 'c:\delphi programs\events\source1.txt');
     AssignFile(S1, 'c:\delphi programs\events\source2.txt');
     Reset(s2);
     Reset(s1);
     while not eof(s1) do begin
        readln(s1, RString);
        SQLString := 'insert into source1(f1, f2) values(';
        SQLstring := SQLString+ QuotedStr(copy(Rstring, 1, pos(chr(9), Rstring)-1))+', ';
        SQLString := SQLString+QuotedStr(copy(Rstring, pos(chr(9),Rstring)+1,length(Rstring)))+')';
        with sourcequery do begin
           close;
           SQL.Clear;
           SQL.Add(SQLString);
           ExecSQL;
        end;
     end;
  end;
end;

When I try to compile it, though, it halts after "eof(" on this line:

 while not eof(s1) do begin

with the "missing operator or semi-colon" error message.

Try as I might I can find no error - missing operators OR semi-colons. I have commented the file-reading block out and it compiles fine. I've retyped it a number of times in case there were hidden special characters. So far this is the entire program apart from the header information.

Can anyone spot the silly error?

Johan
  • 74,508
  • 24
  • 191
  • 319
Capfka
  • 353
  • 2
  • 6
  • 15
  • 3
    You probably have a scope resolution issue. Try `while not System.eof(s1)...` instead. – 500 - Internal Server Error Apr 25 '14 at 13:33
  • 11
    and this is why you shouldn't use `with` – David A Apr 25 '14 at 13:41
  • Thanks 500, that did the trick. I have also tidied up the initial block where I delete the contents so that it is not the master block for the whole procedure. How do I give you the big tick? – Capfka Apr 25 '14 at 13:47
  • David A, why shouldn't I use "with"? It's a fairly basic structure in Delphi. – Capfka Apr 25 '14 at 13:47
  • And I don't think there should be an asterisk in your delete Sql (but maybe you're using an unusual Sql back-end). – MartynA Apr 25 '14 at 13:47
  • You should not use with because it pollutes your namespace – David Heffernan Apr 25 '14 at 13:55
  • 2
    "with" is evil, as it makes code hard to read. The IDE can't figure out what you mean, the next developer to look at the code will also be at a disadvantage. – Chris Thornton Apr 25 '14 at 13:56
  • MartynA - it used to be standard, but it's not any more. However, most database systems probably just ignore it. It works ... – Capfka Apr 25 '14 at 14:46
  • @Christhornton That's interesting. I would have thought it made the code easier to read. Is there a discussion I can read of the why's and wherefore's anywhere? – Capfka Apr 25 '14 at 14:50
  • 1
    "With Considered Harmful" -- http://hallvards.blogspot.com/2004/08/with-statement-considered-harmful.html – Nick Hodges Apr 25 '14 at 15:38
  • 2
    A nested with?!? It burns! IT BURNS! Make it stop! – Nick Hodges Apr 25 '14 at 15:39
  • Reasons for not using `with`, [Is Delphi “with” keyword a bad practice?](http://stackoverflow.com/questions/514482/is-delphi-with-keyword-a-bad-practice). – LU RD Apr 25 '14 at 16:58

1 Answers1

8

All your code is wrapped in a with sourcequery do begin block, so any identifier within that block is first checked for whether it could be a member of sourcequery. That variable, evidently, has a member named eof that isn't a function. The compiler binds the eof name to that non-function instead of the function you expected it to be bound to, and therefore complains when you attempt to use it like a function.

The best solution is to stop using with. It leads to problems like this, where the apparent scope of names doesn't match the one the compiler sees. It also leads to problems debugging (because of a long-standing bug in the debugger, where it interprets names the way you did here, rather than the way the compiler interprets them). It can lead to other bugs, too. If you don't like typing sourcequery.xyz all the time, then you can create an alias for sourcequery that doesn't take up so much room:

var
  sq: TypeOfSourceQuery;
begin
  sq := sourcequery;
  sq.Close;
  sq.SQL.Clear;
  ...

If you really don't want to use that solution, then you can use the quick-and-easy solution, which is to qualify the eof name with the unit it belongs to. In your case, you want the function defined in the System unit, so change your code to indicate that:

while not System.Eof(s1) do begin
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • Rob, thanks for that. I was going to remove the with block at the top of the program because it wasn't necessary anyway although I had planned to use it. I don't mind not using the with blocks if there is a technical reason not to do so, although they are very handy. – Capfka Apr 25 '14 at 14:59