Lazarus

Programming => General => Topic started by: Nitorami on August 01, 2020, 09:50:46 am

Title: Overloaded function not working in objfpc ?
Post by: Nitorami on August 01, 2020, 09:50:46 am
What is going on here ? Instead of zero I get a random result. The first version of testme is never called.  The compiler seems to interpret testme as a variable rather than a function call !?!

It works in mode delphi which forces me to declare both versions as overloaded. But not in objfpc. FPC 3.2.0, win32, no optimisations.

Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2.  
  3. function testme: dword;
  4. begin
  5.   writeln ('Version 1 called');
  6.   result := 0;
  7. end;
  8.  
  9. function testme (range: dword): dword; overload;
  10. begin
  11.   writeln ('Version 2 called');
  12.   result := testme mod range;
  13. end;
  14.  
  15. begin
  16.  writeln (testme (1000));  //prints some random number
  17. end.
  18.  
Title: Re: Overloaded function not working in objfpc ?
Post by: process_1 on August 01, 2020, 09:52:32 am
You have to place overload to both functions:

Code: Pascal  [Select][+][-]
  1. function testme: dword; overload;
  2. function testme (range: dword): dword; overload;
  3.  
Title: Re: Overloaded function not working in objfpc ?
Post by: TRon on August 01, 2020, 09:58:36 am
The compiler seems to interpret testme as a variable rather than a function call !?!
That is because it does. It is the function name and thus the result value.

Code: Pascal  [Select][+][-]
  1. result := testme() mod range;
  2.  
Should actually invoke the function for you.
Title: Re: Overloaded function not working in objfpc ?
Post by: process_1 on August 01, 2020, 10:00:49 am
BTW, in this case better use default parameter values, as this :

Code: Pascal  [Select][+][-]
  1. function testme (range: dword=0): dword;
  2.  

And then adopt function itself. Then no need for overloaded functions.
Title: Re: Overloaded function not working in objfpc ?
Post by: Thaddy on August 01, 2020, 10:10:26 am
Your code works as expected here on my Raspbians (both 32 and the experimental AARCH64)
Title: Re: Overloaded function not working in objfpc ?
Post by: Nitorami on August 01, 2020, 10:16:20 am
Thanks for the quick responses.

@process_1:
- declaring both as overload does not help in mode objfpc.
- the code is just a sample I made to demonetrate the effect. In the full code, I cannot use a default parameter.

@TRon:
Understood. "testme" is also the function result as it used to be in Turbo Pascal days. It does work as intented when using the brackets testme(). But that is nasty and a source of error, as Pascal does not normally enforce the explicit use of empty brackets....

@Thaddy: Alright, bot not on windows. The compiler interprets the function name as result, rather than the previously declared function.
Title: Re: Overloaded function not working in objfpc ?
Post by: TRon on August 01, 2020, 10:17:18 am
Hint 1:
Code: [Select]
fpc -V3.2.0 -B "callingout.pas" (in directory: /home/tron/projects/assorted)
Free Pascal Compiler version 3.2.0 [2020/06/08] for arm
Copyright (c) 1993-2020 by Florian Klaempfl and others
Target OS: Linux for ARMHF
Compiling callingout.pas
callingout.pas(14,20) Warning: Function result variable does not seem to be initialized
Linking callingout
19 lines compiled, 0.6 sec
1 warning(s) issued
Compilation finished successfully.

Hint 2:
Code: [Select]
./callingout
Version 2 called
680

fixed:
Code: [Select]
fpc -V3.2.0 -B "callingout.pas" (in directory: /home/tron/projects/assorted)
Free Pascal Compiler version 3.2.0 [2020/06/08] for arm
Copyright (c) 1993-2020 by Florian Klaempfl and others
Target OS: Linux for ARMHF
Compiling callingout.pas
Linking callingout
19 lines compiled, 0.5 sec
Compilation finished successfully.

Code: [Select]
./callingout
Version 2 called
Version 1 called
0

edit:
Code: [Select]
$ uname -a
Linux raspberrypi 4.19.66-v7+ #1253 SMP Thu Aug 15 11:49:46 BST 2019 armv7l GNU/Linux

Code: [Select]
$ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
NAME="Raspbian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
VERSION_CODENAME=stretch
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"

Code: [Select]
$ cat /proc/device-tree/model
Raspberry Pi 3 Model B Plus Rev 1.3
Title: Re: Overloaded function not working in objfpc ?
Post by: TRon on August 01, 2020, 10:21:18 am
@TRon:
Understood. "testme" is also the function result as it used to be in Turbo Pascal days. It does work as intented when using the brackets testme(). But that is nasty and a source of error, as Pascal does not normally enforce the explicit use of empty brackets....
It is actually pretty normal for FPC. But as usual, i'm unable to locate the right page of documentation so quickly  :-[

edit: I was finally able to find it mentioned in the documentation ... https://www.freepascal.org/docs-html/current/ref/refse81.html#x143-16500012.2
Quote
Sometimes, the call is desired, for instance in recursion in that case, the call must be forced. This can be done by adding the parenthesis to the function name:

Not sure if it is explained in more detail somewhere else (I seem to remember it does, no idea where though).
Title: Re: Overloaded function not working in objfpc ?
Post by: PascalDragon on August 01, 2020, 10:33:17 am
@TRon:
Understood. "testme" is also the function result as it used to be in Turbo Pascal days. It does work as intented when using the brackets testme(). But that is nasty and a source of error, as Pascal does not normally enforce the explicit use of empty brackets....

This is one of the point where FPC's original heritage of TP shows (instead of being solely based on Delphi). Overloading was only added with Delphi and thus to “merge” the two concept of result names and overloads for FPC it was decided to go this way, so that one can keep using the named result variable even if overloads are in play. And in 99% of the cases this isn't a problem.

@Thaddy: Alright, bot not on windows. The compiler interprets the function name as result, rather than the previously declared function.

As this behavior is not platform specific I assume that Thaddy did something incorrectly...
Title: Re: Overloaded function not working in objfpc ?
Post by: process_1 on August 01, 2020, 10:49:05 am
Try to set your test in delphi mode and you will see the difference and what TRon pointed.

Notice overload keyword is mandatory in delphi mode, in objfpc is ignored and assumed by default.

Calling function in delphi mode without brackets is allowed, in objfpc is completely different.
Title: Re: Overloaded function not working in objfpc ?
Post by: PascalDragon on August 01, 2020, 10:54:55 am
Calling function in delphi mode without brackets is allowed, in objfpc is completely different.

You can also in general call functions in non-Delphi modes without brackets.

There are only two cases where brackets are required:
1. If you have a function A then its result variable is also named A (in addition to Result in modes ObjFPC and Delphi). You can assign to this variable and you can also read from it. Now if you are inside function A and there is a variant of A that has no arguments (it can be the same function or an overload) then there are two possibilites that can be done if A is inside an expression: read the variable or call the function. Delphi calls the function, but FPC reads the variable, except if you use round brackets and thus mark it as a call.

2. If you have a procedure variable it is used to decide whether you read the value of the procedure variable or you call the procedure variable (especially important if the procedure variable is for a function).
Title: Re: Overloaded function not working in objfpc ?
Post by: Nitorami on August 01, 2020, 11:22:19 am
Using the function name as result variable was maybe one of Borland's poorer design decisions. Or does that go back to Wirth ?

I remember in TP days how I was always annoyed having to re-type the function name in the function body; why ? Whenever you changed a function name you had to repeat this in the function body.
But well, that was the way to go and I was not aware of anything better until I found in FPC this can be done by result variable, or the exit procedure. This seems to clear and obvious that it makes me wonder how and why it was designed differently in the first place.
Title: Re: Overloaded function not working in objfpc ?
Post by: Thaddy on August 01, 2020, 11:24:07 am
As this behavior is not platform specific I assume that Thaddy did something incorrectly...
Nope:
Code: Pascal  [Select][+][-]
  1. program untitled;
  2. {$mode objfpc}
  3.  
  4. function testme: dword;
  5. begin
  6.   writeln ('Version 1 called');
  7.   result := 0;
  8. end;
  9.  
  10. function testme (range: dword): dword;overload;
  11. begin
  12.   writeln ('Version 2 called');
  13.   result := testme mod range;
  14. end;
  15.  
  16. begin
  17.  writeln (testme (1000));  //prints some random number
  18. end.
Outputs:
Code: Bash  [Select][+][-]
  1. Version 2 called
  2. 0
  3.  
on Raspbian and on both architectures (armhf and aarch). I rest my plea..

(If you do not have a Raspberry Pi I can give you one (RPi3) for free)
Title: Re: Overloaded function not working in objfpc ?
Post by: process_1 on August 01, 2020, 11:37:07 am
Using the function name as result variable was maybe one of Borland's poorer design decisions. Or does that go back to Wirth ?

I believe it is Wirth's decision, Borland introduced Result for functions. But not 100% certain in both.

When I started to convert my projects from Delphi to Lazarus there was no converter. In every source file I placed {$mode delphi}. Nowadays, when start new project in Lazarus I do not do that, as I'm aware of the differences between modes.

Also FPC support some C/C++ programming styles by default, as work with C/C++ operators, which is done to make things easier for compilation/optimization and/or code simplicity, but anyway, who would like to stick with puritane delphi syntax - always can.
Title: Re: Overloaded function not working in objfpc ?
Post by: Nitorami on August 01, 2020, 11:57:40 am
I myself started learning FPC in mode obj_fpc and got used to it, so use it by default. Coming from TP, objfpc was the obvious choice.
The issue here was an unpleasant surprise which makes me think about changing to Delphi mode. On the other hand, Delphi has made a few very unfortunate design decisions as well. The dumbest idea in my view was to sacrifice the + operator to concat arrays.... a completely unncessary feature, and makes mathematical operators on arrays unusable. It is disabled by default in objfpc, and I appreciate that.

@Thaddy: That is the same behaviour as on win32. Your result is zero but this may still be randomly; the gist is that Version 1 of testme, which would force the result to zero, is never called.
Title: Re: Overloaded function not working in objfpc ?
Post by: process_1 on August 01, 2020, 12:10:33 pm
Actually, I do not think using Delphi mode is great loss. It is just about syntax. The most obvious difference is when declare dynamical lib calls declaring pointers to functions from it.

BTW, using function name is Wirth's decision, I have found his old document from 1971:

https://oberoncore.ru/_media/library/wirth_the_programming_language_pascal.pdf
Title: Re: Overloaded function not working in objfpc ?
Post by: Thaddy on August 01, 2020, 12:24:19 pm
mea culpa: my test does not print version1 which it should too It should print both lines.
Title: Re: Overloaded function not working in objfpc ?
Post by: PascalDragon on August 01, 2020, 05:39:28 pm
mea culpa: my test does not print version1 which it should too It should print both lines.

It will not in mode ObjFPC. That's independant of the platform and by design.
Title: Re: Overloaded function not working in objfpc ?
Post by: MarkMLl on August 01, 2020, 06:34:56 pm
BTW, using function name is Wirth's decision, I have found his old document from 1971:

https://oberoncore.ru/_media/library/wirth_the_programming_language_pascal.pdf

That document is of historical interest, but cannot be considered useful comment on the language "as she is spoke". For example:

"In order to eliminate side-effects, assignments to non-local variables are not allowed to occur within the function."

Watch out for another early version of that document which allows /* */ as digraphs for { }.

MarkMLl
Title: Re: Overloaded function not working in objfpc ?
Post by: process_1 on August 01, 2020, 10:12:47 pm
That document is of historical interest, but cannot be considered useful comment on the language "as she is spoke".

Well, don't forget these are pioneer days. As well now seems funny to have A,B,C,D... languages, is it? But in these days...

As well, one man hardly could find better solution, as fortran like RETURN [whatewer] statement is not in the language spirit at all...
Title: Re: Overloaded function not working in objfpc ?
Post by: VTwin on August 01, 2020, 11:46:51 pm
BTW, using function name is Wirth's decision, I have found his old document from 1971:

https://oberoncore.ru/_media/library/wirth_the_programming_language_pascal.pdf

I like his statement "In view of its intended usage both as a convenient basis to teach programming and as an efficient tool to write large programs...". Pascal is often dismissed as a "teaching" language, as if that is a bad thing.
TinyPortal © 2005-2018