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?
Lambdas as objects vs lambdas as higher order functions is primarily about state. Lambdas make poor objects, especially in the absence of pattern matching; as soon as your API needs more than one method signature, you need to overload things, and you can get caught up in reimplementing the equivalent of Smalltalk message-send. If you want to make an object, you're usually better off using an object (or anonymous class etc.) when the language provides it.
Using lambdas to parameterize algorithms gives you more power, and if the algorithm can assume that the lambda passed in is stateless, it can do things like memoize (cache) calls to it to further optimize the algorithm. Lambdas as higher order functions help you make more composable libraries, because often the glue needed to join one bit of code to another is just a transformation of the return value of one function to the parameter type of another. That's an ideal application for a lambda.
For example, take sorting a list of objects by a particular attribute. A sort routine can be written that takes in a comparison routine, and that comparison routine can do the work of selecting the attributes and comparing them. But chances are you're comparing things like numbers and strings; you'll have other library code that can do those comparisons. So what you actually want, most of the time, is just the bare minimum: a lambda that, given the object to be sorted, returns the attribute to sort by. That's how the Sort routine works in .NET's LINQ, for example: myList.Sort(x => x.Name) will return a sorted sequence of the contents of myList in the order of x.Name property or field. The lambda here is extremely simple and syntactically light, and that's what makes the pattern work. Above all, the lambda isn't really acting like an object.
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.
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:
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.
C#'s type system is a bit messy over there. Besides Func<T> and Action<T>, there's also Predicate<T> , which works the same as Func<T, bool> except for being an entirely different type that's non-trivial to cast to Func<T, bool>. And the whole lot look a lot like delegates.
If they were all just Func<T> (or aliases for that, or wrappers over that when multicast is really needed), it would be a lot simpler.
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"
Depends how much of your language happens at runtime. In very statically typed languages such as Haskell, type erasure works just fine (that's what GHC does), though it does give the impression of taking more namespace surface when you need generic type varargs (e.g. you can have `Foo<T>` and `Foo<T, U>` when your generic types are reified, if they're erased you'll need `Foo<T>` and `Foo1<T, U>`, there are two types in either case, but reified generics give the impression of a single type with a variable number of type arguments).
Erased generics are a bad idea when your type system is full of holes (easy to bypass) and lots happen at runtime, as is the case in Java.
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.
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.
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.
Yep, using the word simple to describe those languages is not really appropriate.
What I was getting at would be more in the lines of "confined to a single paradigm and style". And again, not saying either of the two mentioned are. It is more a question of future orientation and concept.
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.
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.
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.
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.
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.
> 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.
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!
Using objects and a functional style aren't mutually exclusive. Use objects for encapsulation and abstraction and use a functional style for clarity, conciseness, expressiveness and less mutating state.
I think it's a fair statement to prefer the OO paradigm, and indeed it is good for a whole load of things in programming. Nonetheless, adding lambdas to Java should give plenty of easy wins even if you prefer your code to be broadly OO.
Look through your for and foreach loops. I bet a lot of them would be neater, more readable, and better express intent as some combination of map and filter.
Count how many classes you have with only one method and no data in them. Would you really make separate classes for all of those if you had the option to pass them around as functions?
I would also like to see something like the yield and yield! (yield every item in this collection) keywords, because those can give readability improvements in a lot of places too, but one step at a time.
Agreed, may be I have seen only bad code. I am still a student and the only industry code that I have seen was in Java. Much of the rest of code, that I saw in academia, was functional in nature and written in C.
I have observed that (may be due to the lack of a review system in academia) the code was much harder to read. With C, the problem was even worse due to extensive use of global variables and poor structuring of code. Java, on the other hand, has two benefits: firstly, it's really strict and verbose. So even if a person is practicing bad coding, it is still harder to make truly unreadable code. Secondly, the IDE are more powerful, makes coding as well as code browsing easier.
My prejudice might be against C and in favor of Java. And i just related it to functional and OO respectively. But I would like to add that modifying objects still somehow seem more intuitive to me - probably because I had a better Java teacher than a C teacher. :)
I think you might be misunderstanding what "functional" means. C is typically considered a procedural and not functional language, even though you do define everything in functions.
Functional programming refers to languages (like scheme and Haskell, and also Ruby and Python) where a function is no different than any other object in memory (like int, char, etc.). It can be returned as a value and passed as a parameter. A function can take functions as arguments and return another function as a result, kind of like taking the derivative or integral in math. (Something like this can be done in C with function pointers, but it's ugly.) Moreover, it's possible to define an "anonymous function", or "lambda". This is essentially an expression that evaluates to a function without a name, the same way you can type (x * y * z) and have it evaluate to a number without having to store it in a named variable first.
Also, you ideally want to define "pure functions", which means functions that return the same value for the same inputs no matter when you call them. These are much easier to debug than code that depends on outside conditions.
When you wrap your head around functional programming, it is actually a lot easier and more sensible in many cases than OOP. Of course, OO is still ideal in a lot of situations, which is why many languages (Python, Ruby most notably) combine the two.
(if you've been in academia, Mathematica is an example of a functional language.)
I didn't downvote. Don't sweat the downvotes. Sometime people just hit the wrong button. Sometimes they don't agree. If you worry about being popular on HN ...
Anyway.
It might be harder to read because you already know Java. Javascript has some horrible warts (IMO), and CoffeeScript fixes.
Also, Javascript is usually targeting the DOM, which is often ugly, especially if you are trying to include compatibility stuff. The DOM is basically a GUI, and GUI code can be rank ugly. Yes, it is hard to read (and learn) HTML, CSS, DOM, HTTP, and Javascript all at once, which is what real Javascript often involves.
Yes, and to add on that, I think for JS there is a lot of ugly code out there on the web. I have actually used them a lot before watching Crockford video's and I found them quite late!
BTW, are there any other resources similar to these videos? (Or, to put it differently, is Douglas Crockford the authority for JS?)
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?