Anonymous procedures (Was: Re: [fpc-devel] for-in-index loop)
Alexander Klenin
klenin at gmail.com
Fri Jan 25 23:57:04 CET 2013
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.
I am still of the opinion that "for-in-index" would be a good addition
nevertheless,
because it is a simple and neat solution for 90% of the cases, so even
if there exists
a general and complex solution for 100%, IMHO simple one is still worth having.
Nevertheless, I separated the thread to discuss anonymous procedures,
hopefully with less flame, or at least, with flame of different colours :)
When comparing anonymous procedures with built-in for-in loop,
it is important to consider the code speed.
I think that good support for inlining "Iterate" procedure *together
with its argument*
is essential for anonymous procedures to be a competitive solution for
the problem
of container iteration.
> map.Iterate(procedure(const aKey: String; const aValue: TObject)
> begin
> Writeln(aKey, ' => ', aValue.ClassName);
> end;
> );
As you noted, this solution is conceptually good, but rather cumbersome to write
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".
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;
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:
procedure p(a, b: Integer);
p(3, 5); // Traditional syntax
p :3 :5; // Proposed extension
Then, then code will be
map.Iterate :lambda
Writeln(aKey, ' => ', aData.ClassName);
end;
sum := arr.Reduce :lambda as a + b;
which is as good as it gets, IMHO.
> And for a given array type and type helper support you can do the following:
While type helpers are a neat idea, I fear they introduce too much
"action at a distance"
for so frequent usage.
A global generic functions (they are planned anyway, aren't they?)
will be sufficient:
Iterate :map :lambda
Writeln(aKey, ' => ', aData.ClassName);
end;
--
Alexander S. Klenin
More information about the fpc-devel
mailing list