

"..best direction for evolving Java is to encourage a more functional style" - sadiq
http://mail.openjdk.java.net/pipermail/lambda-dev/2011-August/003877.html

======
extension
Can someone explain the dichotomy between lambdas-as-objects and whatever the
alternative is? If they aren't objects, would they be a primitive value with
no methods or superclass? What is the advantage of that?

EDIT: Ok, I think I'm starting to understand the issue. If lambdas are objects
then they have to be typed by their signature. It would have to be a
parameterized type i.e. generic. And because of type erasure, the call
signature of lambdas would only be known at compile time. So you can't check,
at runtime, that a lambda has a compatible signature. That does seem pretty
hairy to me.

And if they aren't objects, I guess their signatures would be tracked with
some sort of new parallel type system that could be better tailored for the
purpose. Is that it?

~~~
jawher
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.

~~~
masklinn
> C# has them, and so does Scala.

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.

~~~
jawher
Even Java has the Void type, meaning you can write:

    
    
        Function<Void>
    

It's a bit shady though as you still have to return a value from the body of
the method, and that value has to be null.

~~~
StrawberryFrog
That sort of this is also easy to do in C# or any strongly typed language.
Similar things in c# are the DBNull type which "Represents a nonexistent
value" from a database (<http://msdn.microsoft.com/en-
us/library/system.dbnull.aspx> ) and Type.Missing which "Represents a missing
value in the Type information"

------
Ygor
Which of the two approaches would you consider better for the JVM and/or .NET
as a platform:

1\. Make the most popular languages, c# and Java, more complex by adding more
features such as functional and dynamic support.

2\. Make the "core" languages simple and precise, and encourage the use of
other languages for adding more options and features to the platform.

Currently, for example, c# does support functional style programming, but
there is also f# which ships with VS2010. At first, it seams as if the
designers are not sure which of the two approaches to take. and just go both
ways. Java is a little behind, but that's why we have clojure and scala.

~~~
rlmw
Neither Java, nor c#, are simple. They're arguable less complex than things
like f# and scala, but its quite a lot about the question of familiarity.

If you're coming from an imperative, oop, background then these languages will
require more learning because you're not familiar with the concepts.

But a language like Java is huge by comparison with something like Javascript
or python. In terms of the size of grammar, the number of semantic rules
required for description, etc.

~~~
icey
If you take the entire corpus of knowledge required to use a language, I'd
argue that F# is less complex than C#.

It may seem like it's more complex if the user doesn't have a functional
background; but if the user is equally comfortable with both OOP and
Functional paradigms F# is the simpler, smaller, more regular language of the
two.

------
camo
until erasure is fixed, no new hacks\workarounds can be added.

unfortunately you can't build hacks on hacks on hacks...even as engineeringly
pleasing as some hacks might be.

imo, java needs to find some way of updating the vm.

~~~
extension
Priority: 4-Low <http://bugs.sun.com/view_bug.do?bug_id=5098163>

It's not that they can't update the VM, it's that they don't want to force a
painful migration to reified versions of libraries that aren't backwards
compatible. But I don't know why they can't just do what that last comment
said: extend the old interfaces for reification without breaking them, using
Object as the default type parameter.

~~~
camo
i think the last comment's suggestion wasn't acceptable because it will break
type safety for previously compiled code. perhaps this was too much to stomach
for those making the decision?

it would remain binary compatible tho, so it would seem to be a possible
solution.

for java to really advance forward it needs to be done in a manner where the
principal is the future, not the past. if this means rendering old code as
non-type-stafe then this is a small price for a whole new programming
paradigm, or even two.

i've struggled with generics since they were added and the problem is that all
the potential they propose is only possible if they're reified. as they stand
they are worthless and just move a cast from the value to the class but they
allude to far more, which is a rat hole.

java's had full backward compatibility for decades. code is a depreciating
asset and worth less with every year since compilation. it's an incumbent now,
slowing, even mutating, progress.

if some legacy code is so valuable, it should have earned its scars enough to
have type safety turned off.

------
masklinn
Erm... duh? Welcome to 30 years ago, first stop is Smalltalk?

------
drblast
Even though I have great fun tinkering with Java, I think it's is a dead-end.
Like C++, it exists in sort of a weird limbo between dynamic high level
languages and C/Assembly.

The advantages of the performance of imperative code that exist with C aren't
there, nor is the simple flexibility of Lisp or Python.

I attended a talk by James Gosling and he pretty much summed it up when he
said, "Java was an attempt to drag C++ programmers kicking and screaming
halfway to Common Lisp."

"Evolving" such a language into a more functional one, and doing it properly,
will require much more than an evolution. That would completely change the
language.

And you can still take advantage of functional concepts in Java as is. To me
it seems like static methods are underused, but if you eliminate most or all
of the member variables from your classes, you can code in a very functional
style in Java. It's not the prettiest solution, but neither is having little
bits of state everywhere at once.

~~~
PaulHoule
Common Lisp had safe memory references and garbage collection. It did have
CLOS, but I don't think many people used it. CLOS also was a very different
take on OO.

The core of Java is the OO programming model, and "good" Java programming
revolves around what works in that model.

Lately I've become a fan of "import static", which imports static functions
from another class. "import static java.lang.Math. _" is good to do if you
need to do a lot of math, for instance. "import static
com.example.mysystem.MyDSL._ " sets you up to use an internal DSL.

Faking Lambdas with objects is cumbersome but not difficult, and remember
there are many tricks like new ArrayMap<String,String>() {{ put("k1","v1");
put ("k2","v2") }} which let you build structures the way you would in
Javascript, Python, PHP, C# or whatever.

------
dpkendal
Prediction: within 5 years, the term "functional programming" will be almost
meaningless.

~~~
technomancy
"Horseless carriage".

"Webcomic".

"Cell phone".

~~~
dpkendal
I didn’t really mean in that sense, though that’s another possibility.

What I meant was that, when Java somehow becomes ‘functional’ (like _that_
transition can happen to an established language) it will be assumed that any
program written in this version is ‘functional,’ regardless of whether it
really is written in a functional style.

Either way, adding lambdas does not make you into an acceptable functional
language. Java is still not a language that Joel Spolsky won’t complain about
the teaching of in schools.

------
keeperofdakeys
So, Java will eventually have two different paradigms to code in. The saying
'do one thing and do it well' would be good to keep in mind here.

~~~
masklinn
> So, Java will eventually have two different paradigms to code in.

I don't think that's the case. Higher-order functions have been part of the OO
toolbox since the batch of OO languages has existed, generally under the label
"blocks" (indicating non-local returns separating them from the preexisting
"lambdas").

And I'd argue that a language without anonymous first-class function can not
be "truly" object-oriented, or at least not without significant syntactic
overhead.

To me, a core idea of OO is that objects are opaque boxes to which you "give
order" (that makes Erlang's processes excellent objects, by the way). But it
is very common that you need to customize the exact behavior in some way.

Without first-class functions, the choices are to either extract all relevant
data from the object, perform the operation yourself and (optionally) feed the
data back, low overhead but a far cry from object orientation; or to create a
new type holding all relevant customization information (that's the delegate
pattern), very high overhead but remains object oriented.

First-class functions in OO language act as very-low-overhead delegates (you
may still need full-blow delegates for complex customization, but single-
method delegates aren't needed anymore), and let language users avoid
imperative programming.

------
mayanksinghal
I actually like the OO paradigm much more than functional. It makes the code
much more readable! (I have no opinion on the comparative strengths though)

But I have only used a few languages - Scheme and C are horrible to use
(personal experience, yours might defer). Java and JavaScript have been
brilliant!

~~~
natesm
I don't really know Java, so this is made up Java/C#/something, but compare
these:

    
    
        List<int> mapped = new List<int>();
        for (int i = 0; i < list.count(); i++)
        {
            mapped[i] =  list[i] + 1;
        }
    

Or:

    
    
        List<int> mapped = list.map((x) => x + 1);
    

Which do you think is more elegant and readable? For a slightly more extreme
example, what if we want the numbers less than 100:

    
    
        List<int>filtered = new List<int>();
        for (int i = 0, j = 0; i < list.count(); i++)
        {
            if (list[i] < 100)
            {
                filtered[j] = list[i];
                j++;
            }
        }
    

Or this:

    
    
        List<int> filtered = list.filter((x) => x < 100);

~~~
jshen
I wrote a blog post with a nearly identical example.

[http://jaydonnell.com/blog/2011/08/07/is-your-idea-
clealry-e...](http://jaydonnell.com/blog/2011/08/07/is-your-idea-clealry-
expressed-in-your-code/)

The code gets nutty when you have to do multiple transforms on collections.
There are some libraries in Java which make it more bearable.

<http://code.google.com/p/lambdaj/>

    
    
        List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());

