On 25.01.2013 23:57, Alexander Klenin wrote:
On Sat, Jan 26, 2013 at 5:17 AM, Sven Barth <pascaldra...@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
_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply via email to