|
To the best of my understanding, lambdas-as-objects would mean providing structural types, i.e. generic function types that are able to describe the structure of a lambda (arguments and result type). e.g. (a fictive syntax): Function0<Int> f = () => 5
f here is a lambda that take no args and returns an Int. It's type is Function0 (0 for no args) and parameterized with the return type.Another example with 2 args: Function2<String, Float, Int> f = (String name, Float rate) => 5
The Function* types are the generic structural types able to describe lambdas. C# has them, and so does Scala.Java however decided not to have them, because they don't adhere well with Java's history with nominative types (a type has a name that carries sense). They rather came up with the SAM auto conversion, which is a neat idea in itself, but a bit less flexible than structural types, and may (and will lead to a Cambrian explosion in the number of types, e.g. Reducer, Mapper, Folder, Filter, Predicate, etc.) What's even worse though is erasure: Java generics are erased at compile time, and this fucks up things really bad with overloading, so in a code like this (in the type List for example): public <S> List<T> stupidOpName(Function1<T, S> f) { ... }
public List<T> stupidOpName(Function1<T, Boolean> f) { ... }
After erasure, we'll end up with : public List stupidOpName(Function1 f) { ... }
public List stupidOpName(Function1 f) { ... }
i.e. 2 methods with the same name and same signature. This is bad. You don't ever want that to happen. And fortunately the java compiler won't let it happen.So, the alternative is I said SAM (Single Abstract Method) types: no structural types, but lambdas can be automatically converted to a SAM if compatible, so you could do this for example: Runnable r = () => { ... }
The lambda gets converted to the Runnable type. |
With the slight difference that its generics are reified, so all `Function` generic arities have the same name (it's `Function<T>`, `Function<T1, T2>`, ...), although because there is no `void` or `Unit` type in C# it needs two base function types, to handle functions with a return value (`Function`) and functions with no return value (`Action`).
I believe the Kotlin project fixes this issue by having a first-class `Unit` type, so C#'s `Action` becomes `Func<Unit>` in Kotlin.