Recent

Author Topic: [SOLVED] Beginners OOP Question  (Read 11763 times)

MathMan

  • Sr. Member
  • ****
  • Posts: 325
[SOLVED] Beginners OOP Question
« on: July 29, 2014, 12:58:03 pm »
I am currently feeling pretty stupid regarding the following.

I have a test routine that gets activated from the menu. Instead of showing test results via ShowMessage() boxes I wanted to dump the results to a file. This seemed pretty straight forward to me intially. I started with

Code: [Select]
procedure TLongCalc.MenuTestClick(Sender: TObject);

var
  fResult: TEXT;

  ...

begin

  ...

  Assign( fResult, 'results.txt' );
  Append( fResults );

  ...

  WriteLn( fResult, ... );

  ...

  Close( fResult );

end;

But this brought up an (initially) obscure error message "Wrong number of parameters". I scanned the ref-manual but no - Assign(), Append() and Close() for files are defined the way i use them. Then I discovered that the Assign() statement was resolved via "classesh.inc" - I banged my head and thought "Gee you dummy - obviously you are in the instance of the application class so hint the compiler on using the file Assign()". And that's where it stopped. I read a lot of the online tutorials on object programming with FP / Laz, read all i could find on file handling etc. in the prog- & ref-manuals, read relevant parts in the systems unit definition, read ...

Now it's all tangled up as things do not seem to match and after trying three or four different unsuccessfull ways of correctly dereferencing i give up.

However this looks very fundamental to me and I need to understand where I thought wrong and how I need to think - otherwise I am sure i won't get far with FP / Laz.

BTW this is the uses clause for "Main" (where the test Routine resides) in my application

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Menus;

« Last Edit: July 29, 2014, 04:01:50 pm by MathMan »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Beginners OOP Question
« Reply #1 on: July 29, 2014, 01:42:03 pm »
Best to use AssignFile (rather than Assign) and CloseFile (rather than Close).

But don't reinvent the wheel. Add LazLogger to your uses clause and benefit from powerful logging functionality that is already available in the IDE.

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Beginners OOP Question
« Reply #2 on: July 29, 2014, 01:43:11 pm »
But don't reinvent the wheel. Add LazLogger to your uses clause
See also http://wiki.lazarus.freepascal.org/LazLogger

(However note bug
http://bugs.freepascal.org/view.php?id=26537
LazLogger: setting *_debuglog environment variable does not work: no log so you'd best start the application with the --debug-log parameter)
« Last Edit: July 29, 2014, 01:44:46 pm by BigChimp »
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

MathMan

  • Sr. Member
  • ****
  • Posts: 325
Re: Beginners OOP Question
« Reply #3 on: July 29, 2014, 02:37:46 pm »
Best to use AssignFile (rather than Assign) and CloseFile (rather than Close).

But don't reinvent the wheel. Add LazLogger to your uses clause and benefit from powerful logging functionality that is already available in the IDE.

Thanks! I think I understand what LazLogger provides after reading a bit in the CHM files.

However

 1 - CloseFile is only avail with LazLogger, correct?
 2 - The docs show no reference to AssignFile - so where is this coming from?
 3 - my main question unfortunately is still open and it is really important for me to understand. Any guidance highly appreciated.

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Beginners OOP Question
« Reply #4 on: July 29, 2014, 02:41:51 pm »
1. No, it's not. If you type closefile and hover over it with your mouse you'll see where it is defined (objpas => presumably part of the FPC RTL? don't know)
2. HOver over assignfile as well; you should see some comments taken from the help file sources or even the source code of assignfile. It gives a description of what assignfile does.

Edit: FYI, if you surround your code with code tags (see the button marked # on the toolbar when editing), it makes your code in posts easier to read...
« Last Edit: July 29, 2014, 02:43:34 pm by BigChimp »
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Beginners OOP Question
« Reply #5 on: July 29, 2014, 02:46:31 pm »
Regarding finding out what functions do/how they are defined etc, if you right-click on it choose FInd Declaration... which takes you to the function that the compiler (or the IDE, but those should be the same) thinks you are using, including parameters etc.
If functions are defined in multiple units (e.g. in windows as well as sysutils, prefix the unit name - windows.bla or sysutils.bla to force on e of them)
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

MathMan

  • Sr. Member
  • ****
  • Posts: 325
Re: Beginners OOP Question
« Reply #6 on: July 29, 2014, 03:07:34 pm »
1. No, it's not. If you type closefile and hover over it with your mouse you'll see where it is defined (objpas => presumably part of the FPC RTL? don't know)
2. HOver over assignfile as well; you should see some comments taken from the help file sources or even the source code of assignfile. It gives a description of what assignfile does.

Edit: FYI, if you surround your code with code tags (see the button marked # on the toolbar when editing), it makes your code in posts easier to read...

1&2. Neither AssignFile nor CloseFile get resolved this way, Append however does (as expected I get feedback that it is defined in systemsh.inc)
Does the resolver require that the unit is in the uses-clause?

Edit: I'll keep that in mind, thanks.

Re. your other comment - the right click and selecting "Find Declaration" had no effect whatsoever unfortunately
Before you ask - I made a clean installation and changed nothing on the system so far. Only choice I made on install was selecting "German" as installation language

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Beginners OOP Question
« Reply #7 on: July 29, 2014, 03:13:34 pm »
Does the resolver require that the unit is in the uses-clause?
Yes, it does. See Howard's answer below - I'm sure he's right ;)

Re. your other comment - the right click and selecting "Find Declaration" had no effect whatsoever unfortunately
Before you ask - I made a clean installation and changed nothing on the system so far. Only choice I made on install was selecting "German" as installation language
It'll have to find the function first... given your response above it seems it doesn't?

Note: probably best to post the entire source code to your program if it's not too long so others can test easily with the same uses clauses etc.
Project/Publish project lets you publish only the source code to a new directory which you can zip up and attache to a post (of course if it's just one lpr file it's easier to immediately zip that up)
« Last Edit: July 29, 2014, 03:30:22 pm by BigChimp »
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Beginners OOP Question
« Reply #8 on: July 29, 2014, 03:25:27 pm »
This code works for me:
Code: [Select]
program assigntest;

uses Sysutils,classes;

procedure Filetest;
const
  FileName='results.txt';
var
  fResult: TEXT;

begin
  // If we do not create the file, append will give an error
  if not(FileExists(FileName)) then
  begin
    AssignFile( fResult, FileName );
    Rewrite(fResult);
    CloseFile(fResult);
  end;
  AssignFile( fResult, FileName );
  Append(fResult);
  WriteLn( fResult, 'bla' );
  CloseFile( fResult );
end;

begin
  FileTest;
end.
See also
http://wiki.lazarus.freepascal.org/File
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Beginners OOP Question
« Reply #9 on: July 29, 2014, 03:25:41 pm »
"Assign" was Niklaus Wirth's name for one of the original file procedures when he designed Pascal.
Unfortunately Borland used the same identifier for a commonly-used method of TPersistent, which copies all a component's data from one instance to another.
Consequently the file routines were renamed with "File" appended to them, to avoid the name clash.
The IDE knows all the identifiers in the FPC runtime library (RTL), whatever is (or is not) in your uses clause, such as AssignFile(), for instance.
However, LCL identifiers are known by the IDE only when the unit that declares them is specified in the uses clause. For this reason a default new project in Lazarus provides a uses clause with several common units specified.

You could try the following program which offers simple logging of mouse movement (don't move the mouse too much or for too long before clicking the Save button or you'll have a huge file). Start a new project in Lazarus and replace the unit1 code with the following, saving the unit as MainLogForm:

Code: [Select]
unit MainLogForm;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, StdCtrls;

type

  { TLogForm }

  TLogForm = class(TForm)
    procedure BSaveOnClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure MLoggerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  private
    BSave: TButton;
    FStart: TTimeStamp;
    MLogger: TMemo;
    procedure LogMouse(anX, aY: integer);
  end;

var
  LogForm: TLogForm;

implementation

{$R *.lfm}

{ TLogForm }

procedure TLogForm.BSaveOnClick(Sender: TObject);
begin
  MLogger.Lines.SaveToFile('log.txt');
end;

procedure TLogForm.FormCreate(Sender: TObject);
begin
  MLogger:=TMemo.Create(Self);
  MLogger.Align:=alLeft;
  MLogger.OnMouseMove:=@MLoggerMouseMove;
  MLogger.Clear;
  MLogger.Parent:=Self;

  BSave:=TButton.Create(Self);
  BSave.Top :=10;
  BSave.Left:=MLogger.Width + 10;
  BSave.Caption:='Save log';
  BSave.OnClick:=@BSaveOnClick;
  BSave.Parent:=Self;
  FStart:=DateTimeToTimeStamp(Now);
end;

procedure TLogForm.LogMouse(anX, aY: integer);

  function SecsFromStart:integer;
  begin
    Result:=(DateTimeToTimeStamp(Now).Time - FStart.Time) div 1000;
  end;

begin
  mLogger.Append(Format('Mouse at (%d,%d) after %d seconds',[anX, aY, SecsFromStart]));
end;

procedure TLogForm.MLoggerMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  LogMouse(X, Y);
end;

end.

MathMan

  • Sr. Member
  • ****
  • Posts: 325
Re: Beginners OOP Question
« Reply #10 on: July 29, 2014, 03:48:36 pm »
This code works for me:
Code: [Select]
program assigntest;

uses Sysutils,classes;

procedure Filetest;
const
  FileName='results.txt';
var
  fResult: TEXT;

begin
  // If we do not create the file, append will give an error
  if not(FileExists(FileName)) then
  begin
    AssignFile( fResult, FileName );
    Rewrite(fResult);
    CloseFile(fResult);
  end;
  AssignFile( fResult, FileName );
  Append(fResult);
  WriteLn( fResult, 'bla' );
  CloseFile( fResult );
end;

begin
  FileTest;
end.
See also
http://wiki.lazarus.freepascal.org/File

Yepp, that's working for me too! Many thanks!

I think I'll prefer the following (based on your comment that resolving can be done by prepending the unit Name). It is a pure personal thing - for me this way it's more obvious what is going on

Code: [Select]
procedure TLongCalc.MenuTestClick(Sender: TObject);

const
  fResultName='result.txt';

var
  fResult: TEXT;

begin
  if not( FileExists( fResultName ) ) then
  begin
    System.Assign( fResult, fResultName );
    System.Rewrite( fResult );
    System.Close( fResult );
  end;
  System.Assign( fResult, 'results.txt' );
  System.Append( fResult );

MathMan

  • Sr. Member
  • ****
  • Posts: 325
Re: Beginners OOP Question
« Reply #11 on: July 29, 2014, 03:53:54 pm »
"Assign" was Niklaus Wirth's name for one of the original file procedures when he designed Pascal.
Unfortunately Borland used the same identifier for a commonly-used method of TPersistent, which copies all a component's data from one instance to another.
Consequently the file routines were renamed with "File" appended to them, to avoid the name clash.
The IDE knows all the identifiers in the FPC runtime library (RTL), whatever is (or is not) in your uses clause, such as AssignFile(), for instance.
However, LCL identifiers are known by the IDE only when the unit that declares them is specified in the uses clause. For this reason a default new project in Lazarus provides a uses clause with several common units specified.

Many thanks for the above explanation! Now I know where I went wrong, how I should approach things in the future, learned a new feature of the IDE (with it's limitations) and on top got the explanation how the issue with Assign came to pass.

So again thanks to you and BigChimp for taking the time!

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11452
  • FPC developer.
Re: [SOLVED] Beginners OOP Question
« Reply #12 on: July 29, 2014, 11:32:26 pm »
I use

Code: [Select]
function appendfile(var datafile : Textfile;filename:string):boolean;
var b:boolean;
begin
  b:=fileexists(filename);
  AssignFile(DataFile, FileName);
  {$i-}
  if b then
    Append(DataFile)
  else
    rewrite(datafile);
  {$i+}
  result:=b;
end;

Note the $I-/$I+, this means that after using this function you can query ioresult to see if opening went well. Maybe we should add this somewhere.

Graeme

  • Hero Member
  • *****
  • Posts: 1428
    • Graeme on the web
Re: Beginners OOP Question
« Reply #13 on: July 30, 2014, 09:01:21 pm »
1 - CloseFile is only avail with LazLogger, correct?
 2 - The docs show no reference to AssignFile - so where is this coming from?
May I suggest you use a better help system. Download INF documentation of RTL, FCL, LCL and fpGUI using this link [http://sourceforge.net/projects/fpgui/files/fpGUI/Documentation/].

To view INF help files, use DocView. You can download a binary for it from here [http://sourceforge.net/projects/fpgui/files/fpGUI/1.0/].

To integrate DocView with Lazarus IDE, or any other IDE or programmers editor, take a look here [http://fpgui.sourceforge.net/docview_ide_integration.shtml]. There is no need to recompile Lazarus IDE for integration.

To see how DocView looks like, go here [http://fpgui.sourceforge.net/screenshots_apps.shtml]

DocView and INF files are very small, DocView itself is extremely fast, has advanced searching, search highlighting, inline annotation support, user defined bookmarks, can concatenate multiple INF help files at runtime etc.
--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

Graeme

  • Hero Member
  • *****
  • Posts: 1428
    • Graeme on the web
Re: [SOLVED] Beginners OOP Question
« Reply #14 on: July 30, 2014, 09:39:56 pm »
Note the $I-/$I+, this means that after using this function you can query ioresult to see if opening went well.

Good point!

Quote
Maybe we should add this somewhere.
A good place would be the documentation.  I just had a look, none of the FPC 2.6.2 documenation (PDF, HTML) lists much documentation for the 'objpas' unit. Yet looking at the FPC docs repository, there is more documentation. I guess these will appear in the official 2.6.4 docs when they get generated.

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

 

TinyPortal © 2005-2018