Skip to content

Anonymous functions - Errors with scoped variables - (local and global variables).

Edit:
I tried it intensively, also with some modifications. Seems to be completely solved. Thank you!!

=========================================================================================

Edit:
I updated to:

Verbose: Free Pascal Compiler version 3.3.1-12784-gb9aeeaa6e3 [2023/06/21] for x86_64

The problems vanish with {$mode delphi}, but persist with {$mode objfpc}.

This Issue replaces #40315 (closed). I describe the remaining problems in better detail here.
So #40315 (closed) is closed now.

I get various errors with the same source. The errors change when I change variable declarations.
All these declarations, which do not compile, are syntactic correct.

Example:

The following source is exactly equal, only difference: I removed the (unused) local variable "str".
This results in compile error:

project2.lpr(41,25) Error: Overloaded identifier "__FPCINTERNAL__ANONYMOUS_2" isn't a function
program project2;
// This program compiles and runs in Delphi and in FPC. (at least should run in FPC)
// It is intentionally designed this way.
{$ifdef FPC}
{$mode objfpc}{$H+}
{$modeswitch functionreferences}
{$modeswitch anonymousfunctions}
  // {$warn 5036 off}// "Warning: (5036) Local variable "$Capturer" does not seem to be initialized"
{$endif}
// uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
  // Classes, Sysutils { you can add units after this };

type
  T_X = String; // Type of Test-variable X
  TfuncS = reference to function: T_X;
  TfuncF = reference to function(s: T_X): TfuncS;

var f_inner: TfuncS;
  f_outer: TfuncF;
//------------------------------------------------------------------------------
procedure caller;
begin
  f_inner();
end;
//------------------------------------------------------------------------------
procedure main;

var X: T_X;
   // str:String;
    f_outer: TfuncF;

begin

  X := '1234';

  f_outer := function(s: T_X): TfuncS // This captures local and persistent copy of "X"
  begin
      Result := function: T_X
      begin
          Writeln(s);
          Result := s;
      end;
      Writeln('Outer function was called');
  end;
  f_inner := f_outer(X); // This instantiates the outer function and f_inner and captures their local context.

  X := '0'; // Erase the T_X content

  Writeln('now calling f_inner');
  caller(); // This line prints the T_X s=1234, which was captured by the outer function.
               // f_inner will be called from an external context, this is just for test and demonstration
end;
//------------------------------------------------------------------------------
begin
  main;
  Writeln('Now the context of "main()" is lost. Can we still print the variable "X"?');
  if f_inner() = '1234' then
    Writeln('Yes! :-)')
  else
    Writeln('No! :-(');

  readln;

end.

New Example:

This source is equal again, I removed only the local variable "f_outer" and it should now use the global variable with same name instead.
This gives the same compile error.
Strangely, if I then also remove the unused local variable "str", it compiles and runs.

program project2;
// This program compiles and runs in Delphi and in FPC. (at least should run in FPC)
// It is intentionally designed this way.
{$ifdef FPC}
{$mode objfpc}{$H+}
{$modeswitch functionreferences}
{$modeswitch anonymousfunctions}
  // {$warn 5036 off}// "Warning: (5036) Local variable "$Capturer" does not seem to be initialized"
{$endif}
// uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
  // Classes, Sysutils { you can add units after this };

type
  T_X = String; // Type of Test-variable X
  TfuncS = reference to function: T_X;
  TfuncF = reference to function(s: T_X): TfuncS;

var f_inner: TfuncS;
    f_outer: TfuncF;
//------------------------------------------------------------------------------
procedure caller;
begin
  f_inner();
end;
//------------------------------------------------------------------------------
procedure main;

var X: T_X;
      str:String;
   // f_outer: TfuncF;

begin

  X := '1234';

  f_outer := function(s: T_X): TfuncS // This captures local and persistent copy of "X"
  begin
      Result := function: T_X
      begin
          Writeln(s);
          Result := s;
      end;
      Writeln('Outer function was called');
  end;
  f_inner := f_outer(X); // This instantiates the outer function and f_inner and captures their local context.

  X := '0'; // Erase the T_X content

  Writeln('now calling f_inner');
  caller(); // This line prints the T_X s=1234, which was captured by the outer function.
               // f_inner will be called from an external context, this is just for test and demonstration
end;

//------------------------------------------------------------------------------
begin
  main;
  Writeln('Now the context of "main()" is lost. Can we still print the variable "X"?');
  if f_inner() = '1234' then
    Writeln('Yes! :-)')
  else
    Writeln('No! :-(');

  readln;

end.
Edited by Peter Heckert
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information