Anonymous procedures (Was: Re: [fpc-devel] for-in-index loop)

Sven Barth pascaldragon at googlemail.com
Sat Jan 26 10:31:25 CET 2013


On 25.01.2013 23:57, Alexander Klenin wrote:
> On Sat, Jan 26, 2013 at 5:17 AM, Sven Barth <pascaldragon at googlemail.com> wrote:
>> One could also do an alternative (though currently not with arrays, but with
>> type helper support even that would be possible...):
>
> Yes, this is certainly the most interesting alternative. Actually,
> anonymous procedures/closures
> is the "real" task I wanted Vasily to perform, after the "warm-up" of
> for-in-index.

Just in case: we already have a branch where someone started the 
development for anonymous functions some months ago. You can find it here:

http://svn.freepascal.org/cgi-bin/viewvc.cgi/branches/blaise/closures/

Please Note: the branch currently won't compile as the unit "pnameless" 
is missing. I've asked the author whether he wants to continue his work 
or if he could at least leave the branch in a compiling state. I'm still 
waiting for an answer (he confirmed me though that he got my mail and 
that he'll answer me when he finds the time).

> You have also proposed lambda-expressions:
>> map.Iterate(lambda TFPGMapLongInt.TIteratorProc(aKey, aData) as Writeln(aKey, ' => ', aData.ClassName));
>
> I think that they are not optimal in the proposed form.
> Note that the longest part of the expression is actually a restatement
> of the Iterate parameter type.
> I propose to allow omitting that:
>
> map.Iterate(lambda begin
>    Writeln(aKey, ' => ', aData.ClassName);
> end;)
>
> That is, basically, "lambda" means "use procedure definition from the
> parameter type".

I have already thought about this as well, but this is simply not how 
Pascal (and especially the compiler) works. In Pascal the result of an 
expression is (at first) independantly of the result it is assigned to. 
For example:

double1 := 1.0/2.0;

here the expression on the right side will be evaluated with the 
smallest possible precision that does not cause data loss (let's assume 
for now that 1.0, 2.0 and 0.5 all can be represented by a Single) and 
only in the assignment the result is converted to a Double.

Also there's the problem of overloaded procedures. Let's assume we have

type
   TProc1 = reference of procedure(aArg: Integer);
   TProc2 = reference of procedure(aArg: String);

procedure SomeProc(aArg: TProc1);
procedure SomeProc(aArg: TProc2);

SomeProc(lambda as Writeln(aArg));

Which SomeProc to choose? Even if the lamda's code could derive the 
argument types directly (which must not be the case as you can see in 
the example, as Writeln can take an Integer as well as a String) you'd 
still need to find the correct procedure.

Also the parameter names MUST be declared somewhere. This is Pascal. 
There can't be a symbol name appearing suddenly in the middle of the code.

These three points are why I proposed my example as is: we need somehow 
the signature of the lambda. Maybe "lambda(aArg: Integer) as 
Writeln(aArg)" would be sufficient already (or "lambda(aArg: Integer): 
String as IntToStr(aArg)" for a function).

Otherwise - to borrow a statement from the for-in-index thread - we 
would be butchering Pascal.

>
> Independently, I propose a general shorthand for functions containing
> a single expression
> (and perhaps for procedures containing a single statement, but I am
> less certain here):
>
> function f(a, b: Integer): Integer;
> begin Result := a + b; end;
> =>
> function f(a, b: Integer): Integer as a + b;
>

I don't know whether I'd want to extend this to single line 
functions/procedures. This is where the language becomes less clear again.

> with both shortcuts combined, it becomes possible to write something like
>
> sum := arr.Reduce(lambda as a + b;);
>
> Even further, Ruby (or Objective C)-like extension may be introduced to allow
> procedure arguments (or perhaps just the last one) to be separated by
> some special character instead of parenthesis, for example:

No, no, no. No "special characters". If you want to differentiate 
something, then use keywords.

Regards,
Sven



More information about the fpc-devel mailing list