Anonymous procedures (Was: Re: [fpc-devel] for-in-index loop)
Alexander Klenin
klenin at gmail.com
Sat Jan 26 20:12:48 CET 2013
On Sun, Jan 27, 2013 at 3:10 AM, Sven Barth <pascaldragon at googlemail.com> wrote:
> On 26.01.2013 16:34, Alexander Klenin wrote:
>> Ok, then let's take just one step back:
>> SomeProc(lambda TProc1 as Writeln(aArg));
>>
>> This way, but problems are solved -- procedure type is specified
>> independently from the parameter type,
>> and overload resolution will work.
>
> While the compiler would be satisfied by this, this nevertheless leaves the
> problem that we (as in "the user of the language") don't really see where
> the aArg comes from...
>
> I can already imagine many questions like the following appearing on the
> mailing list:
>
> === quote begin ===
>
> type
> TMyProc = reference to function(aArg: Integer): String;
>
> procedure SomeProc(aArg: Integer);
> begin
> SomeProcTakingTMyProc(lambda TMyProc as IntToStr(aArg));
> end;
>
> Why doesn't the lambda expression return the value that's passed to
> SomeProc, but something completely different?!
>
> === quote end ===
This is quite similar to using "with" statement -- yes, name clashes
are possible.
Perhaps they should be disallowed, like currently it is impossible to
declare local variable
overriding class field (except in Delphi mode).
In this case, user will have to revert to full syntax.
> Maybe the idea that I presented in the mail in the for-in-index thread:
>
> lambda TProc(aArg) as ...
>
> TProc is used to bind the correct type and the names in the parentheses are
> mapped to the arguments of TProc.
Well, this would be yet another step backwards.
The break-even point where the gain is not enough to justify the
feature would be quite near.
I'd prefer the previous variant -- with additional safety as described above.
> Just one point to ensure we understand this the same: if we use the
> abbreviated syntax ("as STMT/EXPR") then no variable/type/constant
> declarations are possible.
Of course, that's the point of the shorthand.
> What still bothers me a bit is the handling of result values... if we
> require the code after the AS to be an EXPR we'd need to implicitely assign
> the result value. What does now happen if the lambda's type does require a
> return value, but we don't provide one? What the otherway round?
I suggest the following:
Shortcut for functions *require* expression as body,
since the only correct single statement would be assignment to Result
(or call to Exit with an argument).
Shortcut for procedures *require* a statement.
Of course, the statement may be a function call, but that does not
matter for procedure.
> === example begin ===
>
> type
> TProc = reference to procedure;
> TIntFunc = reference to function;
>
> x := lambda TProc as fMyMemo.Lines.Add('FooBar'); // Add returns Integer
ok
> y := lambda TIntFunc as Writeln('Foobar');
Syntax error: expression expected
>> But in this case, perhaps you are right, how about (taking into
>> account the discussion of lambda above):
>>
>> sum := a.Reduce with lambda TAdderFunc as a + b;
>> or without type helpers:
>> sum := Reduce with a, lambda TAdderFunc as a + b;
> While I still don't know why you'd want to replace parenthesis I would
> definitely prefer this syntax over any ":" you can throw at me ^^
This is mostly to avoid JavaScript-style mixed closing brackets in nested calls:
a.forEach(function (aelem) {
aelem.forEach(function (v) {
doSomething(v);
})
});
with the no-parenthisis extension, the Pascal equivalent may be
(suppose the actual code is long, so "as" shortcut does not apply):
a.forEach with lambda TAElemProc begin
AElem.forEach with lambda TIntegerProc begin
doSomething(v);
end;
end;
without the extension, the Pascal equivalent may be:
a.forEach(lambda TAElemProc begin
AElem.forEach(lambda TIntegerProc begin
doSomething(v);
end);
end);
--
Alexander S. Klenin
More information about the fpc-devel
mailing list