Java Lambdas and Closures - java

I hear lambdas are coming soon to a Java near you (J8). I found an example of what they will look like on some blog:
SoccerService soccerService = (teamA, teamB) -> {
SoccerResult result = null;
if (teamA == teamB) {
result = SoccerResult.DRAW;
}
else if(teamA < teamB) {
result = SoccerResult.LOST;
}
else {
result = SoccerResult.WON;
}
return result;
};
So right off the bat:
Where are teamA and teamB typed? Or aren't they (like some weird form of generics)?
Is a lambda a type of closure, or is it the other way around?
What benefits will this give me over a typical anonymous function?

The Lambda expression is just syntactic sugar to implement a target interface, this means that you will be implementing a particular method in the interface through a lambda expression. The compiler can infer the types of the parameters in the interface and that's why you do not need to explicitly define them in the lambda expression.
For instance:
Comparator<String> c = (s1, s2) -> s1.compareToIgnoreCase(s2);
In this expression, the lambda expression evidently implements a Comparator of strings, therefore, this implies the lambda expression is syntactic sugar for implementing compare(String, String).
Thus, the compiler can safely assume the type of s1 and s2 is String.
Your target interface type provides all the information the compiler needs to determine what are the actual types of the lambda parameters.
Briant Goetz, Java Language Architect at Oracle Corportion has published a couple of articles of the work in progress in JDK 8 Lambdas. I believe the answers to your questions are there:
State of Lambda.
State of Lambda Libraries Edition.
Translation of Lambda Expressions
JVMLS 2012: Implementing Lambda Expressions in Java
This second article explains how the lambda expressions are implemented at the bytecode level and may help you delve into the details of your second question.

See this page for a full version of that example (however, the relevant parts are shown below).
The types are inferred from the SoccerService interface and SoccerResult enum, not shown in your snippet:
enum SoccerResult{
WON, LOST, DRAW
}
interface SoccerService {
SoccerResult getSoccerResult(Integer teamA, Integer teamB);
}
The benefit (of lambdas versus standard anonymous classes) is just reduced verbosity:
(x, y) => x + y
versus something like:
new Adder()
{
public int add(int x, int y)
{
return x + y;
}
}
For the difference between a closure and a lambda, see this question.

Where are teamA and teamB typed? Or aren't they (like some weird form of generics)?
Lambda's use target typing, much like generic method calls (since 1.5) and the diamond [not an] operator (since 1.7). Roughly, where the type the result applied to is stated (or can be inferred) that is used to supply the type of the Single Abstract Method (SAM) base type and hence the method parameter types.
As an example of generic method inference in 1.5:
Set<Team> noTeams = Collections.emptySet();
And diamond operator in 1.7:
Set<Team> aTeams = new HashSet<>();
Team, team, team, team, team, team. I even love saying the word team.
Is a lambda a type of closure, or is it the other way around?
A lambda is a limited form of closure in almost exactly the same way as anonymous inner classes, but with some random differences to catch you out:
The outer this is not hidden by an inner this. This means that the same text in a lambda and an anonymous inner class can mean subtly but completely different things. That should keep Stack Overflow busy with odd questions.
To make up for the lack of inner this, if assigned directly to a local variable, then that value is accessible within the lambda. IIRC (I could check, but wont), in an anonymous inner class the local will be in scope and hide variables in an outer scope but you can't use it. I believe the lack of an instance initialiser makes this much easier to specify.
Local fields that do not happen to be marked final but could be, are treated as if they are final. So not are they in scope, but you can actually read (though not write) them.
What benefits will this give me over a typical anonymous function?
A briefer syntax. That's about it.
Of course the rest of the Java syntax is just as hopelessly bad as ever.
I don't believe this is in the initial implementation, but instead of being implemented as [inner] classes, lambdas can use method handles. The performance of method handles falls somewhat short of earlier predictions. Doing away with classes, should reduce bytecode footprint, possibly runtime footprint and certainly class loading time. There could be an implementation where most anonymous inner classes (not Serializable, trivial static initialiser) didn't go through the poorly conceived class loading mechanism without any particularly noticeable incompatibilities.
(Hope I've got the terminology wrt hiding correct.)

Related

Why can a void method in C++ return a void value, but in other languages it cannot?

This program compiles and runs in C++ but doesn't in a number of different languages, like Java and C#.
#include <iostream>
using namespace std;
void foo2() {
cout << "foo 2.\n";
}
void foo() {
return foo2();
}
int main() {
foo();
return 0;
}
In Java this gives a compiler error like 'Void methods cannot return a value'. But since the method being called is a void itself, it doesn't return a value. I understand that a construct like this is probably prohibited for the sake of readability. Are there any other objections?
Edit: For future reference, I found some a similar question here return-void-type-in-c-and-c
In my humble opinion this question isn't answered yet.
The reply 'Because it says so in the specification, move on' doesn't cut it, since someone had to write the specification in the first place. Maybe I should have asked 'What are the pros and cons of allowing returning a void type like C++'?
It's because of the possibility of its usage in templates. C# and Java forbid void as a type argument, but C++ permits it to allow you to write template code like this:
template<typename T, typename TResult>
TResult foo(T x, T y)
{
return foo2(x, y);
}
If void methods weren't allowed to return a void expression, this template instantiation would be impossible if TResult was void. If that were the case, you would need a separate template definition if you ever wanted TResult to actually be void.
For example, remember how in C# there are two sets of generic general-purpose delegates, namely Func<> and Action<>? Well, Action<T> exists precisely because Func<T, void> is forbidden. The C++ designers didn't want to introduce situations like this wherever possible, so they decided to allow you to use void as a template argument -- and the case you found is a feature to facilitate exactly that.
(Allow me to write the rest in a pretend-Q&A format.)
But why do C# and Java not allow a similar construct?
First, realize how generic programming is made possible in those languages:
C# and Java generics work by parsing a generic type (or method) definition and making sure it is valid for the generic constraints/bounds you have provided.
C++ templates are a search-and-replace mechanism with a powerful metaprogramming language around them. They are not required to make sense in the absence of specific template arguments -- they go from the "template metalanguage" to the "C++ language" (so to speak) only when they get their hands on actual arguments.
Why pick one approach of implementing generic programming over the other?
The generics approach maintains the nominal typing of the rest of the language. This has the advantage of allowing the (AOT) compiler to do static analysis, type checking, error reporting, overload resolution and eventually code generation once.
The templates approach is essentially duck typing. Duck typing in a nominally typed language doesn't have the advantages described above, but it allows you more flexibility in the sense that it will permit potentially "invalid" things ("invalid" from the point of view of a nominal type system) as long as you don't actually mention those invalid possibilities anywhere in your program. In other words, templates allow you to express a larger set of cases uniformly.
Okay, so what would C# and Java need to do to support void as a valid generic argument?
I would have to speculate to answer this, but I'll try.
At the language level, they would have to waive the notion that return; is valid only in void methods and always invalid for non-void methods. Without this change, very few useful methods could be instantiated -- and they would all probably have to end with recursion or an unconditional throw (which satisfies both void and non-void methods without returning). So to make this useful, C# and Java would also have to introduce the C++ feature of allowing you to return void expressions.
Okay, let's assume you have that and now you can write code like this:
void Foo2() { }
void Foo()
{
return Foo2();
}
Again, the non-generic version is as useless in C# and Java as it is in C++. But let's move on and see its real usefulness, which is in generics.
You should now be able to write generic code like this -- and TResult could now be void (in addition to all the other types that were already permitted):
TResult Foo<T, TResult>(T a)
{
return Foo2(a);
}
But remember that in C# and Java, overload resolution happens "early", rather than "late". The same callee will be chosen by the overload resolution algorithm for every possible TResult. And the type checker will have to complain, because you're either returning a void expression from a possibly non-void method or you're returning a non-void expression from a possibly void method.
In other words, the outer method can't be generic, unless:
The callee is also generic and its return type is defined by a generic type parameter that matches that of the outer method.
Overload resolution in generic types and methods is postponed until actual type arguments are made available, so that we can pick a correct non-generic method at the call spot.
What if we went with the first option - make the callee's return type generic and move on?
We could do that, but it simply pushes our problem to the callee.
At some point, we would need some way to "instantiate" some kind of void instance and optionally be able to receive it somehow. So now we would need constructors for void (although every void method could count as a factory method, if you squint) and we would also need variables of type void, possible conversions from void to object, and so on.
Basically, void would have to become a regular type (e.g. a regular empty struct) for all intents and purposes. The implications of this aren't terrible, but I think you can see why C# and Java avoided it.
What about the second option - postpone overload resolution?
Also entirely possible, but note that it would effectively turn generics into weaker templates. ("Weaker" in the sense that C++ templates aren't restricted to typenames.)
Again, it wouldn't be the end of the world, but it would involve losing the advantages of generics that I described earlier. The designers of C# and Java clearly want to keep those advantages.
Sidenote:
In C#, there is one special case I know of, where binding happens after the validation of the generic type definition. If you have a new() constraint on a T and you attempt to instantiate a new T(), the compiler will generate code that checks whether T is a value type or not. Then:
For value types, new T() becomes default(T) -- remember that C# default struct constructors aren't really constructors in the CLR sense.
For reference types, Activator.CreateInstance is called, which is an indirect constructor invocation using reflection.
This particular case is very special because, even though it has completely postponed method binding to the runtime, the compiler can still perform static analysis, type checking and code generation once. After all, the type of the expression new T() is always T and a call to something that has an empty formal parameter list can be trivially resolved and verified.
According to the Java Language Specification §14.17:
A return statement with no Expression must be contained in one of the following, or a compile-time error occurs:
A method that is declared, using the keyword void, not to return a value (§8.4.5)
...
A return statement with an Expression must be contained in one of the following, or a compile-time error occurs:
A method that is declared to return a value
...
So, by declaring that a method is void, you are saying that it returns no value, so you are limited to using a return; statement with no expression.

Java 8 dancing around functions as first class citizens? [duplicate]

This question already has answers here:
Java 8 lambda expression and first-class values
(5 answers)
Closed 8 years ago.
So the functional programmer in me likes languages like python that treat functions as first class citizens. It looks like Java 8 caved to the pressure and "sort of" implemented things like lambda expressions and method references.
My question is, is Java on its way to using first class functions, or is this really just syntactic sugar to reduce the amount of code it takes to implement anonymous classes / interfaces such as runnable? (my gut says the latter).
My ideal scenario
Map<String,DoubleToDoubleFunc> mymap = new HashMap<String,DoubleToDoubleFunc>();
...
mymap.put("Func 1", (double a, double b) -> a + b);
mymap.put("Func 2", Math::pow);
...
w = mymap.get("Func 1")(y,z);
x = mymap.get("Func 2")(y,z);
There is no function structural type in Java 8. But Java has always had first class objects. And in fact, they have been used as an alternative. Historically, due to the lack of first-class functions, what we have done so far is to wrap the function inside an object. These are the famous SAM types (single abstract method types).
So, instead of
function run() {}
Thread t = new Thread(run);
We do
Runnable run = new Runnable(){ public void run(){} };
Thread t = new Thread(run);
That is, we put the function inside an object in order to be able to pass it around as a value. So, first class objects have been an alternative solution for a long time.
The JDK 8 simply makes implementing this concept simpler, and they call this type of wrapper interfaces "Functional Interfaces" and offer some syntactic sugar to implement the wrapper objects.
Runnable run = () -> {};
Thread t = new Thread(run);
But ultimately, we are still using first-class objects. And they have similar properties to first-class functions. They encapsulate behavior, they can be passed as arguments and be returned as values.
In the lambda mailing list Brian Goetz gave a good explanation of some of the reasons that motivated this design.
Along the lines that we've been discussing today, here's a peek at
where we're heading. We explored the road of "maybe lambdas should
just be inner class instances, that would be really simple", but
eventually came to the position of "functions are a better direction
for the future of the language".
This exploration played out in stages: first internally before the EG
was formed, and then again when the EG discussed the issues. The
following is my position on the issue. Hopefully, this fills in some
of the gaps between what the spec currently says and what we say
about it.
The issues that have been raised about whether lambdas are objects or
not largely come down to philosophical questions like "what are
lambdas really", "why will Java benefit from lambdas", and ultimately
"how best to evolve the Java language and platform."
Oracle's position is that Java must evolve -- carefully, of course --
in order to remain competitive. This is, of course, a difficult
balancing act.
It is my belief that the best direction for evolving Java is to
encourage a more functional style of programming. The role of Lambda
is primarily to support the development and consumption of more
functional-like libraries; I've offered examples such as
filter-map-reduce to illustrate this direction.
There is plenty of evidence in the ecosystem to support the hypothesis
that, if given the tools to do so easily, object-oriented programmers
are ready to embrace functional techniques (such as immutability) and
work them into an object-oriented view of the world, and will write
better, less error-prone code as a result. Simply put, we believe the
best thing we can do for Java developers is to give them a gentle push
towards a more functional style of programming. We're not going to
turn Java into Haskell, nor even into Scala. But the direction is
clear.
Lambda is the down-payment on this evolution, but it is far from the
end of the story. The rest of the story isn't written yet, but
preserving our options are a key aspect of how we evaluate the
decisions we make here.
This is why I've been so dogged in my insistence that lambdas are not
objects. I believe the "lambdas are just objects" position, while
very comfortable and tempting, slams the door on a number of
potentially useful directions for language evolution.
As a single example, let's take function types. The lambda strawman
offered at devoxx had function types. I insisted we remove them, and
this made me unpopular. But my objection to function types was not
that I don't like function types -- I love function types -- but that
function types fought badly with an existing aspect of the Java type
system, erasure. Erased function types are the worst of both worlds.
So we removed this from the design.
But I am unwilling to say "Java never will have function types"
(though I recognize that Java may never have function types.) I
believe that in order to get to function types, we have to first deal
with erasure. That may, or may not be possible. But in a world of
reified structural types, function types start to make a lot more
sense.
The lambdas-are-objects view of the world conflicts with this possible
future. The lambdas-are-functions view of the world does not, and
preserving this flexibility is one of the points in favor of not
burdening lambdas with even the appearance of object-ness.
You might think that the current design is tightly tied to an object
box for lambdas -- SAM types -- making them effectively objects
anyway. But this has been carefully hidden from the surface area so
as to allow us to consider 'naked' lambdas in the future, or consider
other conversion contexts for lambdas, or integrate lambdas more
tightly into control constructs. We're not doing that now, and we
don't even have a concrete plan for doing so, but the ability to
possibly do that in the future is a critical part of the design.
I am optimistic about Java's future, but to move forward we sometimes
have to let go of some comfortable ideas. Lambdas-are-functions opens
doors. Lambdas-are-objects closes them. We prefer to see those doors
left open.
They are not really first-class functions IMO. Lambda is ultimately an instance of a functional interface. But it does give you advantages of a first-class function. You can pass it as an argument to a method that expects an instance of functional interface. You can assign it to a variable, in which case its type will be inferred using target typing. You can return it from a method, so on.
Also, lambdas doesn't completely replace anonymous classes. Not all anonymous classes can be converted to lambdas. You can go through this answer for a nice explanation about difference between the two. So, no lambdas are not syntactic sugar for anonymous classes.
It's not syntactic sugar for anonymous classes; what it compiles to is somewhat more involved. (Not that it would be wrong to do that; any language will have its own implementation detail for how lambdas are compiled, and Java's is no worse than many others.)
See http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html for the full, nitty-gritty details.
interface DoubleDoubleToDoubleFunc {
double f(double x, double y);
}
public static void main(String[] args) {
Map<String, DoubleDoubleToDoubleFunc> mymap = new HashMap<>();
mymap.put("Func 1", (double a, double b) -> a + b);
mymap.put("Func 2", Math::pow);
double y = 2.0;
double z = 3.0;
double w = mymap.get("Func 1").f(y,z);
double v = mymap.get("Func 2").f(y,z);
}
So it still is syntactic sugar and only to some degree.

Java 8 lambda expression and first-class values

Are Java 8 closures really first-class values or are they only a syntactic sugar?
I would say that Java 8 closures ("Lambdas") are neither mere syntactic sugar nor are they first-class values.
I've addressed the issue of syntactic sugar in an answer to another StackExchange question.
As for whether lambdas are "first class" it really depends on your definition, but I'll make a case that lambdas aren't really first class.
In some sense a lambda wants to be a function, but Java 8 is not adding function types. Instead, a lambda expression is converted into an instance of a functional interface. This has allowed lambdas to be added to Java 8 with only minor changes to Java's type system. After conversion, the result is a reference just like that of any other reference type. In fact, using a Lambda -- for example, in a method that was passed a lambda expression as parameter -- is indistinguishable from calling a method through an interface. A method that receives a parameter of a functional interface type can't tell whether it was passed a lambda expression or an instance of some class that happens to implement that functional interface.
For more information about whether lambdas are objects, see the Lambda FAQ Answer to this question.
Given that lambdas are converted into objects, they inherit (literally) all the characteristics of objects. In particular, objects:
have various methods like equals, getClass, hashCode, notify, toString, and wait
have an identity hash code
can be locked by a synchronized block
can be compared using the == and != and instanceof operators
and so forth. In fact, all of these are irrelevant to the intended usage of lambdas. Their behavior is essentially undefined. You can write a program that uses any of these, and you will get some result, but the result may differ from release to release (or even run to run!).
Restating this more concisely, in Java, objects have identity, but values (particularly function values, if they were to exist) should not have any notion of identity. Java 8 does not have function types. Instead, lambda expressions are converted to objects, so they have a lot baggage that's irrelevant to functions, particularly identity. That doesn't seem like "first class" to me.
Update 2013-10-24
I've been thinking further on this topic since having posted my answer several months ago. From a technical standpoint everything I wrote above is correct. The conclusion is probably expressed more precisely as Java 8 lambdas not being pure (as opposed to first-class) values, because they carry a lot of object baggage along. However, just because they're impure doesn't mean they aren't first-class. Consider the Wikipedia definition of first-class function. Briefly, the criteria listed there for considering functions first-class are the abilities to:
pass functions as arguments to other functions
return functions from other functions
assign functions to variables
store functions in data structures
have functions be anonymous
Java 8 lambdas meet all of these criteria. So that does make them seem first-class.
The article also mentions function names not having special status, instead a function's name is simply a variable whose type is a function type. Java 8 lambdas do not meet this last criterion. Java 8 doesn't have function types; it has functional interfaces. These are used effectively like function types, but they aren't function types at all. If you have a reference whose type is a functional interface, you have no idea whether it's a lambda, an instance of an anonymous inner class, or an instance of a concrete class that happens to implement that interface.
In summary, Java 8 lambdas are more first-class functions than I had originally thought. They just aren't pure first-class functions.
Yes, they are first class values (or will be, once Java 8 is released...)
In the sense that you can pass them as arguments, compose them to make higher order functions, store them in data structures etc. You will be able to use them for a broad range of functional programming techniques.
See also for a bit more definition of what "first class" means in this context:
http://en.wikipedia.org/wiki/First-class_citizen
As I see it, it is syntactic sugar, but in addition with the type inference, a new package java.util.functions and semantic of inner classes it does appear as a first-class value.
A real closure with variable binding to the outside context has some overhead. I would consider the implementation of Java 8 optimal, sufficiently pure.
It is not merely syntactical sugar at least.
And I wouldn't know of any more optimal implementation.
For me Lambdas in Java 8 is just syntax sugar because you cannot use it as First class Citizen (http://en.wikipedia.org/wiki/First-class_function) each function should be wrapped into object it imposes many limitation when comparing to language with pure first class function like SCALA. Java 8 closures can only capture immutable ("effectively final") non-local variables.
Here is better explanation why it is syntax-sugar Java Lambdas and Closures

Why does Java need interfaces and Smalltalk does not?

I have been programming in Smalltalk for some time, but I never really needed interfaces to implement anything. Then why can't languages such as Java get rid of interfaces? Is it only Smalltalk or is there another language which doesn't need interfaces?
Because Java is statically typed while Smalltalk is not. Interfaces don't serve any purpose when you don't declare types and your variables aren't going to be typechecked. But in a statically typed language like Java, they're extremely handy, because they let you have a variable whose type is defined by the methods the object implements instead of its class. It brings you a lot closer to the dynamic typing Smalltalk has natively without giving up the benefits of typechecking.
It is a polymorphism issue: in Java you have static types and therefore you need to know which messages can your object answer... in Smalltalk (and other non-static languages) you just need to implement right methods to have polymorphism.
For instance:
In Java you need to implement Cloneable, who defines method
Cloneable.clone to have cloneble objects. Then, the compiler knows
your object will understand that method (otherwise it will throw an
error)
In smalltalk, you just need to implement method #clone.
Compiler never knows/don't care about which messages understands your
objects until it is called.
That also means you can have polymorphic objects without being part of same hierarchy... multi inheritance, mixins and other approachs (traits are present on Pharo) are just reuse technics, not a design constraint.
This way of do things is often called "duck typing"... see: http://en.wikipedia.org/wiki/Duck_typing
Do you think there might be a useful role for "interfaces" in Smalltalk?
See - Adding Dynamic Interfaces to Smalltalk
not sure what exactly your asking (or rather, which question you most want answered) but have a look at Ruby. From my understanding it's much closer to smalltalk than Java is.
If i were to answer the question about why java needs interfaces, I guess I'd say something about java being a statically typed language and taking that philosophy to the extent that java does is what makes for the need of interfaces. Effectively interfaces try to give you something like multiple inheritence in java without the multiple inheritance issues that other languages face (C++ i believe).
Java has no need for interfaces. It is something the compiler chose to support rather than discard.
At runtime, interfaces cannot be enforced in any language because all dynamic objects are either 1. structs of pure state or 2. structs of pure state with first member being a pointer to a vtable mapping either integers to members(via array) or strings to members(being dictionary/hashmap). The consequence of this is that you can always change the values at indices of the vtable, or entries of the hashmap, or just change the vtable pointer to another vtable address, or just illegal access memory.
Smalltalk could have easily stored information given at compile time of your classes, and in a way it does, that's how intellisense in smalltalk browsers gives member suggestions, but this would not actually benefit smalltalk.
There are several issues with smalltalk's syntax that limits the use of interfaces.
Smalltalk has only one primary type
This means that it can't just warn you if you try putting a square into a circle hole, there are no squares, there are no holes, everything is an object to the smalltalk compiler.
The compiler could choose to type deduce variables that were assigned, but smalltalk philosophically objects to doing so.
Smalltalk methods always take one argument
It might seem like doing myArray at: 1 put: 'hi' has two arguments, but in reality, you are calling a javascript equivelent of myArray['at:put:']([1, 'hi']) with myArray being an object(~hashmap). the number of arguments thus cannot be checked without breaking the philosophy of smalltalk.
there are workarounds smalltalk could do to check number of arguments, but it would not give much benefit.
smalltalk exposes its compiler to runtime, whereas java tries very hard to bury the compiler from runtime.
When you expose your compiler to runtime(all languages from assembly to javascript can easily expose their compiler to runtime, few make it part of the easily accessible parts of the language, the more accessible the compiler is at runtime, the higher level we consider the language to be), your language becomes a tad more fragile in that the information you use at compile time on one line, may no longer be valid on another line because at runtime, the information compiler relied on being fixed is no longer the same.
One consequence of this is that a class might have one interface at one point of the program, but half way into the program, the user changed the class to have another interface; if the user wants to use this interface at compile time(after changing the class using code), the compiler needs to be much smarter to realize that the class that didn't support ".Greet()" now suddenly does, or no longer does, or that the method ".Greet()" and method ".Foo()" have been swapped around.
interfaces are great at compile time, but completely unenforceable at runtime. This is great news for those that want to change behavior of code without needing to restart the program, and horrible news for type safety purists - their ideals simply can't be enforced at runtime without manually poking every assertion at an interval.
unlike C++, smalltalk does not use arrays for vtables, instead it uses maps from strings to objects. This means that even if you do know that the method exists in the class you're calling, you cannot optimize it to a dispid so that future calls to this method use array offset instead of hashing to find the method. To demonstrate this, let's use javascript:
The current smalltalk objects behave analogous to this:
var myIntVtbl = {
'+': function(self, obj1) {
return {lpVtbl: myIntVtbl, data: self.data + obj1.data};
}
};
var myInt1 = {lpVtbl: myIntVtbl, data: 2};
var myInt2 = {lpVtbl: myIntVtbl, data: 5};
var myInt3 = myInt1['lpVtbl']['+'](myInt1, myInt2);
var myInt4 = myInt3['lpVtbl']['+'](myInt3, myInt3);
var myInt5 = myInt4['lpVtbl']['+'](myInt4, myInt4);
console.log(myInt5);
each time we call +, we must hash '+' to get the member from the vtable dictionary. Java works similarly, which is why decompilers can tell the names of methods so easily.
one optimization that a compiler can do if it knows interfaces, is to compile strings to dispids, like so:
var myIntVtbl = [
function(self, obj1) {
return {lpVtbl: myIntVtbl, data: self.data + obj1.data};
}
];
var myInt1 = {lpVtbl: myIntVtbl, data: 2};
var myInt2 = {lpVtbl: myIntVtbl, data: 5};
var myInt3 = myInt1['lpVtbl'][0](myInt1, myInt2);
var myInt4 = myInt3['lpVtbl'][0](myInt3, myInt3);
var myInt5 = myInt4['lpVtbl'][0](myInt4, myInt4);
console.log(myInt5);
as far as I know, neither java nor smalltalk do this for classes, whereas C++, C#(via comvisible attribute) do.
To summarize, smalltalk can use interfaces, in turn becoming more like PHP, but won't get pretty much any benefit of it at compile time other than weak reassurances.
Likewise, Java doesn't need interfaces, it can literally work like smalltalk under the condition that you expose the java compiler to java to be more accessible. To get a feel for this, you can interop between java and nashorn javascript engine that comes with all current java kits and use its' eval function as a runtime compiler. Java can easily get rid of interfaces, and use reflective polymorphism, treat everything as Object, but it'll be much more verbose to talk to objects without letting you index by string, and overloading the index operator for string to dynamically find the members.

Why does erasure complicate implementing function types?

I read from an interview with Neal Gafter:
"For example, adding function types to the programming language is much more difficult with Erasure as part of Generics."
EDIT:
Another place where I've met similar statement was in Brian Goetz's message in Lambda Dev mailing list, where he says that lambdas are easier to handle when they are just anonymous classes with syntactic sugar:
But my objection to function types was not that I don't like function types -- I love function types -- but that function types fought badly with an existing aspect of the Java type system, erasure. Erased function types are the worst of both worlds. So we removed this from the design.
Can anyone explain these statements? Why would I need runtime type information with lambdas?
The way I understand it, is that they decided that thanks to erasure it would be messy to go the way of 'function types', e.g. delegates in C# and they only could use lambda expressions, which is just a simplification of single abstract method class syntax.
Delegates in C#:
public delegate void DoSomethingDelegate(Object param1, Object param2);
...
//now assign some method to the function type variable (delegate)
DoSomethingDelegate f = DoSomething;
f(new Object(), new Object());
(another sample here
http://geekswithblogs.net/joycsharp/archive/2008/02/15/simple-c-delegate-sample.aspx)
One argument they put forward in Project Lambda docs:
Generic types are erased, which would expose additional places where
developers are exposed to erasure. For example, it would not be
possible to overload methods m(T->U) and m(X->Y), which would be
confusing.
section 2 in:
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-3.html
(The final lambda expressions syntax will be a bit different from the above document:
http://mail.openjdk.java.net/pipermail/lambda-dev/2011-September/003936.html)
(x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); }
All in all, my best understanding is that only a part of syntax stuff that could, actually will be used.
What Neal Gafter most likely meant was that not being able to use delegates will make standard APIs more difficult to adjust to functional style, rather than that javac/JVM update would be more difficult to be done.
If someone understands this better than me, I will be happy to read his account.
Goetz expands on the reasoning in State of the Lambda 4th ed.:
An alternative (or complementary) approach to function types,
suggested by some early proposals, would have been to introduce a new,
structural function type. A type like "function from a String and an
Object to an int" might be expressed as (String,Object)->int. This
idea was considered and rejected, at least for now, due to several
disadvantages:
It would add complexity to the type system and further mix structural and nominal types.
It would lead to a divergence of library styles—some libraries would continue to use callback interfaces, while others would use structural
function types.
The syntax could be unweildy, especially when checked exceptions were included.
It is unlikely that there would be a runtime representation for each distinct function type, meaning developers would be further exposed to
and limited by erasure. For example, it would not be possible (perhaps
surprisingly) to overload methods m(T->U) and m(X->Y).
So, we have instead chosen to take the path of "use what you
know"—since existing libraries use functional interfaces extensively,
we codify and leverage this pattern.
To illustrate, here are some of the functional interfaces in Java SE 7
that are well-suited for being used with the new language features;
the examples that follow illustrate the use of a few of them.
java.lang.Runnable
java.util.concurrent.Callable
java.util.Comparator
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener
...
Note that erasure is just one of the considerations. In general, the Java lambda approach goes in a different direction from Scala, not just on the typed question. It's very Java-centric.
Maybe because what you'd really want would be a type Function<R, P...>, which is parameterised with a return type and some sequence of parameter types. But because of erasure, you can't have a construct like P..., because it could only turn into Object[], which is too loose to be much use at runtime.
This is pure speculation. I am not a type theorist; i haven't even played one on TV.
I think what he means in that statement is that at runtime Java cannot tell the difference between these two function definitions:
void doIt(List<String> strings) {...}
void doIt(List<Integer> ints) {...}
Because at compile time, the information about what type of data the List contains is erased, so the runtime environment wouldn't be able to determine which function you wanted to call.
Trying to compile both of these methods in the same class will throw the following exception:
doIt(List<String>) clashes with doIt(List<Integer); both methods have the same erasure

Categories

Resources