top | item 33680180

(no title)

fm77 | 3 years ago

> 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)

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).

discuss

order

int_19h|3 years ago

Function pointer types are a Turbo Pascal extension; in standard (Wirth/ISO) Pascal, you cannot have "type = function" etc, you can only use that syntax to declare arguments of function type. So they're not first-class values. They're closures because they capture the enclosing environment (variables).

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.