Interesting - being an absolute non-expert in closures - but isn't it the other way around? That is, in Pascal, functions are first-class values but not closures?
Unless I am miss something here, but functions can be assigned to variables:
function add(a,b:integer):integer; { far; in Turbo Pascal }
begin
add := a + b;
end;
type MyFunc = function (a,b:integer):integer;
var f:MyFunc;
x:integer;
begin
f := add; { here we assigning a function to a variable }
x := f(3,4);
end;
> Some dialects - notably, Turbo Pascal - don't allow pointers to local functions at all.I know what you mean here, but that's not entirely true. In Turbo Pascal you had two ways to receive a pointer to a function:
1.) the way just shown, and here you are right, Turbo Pascal doesn't allow local functions, but that’s because how local functions in Turbo Pascal were implemented. Local functions have a hidden parameter (a 16-bit pointer to the caller's stackframe) pushed onto the stack, how do you handle this hidden parameter when you deal with a function pointer with a defined function signature? To avoid headaches I guess Hejlsberg simply choose to not allow local functions here.
2.) via a regular pointer - you simply store the function address in a pointer variable (or pass the function address to a pointer parameter), so:
procedure MyProc;
{ a local function }
function sub(a,b:integer):integer; { far; in TP }
begin
sub := a - b;
end;
type MyFuncHidden = function (a,b:integer; hidden:word):integer;
var p:pointer;
x:integer;
begin
p := @sub; { assigning a local function to a variable }
x := MyFuncHidden(p)(7,8,0);
end;
The problem here, now you as a programmer are in charge of handling the parameter passing.Look at the implementation of ForEach/FirstThat in the Turbo Vision library. Both ForEach and FirstThat accept local functions as parameter (and only local functions).
In your second example, what you're doing is the equivalent of reinterpret_cast between two incompatible pointer types (if they were compatible, you could have just assigned @sub to a variable of type MyFuncHidden). You cannot safely assume that your new signature faithfully corresponds to what the compiler does under the hood - that's an implementation detail. Furthermore, in this case, your function doesn't even try to access variables from the outer scope, and this would break if it did.
In standard Pascal, functions are closures but not first-class values (can be passed as arguments to other functions, but cannot be returned or assigned to variables); a typical implementation would implement a function pointer as a tuple of function address and pointer to stack frame. Some dialects - notably, Turbo Pascal - don't allow pointers to local functions at all.