Lazarus

Programming => General => Topic started by: Paolo on November 27, 2022, 01:41:11 pm

Title: duplicate identifier
Post by: Paolo on November 27, 2022, 01:41:11 pm
Hello (win 10, laz 2.2.2/fpc 3.2.2)

if I write this
Code: Pascal  [Select][+][-]
  1. procedure Test1;
  2. begin
  3.   beep;
  4. end;
  5.  
  6. procedure Test2;
  7.   procedure Test1;
  8.   begin
  9.     beep;
  10.   end;
  11. begin
  12.   Test1;
  13.   beep;
  14. end;
  15.  
  16.  

all is fine, and nested Test1 is called in Test2 execution

but if I write this, where procedures are part of Form1

Code: Pascal  [Select][+][-]
  1.  
  2. procedure TForm1.Test1;
  3. begin
  4.   beep;
  5. end;
  6.  
  7. procedure TForm1.Test2;
  8.   procedure Test1;
  9.   begin
  10.     beep;
  11.   end;
  12. begin
  13.   beep;
  14. end;
  15.  

the compiler says : Duplicate identifier "test1".

That is right ?
Title: Re: duplicate identifier
Post by: Thaddy on November 27, 2022, 01:51:55 pm
Yes
Title: Re: duplicate identifier
Post by: Paolo on November 27, 2022, 02:02:42 pm
thanks Thaddy,

so Test1 in the second case does not overwrite the first Test1 declaration ?
why is not working as in case of simple procedure declaration ?

thans again.
Title: Re: duplicate identifier
Post by: wp on November 27, 2022, 02:06:46 pm
Not sure here, but usually {$MODE Delphi} is less strict than FPC regarding duplicate identifiers.
Title: Re: duplicate identifier
Post by: 440bx on November 27, 2022, 02:10:22 pm
That is right ?
That doesn't look right.  In the second case, Test1 is nested in Test2 just as it is in the first case.

Looks like a bug to me but, it will be nice to have one of the developers confirm that.
Title: Re: duplicate identifier
Post by: ASerge on November 27, 2022, 02:26:04 pm
Looks like a bug to me but, it will be nice to have one of the developers confirm that.
I also think it's a bug. Why is this allowed only in {$MODE DELPHI} mode, but not in {$MODE OBJFPC} mode.
Title: Re: duplicate identifier
Post by: Paolo on November 27, 2022, 02:44:15 pm
Quote
I also think it's a bug.

me too.

at the end the compiler should not be confused on which Test1 I am using and allows code like

Quote

procedure TForm1.Test1;
begin
  beep;
end;
 
procedure TForm1.Test2;
  procedure Test1;   
  begin
    beep;
  end;
begin
  Test1;        //the neseted one
  Self.Test1;  //the fom1.Test1
end;
 
Title: Re: duplicate identifier
Post by: marcov on November 27, 2022, 03:05:02 pm
It's  deliberate. The idea was that it would avoid accidental mistakes, at the cost of a small limitation. But it wasn't applied to Delphi because of compatibility.
Title: Re: duplicate identifier
Post by: Curt Carpenter on November 27, 2022, 08:11:14 pm
For consistency, wouldn't a warning make more sense?  But that said, I can sure see how having multiple procedures with the same name might cause pain for someone trying to maintain a program.
Title: Re: duplicate identifier
Post by: avk on November 27, 2022, 08:31:11 pm
That is right ?
That doesn't look right.  In the second case, Test1 is nested in Test2 just as it is in the first case.

Looks like a bug to me but, it will be nice to have one of the developers confirm that.

Maybe the directive {$modeswitch duplicatelocals} can help somehow?
Title: Re: duplicate identifier
Post by: 440bx on November 27, 2022, 09:26:37 pm
Maybe the directive {$modeswitch duplicatelocals} can help somehow?
I cannot help feeling uneasy about "artifices" to create exceptions to languages rules.   

I think there should not be exceptions to the scoping rules.  Their presence opens the door to inconsistencies and confusing situations (e,g. why does it accept "this or that" in "this case" and  not in "that case" when the two cases are essentially identical ?)
Title: Re: duplicate identifier
Post by: PascalDragon on November 27, 2022, 09:31:14 pm
For consistency, wouldn't a warning make more sense?  But that said, I can sure see how having multiple procedures with the same name might cause pain for someone trying to maintain a program.

People like to ignore warnings even if they're useful ones. Errors can't be ignored however.

Maybe the directive {$modeswitch duplicatelocals} can help somehow?

Yes, that modeswitch controls that and is enabled by default in mode Delphi.

Maybe the directive {$modeswitch duplicatelocals} can help somehow?
I cannot help feeling uneasy about "artifices" to create exceptions to languages rules.   

I think there should not be exceptions to the scoping rules.  Their presence opens the door to inconsistencies and confusing situations (e,g. why does it accept "this or that" in "this case" and  not in "that case" when the two cases are essentially identical ?)

This error has already saved me from potential issues and it arises more likely with object oriented programming.

This functionality is not a bug and it won't be changed.
Title: Re: duplicate identifier
Post by: 440bx on November 27, 2022, 09:38:13 pm
This functionality is not a bug and it won't be changed.
Since from what you're saying it's by design then it may not be a bug but, bug or not, it is an inconsistency in the language's scoping rules.  Inconsistencies are not desirable.
Title: Re: duplicate identifier
Post by: Paolo on November 27, 2022, 09:42:35 pm
I agree with 440bx. Anyway if it is by design, in my view, also the first code fragment should rise the same warning/error.
Title: Re: duplicate identifier
Post by: PascalDragon on November 27, 2022, 09:48:09 pm
I agree with 440bx. Anyway if it is by design, in my view, also the first code fragment should rise the same warning/error.

No, because that would raise issues with backwards compatibility. Object Pascal support was added later to FPC (with the transition from version 1.x to 2.x) and the restriction for the identifier names was added from the get go there, but it couldn't be added for global scope without potentially breaking exisiting code.
Title: Re: duplicate identifier
Post by: ASerge on November 27, 2022, 11:15:42 pm
Maybe the directive {$modeswitch duplicatelocals} can help somehow?
Yes, that modeswitch controls that and is enabled by default in mode Delphi.
But in {$MODE OBJFPC} the error appears, regardless of {$MODESWITCH DUPLICATELOCALS}:
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2. {$MODESWITCH DUPLICATELOCALS}
  3.  
  4. type
  5.   TSome = class
  6.     procedure Proc1;
  7.     procedure Proc2;
  8.   end;
  9.  
  10. procedure TSome.Proc1;
  11. begin
  12. end;
  13.  
  14. procedure TSome.Proc2;
  15.  
  16.   procedure Proc1;
  17.   begin
  18.   end;
  19.  
  20. begin
  21. end;
  22.  
  23. begin
  24. end.
Code: Text  [Select][+][-]
  1. project1.lpr(16,13) Error: Duplicate identifier "Proc1"
  2. project1.lpr(16,18) Hint: Identifier already defined in unit PROGRAM: project1.lpr at line 6
Title: Re: duplicate identifier
Post by: 440bx on November 28, 2022, 12:11:42 am
But in {$MODE OBJFPC} the error appears, regardless of {$MODESWITCH DUPLICATELOCALS}:

Inconsistencies are consistently "deficient" ideas.  In the following code:
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2.  
  3. {$MODESWITCH DUPLICATELOCALS}
  4. {$MODESWITCH ADVANCEDRECORDS}
  5.  
  6. program DuplicateIdentifier;
  7.  
  8. type
  9.   TSome = record
  10.     FieldA    : integer;
  11.     FieldB    : integer;
  12.  
  13.  
  14.     procedure Proc1;
  15.     procedure Proc2;
  16.     procedure Proc4;
  17.   end;
  18.  
  19. procedure TSome.Proc1;
  20. begin
  21. end;
  22.  
  23. procedure TSome.Proc2;
  24.  
  25.   (*
  26.   procedure Proc1;   { Proc1 is NOT ok here }
  27.   begin
  28.   end;
  29.   *)
  30.  
  31.   (*
  32.   procedure Proc2;   { Proc2 is NOT ok here }
  33.   begin
  34.   end;
  35.   *)
  36.  
  37.   procedure Proc3;
  38.  
  39.     { but all the duplicates you can eat here, bon appetit }
  40.  
  41.     procedure Proc1;   { Proc1 is ok here   }
  42.     begin
  43.     end;
  44.  
  45.     procedure Proc2;   { and so is Proc2    }
  46.     begin
  47.     end;
  48.  
  49.     procedure Proc3;
  50.  
  51.       procedure Proc3;
  52.  
  53.         procedure Proc4;  { have another Proc4 for dessert }
  54.  
  55.           procedure FieldA();
  56.           begin
  57.           end;
  58.  
  59.         begin
  60.         end;
  61.  
  62.       begin
  63.         Proc4(); { which Proc4 gets called ? }
  64.       end;
  65.  
  66.     begin
  67.       Proc4(); { which Proc4 gets called - not the same one as above! }
  68.     end;
  69.  
  70.   begin
  71.     Proc4(); { which Proc4 gets called ? }
  72.   end;
  73.  
  74. begin
  75. end;
  76.  
  77.  
  78.  
  79. procedure TSome.Proc4;
  80. begin
  81. end;
  82.  
  83.  
  84. begin
  85. end.                              

if Proc1 and Proc2 are nested in TSome.Proc2 then the compiler is unhappy and emits an error BUT, if Proc1 and Proc2 are nested in Proc3, suddenly there is no more duplicate identifier, IOW, identifier "Proc1" is different than identifier "Proc1" and the same for "Proc2".

But, there can be a "Proc3" inside a "Proc3" inside another "Proc3" without any complaints about duplicate identifiers.   If that isn't enough, since an error is emitted when a "duplicate identifier" is found, that really puts in doubt which Proc4 is invoked by the various Proc3(s)

No wonder they say the road to hell is paved with good identifiers ... uh... I mean good intentions.  ;)

It's much easier to figure things out when rules have no exceptions.   If the compiler is going to complain about "duplicate identifier"s then it should NOT allow any function/procedure/method to be named the same as another one in the entire hierarchy thus making it consistent.  IOW, all names unique in the entire scope.

Alternatively, if it wants to complain about "duplicate identifiers" then it should at least issue a warning for all duplicates it is willing to tolerate and an error for those it is not.  At least a semblance of consistency.


Title: Re: duplicate identifier
Post by: Curt Carpenter on November 28, 2022, 12:26:47 am
It's a fairly esoteric problem in any event isn't it?  Although I agree that the introduction of an exception to scoping rules is unfortunate.

The question for computational linguists, I suppose, is whether any sufficiently rich language can ever be entirely free of such issues.   There will certainly always be trade-offs to be made in the design of such a language, and no provably optimal way to make them, given the diversity of interests and priorities that come into play.   

Meanwhile:  if protecting programmers from themselves was a leading principle -- would "C" ever have made it out of the laboratory?   
TinyPortal © 2005-2018