Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2011-11

using functions from units & main programme

15 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

John Lee

I have a normal fpc unit, call it jim, with 2 functions fna & fnb . fnb uses internally fna.

My main program, has a uses clause including jim, and also a _different_ version of fna, with same parameters as for that in jim, but no fnb.

The problem I get is that when, in main program fnb doesn't use the _new_ version in the main program of fna but still uses the version that is in the unit. I'd thought that versions of fns in the main program are used in place of those in the unit when they both have the same name, but maybe not when a function is used another function?

Never seen this before - is there a way I can force fnb to use the main program's version of fna, not the version that's in the unit?

TIA John

Sven Barth
to John Lee
John Lee wrote 14 lines
I have a normal fpc unit, call it jim, with 2 functions fna & fnb . fnb uses internally fna. My main program, has a uses clause including jim, and also a _different_ version of fna, with same parameters as for that in jim, but no fnb. The problem I get is that when, in main program fnb doesn't use the _new_ version in the main program of fna but still uses the version that is in the unit. I'd thought that versions of fns in the main program are used in place of those in the unit when they both have the same name, but maybe not when a function is used another function? Never seen this before - is there a way I can force fnb to use the main program's version of fna, not the version that's in the unit?

Without example code its hard do decide what the problem is.

Pausible causes:
* there are different parameters (maybe caused by a different $mode or some option), thus the compiler tries to call the best fitting function for the given parameters
* if the function in the program is declared below its point of calling then the function from "jim" will be used
* a bug in the compiler

Can you please state compiler version and platform (just so that the information is available)?

Regards,
Sven

Sven Barth
to John Lee: I have a normal fpc unit, call it jim, with 2 functions fna & fnb . fnb uses internally…
John Lee wrote 14 lines
I have a normal fpc unit, call it jim, with 2 functions fna & fnb . fnb uses internally fna. My main program, has a uses clause including jim, and also a _different_ version of fna, with same parameters as for that in jim, but no fnb. The problem I get is that when, in main program fnb doesn't use the _new_ version in the main program of fna but still uses the version that is in the unit. I'd thought that versions of fns in the main program are used in place of those in the unit when they both have the same name, but maybe not when a function is used another function? Never seen this before - is there a way I can force fnb to use the main program's version of fna, not the version that's in the unit?

Now I that I reread your mail I might get what is going on.

You expect "fnb" which is declared in "jim" to use the function "fna" declared in the main program? If so, then this isn't possible. The unit "jim" is already compiled, thus the call from "fnb" to "jim.fna" is fixed. Your only possibilty would be to use function/procedure variables and pass the function to call as a parameter to "fnb".

Regards,
Sven

John Lee
to Sven Barth

Sorry for confusion, my email wasn't clear...
old fpc version, that I have to use because of availability of various units...Free Pascal Compiler version 2.2.2 [2008/08/03] for i386

this is jim.pp---
unit jim;
interface
 function fna:string;
 function fnb:string;
implementation
function fna:string;
begin
 fna:='jim';
end;
function fnb:string;
begin
 fnb:=fna;
end;
end.
this is fred.pp---
uses jim;
function fna:string;
begin
 fna:='fred';
end;
begin
 writeln(fnb);
end.

This writeln gives jim, ie the version in jim - I'd like it to be fred & thought that it would! What can I do please, to _force_ fnb to use the fred version of fna?

John

Sven Barth wrote 35 lines
Am 18.11.2011 16:49, schrieb John Lee: > I have a normal fpc unit, call it jim, with 2 functions fna & fnb . fnb > > uses internally fna. > > My main program, has a uses clause including jim, and also a _different_ > version of fna, with same parameters as for that in jim, but no fnb. > > The problem I get is that when, in main program fnb doesn't use the > _new_ version in the main program of fna but still uses the version that > is in the unit. I'd thought that versions of fns in the main program are > used in place of those in the unit when they both have the same name, > but maybe not when a function is used another function? > > Never seen this before - is there a way I can force fnb to use the main > program's version of fna, not the version that's in the unit? > Now I that I reread your mail I might get what is going on. You expect "fnb" which is declared in "jim" to use the function "fna" declared in the main program? If so, then this isn't possible. The unit "jim" is already compiled, thus the call from "fnb" to "jim.fna" is fixed. Your only possibilty would be to use function/procedure variables and pass the function to call as a parameter to "fnb". Regards, Sven ______________________________**_________________ fpc-pascal maillist - http://lists.freepascal.org/**mailman/listinfo/fpc-pascal<http://lists.freepascal.org/mailman/listinfo/fpc-pascal>
Sven Barth
to John Lee
John Lee wrote 36 lines
Sorry for confusion, my email wasn't clear... old fpc version, that I have to use because of availability of various units...Free Pascal Compiler version 2.2.2 [2008/08/03] for i386 this is jim.pp--- unit jim; interface function fna:string; function fnb:string; implementation function fna:string; begin fna:='jim'; end; function fnb:string; begin fnb:=fna; end; end. this is fred.pp--- uses jim; function fna:string; begin fna:='fred'; end; begin writeln(fnb); end. This writeln gives jim, ie the version in jim - I'd like it to be fred & thought that it would! What can I do please, to _force_ fnb to use the fred version of fna?

As I said per se this is expected, because the "jnb" in "jim" only knows about the "jna" in "jim", but not about the "jna" in your main program.

Possible solution:

Extend your unit "jim" the following way (this is the "function variable" approach I mentioned):

=== unit jim begin ===

unit jim;
interface
type
   TStringFunc = function: String;
function fna: String;
function fnb(aFunc: TStringFunc = Nil): String;
implementation
function fna: String;
begin
   fna := 'jim';
end;
function fnb(aFunc: TStringFunc): String;
begin
   if Assigned(aFunc) then
     fnb := aFunc
   else
     fnb := fna;
end;
end.

=== unit jim end ===

And your main program will then look like this:

=== main program begin ===

uses jim;
function fna: String;
begin
   fna := 'fred';
end;
begin
   writeln(fnb(@fna)); // will print "fred"
   writeln(fnb); // will print "jim"
end.

=== main program end ===

For further information about procedure/function variables I refer you to the documentation:
http://www.freepascal.org/docs-html/ref/refse17.html#x45-520003.6

Of course you are free to ask further questions if you need help on this or another topic. ;)

Regards,
Sven

John Lee
to Sven Barth

Thanks for the fix, but it makes the code a bit more complicated than I'd hoped/thought based on my (over simple?) impression that local fns are used in place of those in units. John

Sven Barth wrote 113 lines
Am 18.11.2011 17:47, schrieb John Lee: Sorry for confusion, my email wasn't clear... > old fpc version, that I have to use because of availability of various > units...Free Pascal Compiler version 2.2.2 [2008/08/03] for i386 > > this is jim.pp--- > unit jim; > interface > function fna:string; > function fnb:string; > > implementation > function fna:string; > begin > fna:='jim'; > end; > function fnb:string; > begin > fnb:=fna; > end; > end. > > this is fred.pp--- > uses jim; > > function fna:string; > begin > fna:='fred'; > end; > > begin > writeln(fnb); > end. > > This writeln gives jim, ie the version in jim - I'd like it to be fred & > thought that it would! What can I do please, to _force_ fnb to use the > fred version of fna? > As I said per se this is expected, because the "jnb" in "jim" only knows about the "jna" in "jim", but not about the "jna" in your main program. Possible solution: Extend your unit "jim" the following way (this is the "function variable" approach I mentioned): === unit jim begin === unit jim; interface type TStringFunc = function: String; function fna: String; function fnb(aFunc: TStringFunc = Nil): String; implementation function fna: String; begin fna := 'jim'; end; function fnb(aFunc: TStringFunc): String; begin if Assigned(aFunc) then fnb := aFunc else fnb := fna; end; end. === unit jim end === And your main program will then look like this: === main program begin === uses jim; function fna: String; begin fna := 'fred'; end; begin writeln(fnb(@fna)); // will print "fred" writeln(fnb); // will print "jim" end. === main program end === For further information about procedure/function variables I refer you to the documentation: http://www.freepascal.org/**docs-html/ref/refse17.html# **x45-520003.6<http://www.freepascal.org/docs-html/ref/refse17.html#x45-520003.6> Of course you are free to ask further questions if you need help on this or another topic. ;) Regards, Sven ______________________________**_________________ fpc-pascal maillist - http://lists.freepascal.org/**mailman/listinfo/fpc-pascal<http://lists.freepascal.org/mailman/listinfo/fpc-pascal>
Bart
to John Lee: Sorry for confusion, my email wasn't clear... old fpc version, that I have to use because…
{file: jim.pas}
unit jim;
{$ifdef fpc}
  {$mode objfpc}{h+}
{$endif}
interface
function fna: string;
function fnb: string;
implementation
function fna: string;
begin
  fna := 'jim';
end;
function fnb: string;
begin
  fnb := fna;
end;
end.
{file: prog.pas}
Program Prog;
{$ifdef fpc}
  {$mode objfpc}{h+}
{$endif}
uses jim;
function fna: string;
begin
  fna := 'Prog';
end;
begin
  writeln('fna = ',fna);
  writeln('jim.fna = ,'jim.fna);
end.

Compiled with both TurboPascal 6.0 and fpc 2.4.4. the output in both cases is "Prog".
To get "Jim" in the main program file (prog.pas) I have to use jim.fna explicitely:

Turbo Pascal Version 6.0 Copyright (c) 1983,90 Borland International fna = Prog
jim.fna = jim

Free Pascal Compiler version 2.4.4 [2011/04/23] for i386 Copyright (c) 1993-2010 by Florian Klaempfl
Target OS: Win32 for i386
Compiling prog.pas
Linking prog.exe
16 lines compiled, 0.8 sec , 26912 bytes code, 1624 bytes data

F:\TP6>prog
fna = Prog
jim.fna = jim

Bart

Alberto Narduzzi
to John Lee: Thanks for the fix, but it makes the code a bit more complicated than I'd hoped/thought…
Thanks for the fix, but it makes the code a bit more complicated than I'd hoped/thought based on my (over simple?) impression that local fns are used in place of those in units. John

this would be true if you declared another function fnb locally, so that calling fnb could eventually override the one in the unit. As said, the unit itself doesn't (and cannot, btw) know anything about the program (or other units, for instance) that are using it.

Cheers, A.

Sven Barth
to Bart: {file: jim.pas} unit jim; {$ifdef fpc} {$mode objfpc}{h+} {$endif} interface function…
Bart wrote 22 lines
{file: prog.pas} Program Prog; {$ifdef fpc} {$mode objfpc}{h+} {$endif} uses jim; function fna: string; begin fna := 'Prog'; end; begin writeln('fna = ',fna); writeln('jim.fna = ,'jim.fna); end. Compiled with both TurboPascal 6.0 and fpc 2.4.4. the output in both cases is "Prog". To get "Jim" in the main program file (prog.pas) I have to use jim.fna explicitely:

But he wants to call "fnb" in the main program and have that call "fna" of the main program instead of "fna" from "jim".

Regards,
Sven

Bernd
to John Lee: I have a normal fpc unit, call it jim, with 2 functions fna & fnb . fnb uses internally…

2011/11/18 John Lee :

Never seen this before - is there a way I can force fnb to use the main program's version of fna, not the version that's in the unit? TIA John

Your problem sounds very much like you would really want to make use of objects, inheritance and virtual methods. Instead of passing procedure variables to modify or specialize the behavior of Jim.fnb you would make Jim a class with virtual methods:

You could have a class TJim (declared in the unit jim) with two methods fna and fnb and you would declare fna as a virtual method (so it can later be overridden). In your main program you would declare a class TFred derived from TJim and override fna. Then when you make an instance of TFred and call Fred.fnb the code of fnb would automatically use the fna method of TFred.

Bernd

John Lee
to Bart

Thanks for the feedback & suggestions - looks like either functions as parameters or using objects are only ways to do this - either makes the code look horrible & more complex that necessary imo cf the normal use of functions. Surprised this capability hasn't come up before because doesn't sound technically difficult to do.
John

Bart wrote 13 lines
On 11/18/11, Sven Barth wrote: > But he wants to call "fnb" in the main program and have that call "fna" > of the main program instead of "fna" from "jim". You're right. I misread the original post. Bart _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Rich Saunders
to John Lee
John Lee wrote
Surprised this capability hasn't come up before because doesn't sound technically difficult to do.

The need for this capability HAS come up before. That's why the methods that are available are available. They may appear to be "too complicated" but it is a complicated situation.

Bernd
to John Lee: Thanks for the feedback & suggestions - looks like either functions as parameters or…

2011/11/19 John Lee :

Surprised this capability hasn't come up before because doesn't sound technically difficult to do.

The problem is simply that at the time of compiling the unit all the function calls within it are already statically resolved and everything is cast in concrete. Pascal is a static language. It does NOT try to resolve each and every function call at runtime by looking up their names to see which one matches under the current circumstances like some highly dynamic languages do (at the cost of speed), instead each function call is completely resolved at compile time.

Of course sometimes (quite often) the need arises to replace certain function calls within a library or a framework at a later time (decide at runtime which function to call), this is known as late binding, for this there is no other way than to either simply use a callback function (a procedure variable (as the name implies: the procedure is variable, not constant), this is the pragmatic simple C like approach best suited for simple things) or do the same with inheritance and overriding virtual methods (this is basically just another way of solving the exact same problem: specializing the behavior of some generic library code).

Bernd