On 17/04/2021 5:34 pm, fredvs wrote:
> There was some work done to make it work:
> https://github.com/mse-org/mselang/releases
>
> I was able to do some console application on Linux (the version of LLVM for
> Windows was not yet working when I try it 3 years ago).
Thank you Fred for all the information. I'm looking at the MSELang repo
as we speak.
The reason I ask, I was comparing Delphi's Anonymous Methods (lambdas) +
Generics
to how Java does it. It is crazy how verbose Embarcadeco made the syntax. The
compiler
is supposed to be inteligent, yet with the Delphi syntax, you are spoon-feeding
the compiler with things it could have figured out from the code itself, and
often
duplicating information. You really don't save much typing that way.
I'm toying with the idea of experimenting with the Free Pascal Compiler, and
was looking at maybe contributing to FPC (if they don't want it - most
likely outcome - as they only like to copy Embarcadero), then the other option
might be MSELang. But I don't know anything about MSELang and what its
goals were. But I've got a better idea now - thanks to all your links.
The rest of this message is optional... ;-)
Here is a simple example:
========[ As done in Delphi ]========================
type
TSimpleProcedure = reference to procedure;
TSimpleFunction = reference to function(x: string): Integer;
var
x1: TSimpleProcedure;
y1: TSimpleFunction;
begin
x1 := procedure
begin
Writeln('Hello World');
end;
x1; //invoke anonymous method just defined
y1 := function(x: string): Integer
begin
Result := Length(x);
end;
Writeln(y1('bar'));
end.
==================[ end Delphi ]=====================
Now for my idea...
There are some standard "functional interfaces" defined in the RTL like,
but in your own code, you can define your own ones too. The compile will
treat them in the same way is I describe here:
type
// Represents a function that accepts one argument and produces a result.
IFunction<T,R> = interface
function apply(T): R;
end;
// Represents a predicate (boolean-valued function) of one argument.
IPredicate<T> = interface
function test(T): boolean;
end;
// Represents an operation that accepts a single input argument and returns
no result.
IConsumer<T> = interface
procedure accept(T);
end;
// Represents a supplier of results.
ISupplier<T> = interface
function get: T;
end;
// Represents a prodecute that takes no argument and produces no result.
IRunnable = interface
procedure run;
end;
You can then use those in anonymous methods like this:
========[ Mine ]===================================
var
x1: IRunnable;
y1: IFunction<string, integer>;
begin
x1 := () -> Writeln('Hello World'); (1)
x1; //invoke anonymous method just defined
y1 := s -> Result := Length(s); (2)
Writeln(y1('bar'));
end.
==================[ end Mine ]=====================
(1) - The () syntax lists any parameters. It's empty, so no parameters
are used. They are only required if the parameter list is empty.
- The -> syntax borrows from Java and lets the compiler know this
is a lambda (anonymous method)
- IRunnable's method takes no parameters and has no return type
- The code after the -> is the body of the method. This is a 1 line
body, so doesn't require the verbose begin/end pair.
IRunnable is a "functional inteface" with only one method that needs
to be implemented. From that the compiler knows the name and signature
of the method, by looking it up from the interface definition. The
compiler can construct a anonymous class to implement the anonymous
method. That could automatically result in something like this - all
done by the compiler itself:
type
TInternalAnonymousClassName = class(TInterfaceObject) implements IRunnable
public
function run;
end;
TInternalAnonymousClassName.run;
begin
Writeln('Hello World');
end;
(2) - The process is pretty much the same as (1), but this time the
functional inteface signater is different.
- IFunction takes one parameter and returns a result.
- The definition of y1 tells the compiler that the parameter
is of type String and the return type is of type Integer.
So when you define the lambda, you don't have to repeat the
data type information
- s is the name of the parameter, and the compiler already knows
is must be of type String.
- agian it's a one line method, so no need for the begin/end pair.
type
TInternalAnonymousClassName = class(TInterfaceObject) implements IFunction
public
procedure apply(s: String): Integer;
end;
TInternalAnonymousClassName.apply(s: String): Integer;
begin
Result := Length(s);
end;
Regards,
Graeme
_______________________________________________
mseide-msegui-talk mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mseide-msegui-talk