31

I wonder what the technical implementation differences between C# and Scala are and how both solutions compare to the implementation ideas and concerns voiced in the email Peek Past lambda by Brian Goetz, sent to the mailing list of Project Lambda (JSR 335)?

From the email:

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".

and further:

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.

Conclusion:

Lambdas-are-functions opens doors. Lambdas-are-objects closes them.
We prefer to see those doors left open.

And some comment from a person on the Reddit thread says:

I actually e-mailed Neal Gafter about this and to my limited understanding of his explaination C# and the current Java design are quite similar in that Delegates are actually objects and not function types. It seems like he believes that Java should learn from the disadvantages of C#'s lambdas and avoid them (much like C# learned from Java's disadvantages and avoided them in the beginning).

Why does the "Lambdas-are-functions" approach enable more opportunities in the future than "Lambdas-are-objects"? Can someone explain what differences exist and how they would influence how code would be written?

Seeing that things in Scala "just work", I keep thinking that I'm missing something about the approaches taken/proposed in C#/Java (8), probably it is related to concerns about backward-compatibility?

3
  • 1
    This is interesting. Given that Javas type system has no concept of functions as of now, this would mean one had to introduce this first. It could be possible that the language would become too complex with this.
    – Ingo
    Commented Aug 19, 2011 at 12:22
  • Aren't functions should instances of some interface? What's so special about them?
    – soc
    Commented Aug 19, 2011 at 12:46
  • Lisp / Scheme / Clojure can model objects while Java/C# cannot model arbitrary nesting of functions. Python seems to have the best of both worlds, however.
    – Job
    Commented Aug 20, 2011 at 12:33

3 Answers 3

16

I think the discussion regarding objects vs. functions is a red herring. If the question is, "Is a lambda a function or an object?" the answer should be yes.

That's the point of first-class functions: they aren't treated differently than any other type. Java already manages to mostly ignore the differences between Object and primitive types (and Scala does even better), so whether a lambda is a subclass of Object or is a new primitive type or something else isn't really important for the language. What is important is that you can put your lambdas in collections, pass them around to be called, call them, and do anything else you might want to do with either an object or a method.

Scala accomplishes this by using a wrapper object that has a method called apply which can be invoked with just (), making it look just like a method call. This works splendidly; much of the time you don't need to even care whether you have a method or are calling the apply of a function object.

0
9

From what I understand, it's more about how the lambdas are considered at the primary language level. As the email says,

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 think that sums up your question quite nicely. If you declare that "lambdas are objects", then they're just an object of a particular class and you're stuck with that. On the other hand, if you declare "lambdas are functions", then semantically you have a much richer playing field. Java 1.7 might compile them down to objects, so they're practically identical at that point.

But Java 1.8, or 1.9, might bring in changes to the language (such as reified structural types) than enable functions to be used in much more flexible ways. If "lambdas were objects", these changes wouldn't be backwards compatible and you'd have to introduce a new concept altogther, so as not to break people's existing code. But if javac was just quietly converting lambdas to objects behind the scenes, the new javac can convert them to whatever it wants, so long as the semantics still hold.

5
  • lamdas in C# != from delegates. The compiler has the option of compiling them to either delgates or Expression trees. both are indeed object graphs but they are not compiled to a "particular class" nor even a class of a particular inheritance tree
    – Rune FS
    Commented Aug 19, 2011 at 12:34
  • If I understand correctly, then compiling the lambda down into an inner class of the object its associated with ties it to that object, so in the future if Java were to introduce higher-order functions (functions at the same level of objects) then you could not use the inner-class implementation, and there would be an inconsistency. I don't think Java will have higher-order functions anytime soon.
    – mwolfetech
    Commented Aug 19, 2011 at 12:52
  • @mwolfetech: As far as I know, they are already planned for Java 8 with defender methods. They want to add things like foreach, map, filter to collections.
    – soc
    Commented Aug 19, 2011 at 12:54
  • @soc Good point, its hard to keep up with the number of JSRs and whether they actually will complete and make a target version of the JDK. It looks like defender methods might be part of the same JSR. With regards to this JSR, I found Brian Goetz's State of the Lambda post helpful-- explains SAM types and the current thoughts for implementing lambda expressions.
    – mwolfetech
    Commented Aug 19, 2011 at 13:42
  • "current thoughts" mhhh, isn't that post from 2010 obsolete now?
    – soc
    Commented Aug 19, 2011 at 15:28
5

Mostly, he just doesn't want to commit too soon to something. I don't see any reason beyond the erasure one he presented, but that is a very strong reason indeed.

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.

Consider these methods in Scala's Regex:

def replaceAllIn (target: CharSequence, replacer: (Match) ⇒ String): String
def replaceSomeIn (target: CharSequence, replacer: (Match) ⇒ Option[String]): String

It would be simpler if they were simply this:

def replace (target: CharSequence, replacer: (Match) ⇒ String): String
def replace (target: CharSequence, replacer: (Match) ⇒ Option[String]): String

Unfortunately, that is not possible, because those two functions are identical under erasure. But, fine, these function do somewhat different things, so a different name might is fair enough.

However, a Match is something very useful, but most of the time you want either the matched String or the list of subgroups. We would like to have this:

def replaceAllIn (target: CharSequence, replacer: (String) ⇒ String): String
def replaceAllIn (target: CharSequence, replacer: (Seq[String]) ⇒ String): String
def replaceAllIn (target: CharSequence, replacer: (Match) ⇒ String): String

Not possible, because of erasure. I chose this particular example because I was directly involved with it, but I have seen at least half a dozen questions on Stack Overflow, where people ask why an overload is illegal, caused by this exact issue.

And, then, consider that Scala's pattern matching and Java's instanceof are effectively useless because of erasure.

I think it is fair to delay function types until this issue is dealt with. After all, there are plenty languages that have it on the JVM, and it is not like Java is a quickly evolving language.

5
  • Well, if type erasure is the only problem they have, what do they plan to do? Breaking every code on this planet was ruled a non-option for Java 5 already ...
    – soc
    Commented Aug 20, 2011 at 9:42
  • @soc I am so glad I'm not in their shoes! But that was Sun, this is Oracle. Oracle has never had any compunction in making breaking changes between major -- and even minor -- versions of its main product. Commented Aug 20, 2011 at 19:26
  • Maybe they should change the name of the language and start developing a new language, dropping backward compatibility. So one would have the benefits of a new language without the need of playing around with an older and well-established language. After all, this is what Scala and Clojure did.
    – Giorgio
    Commented May 2, 2012 at 6:11
  • @Giorgio That would be a bit pointless. Well, some of the people who are responsible for what Java is today did that, but, as you said, there are alternatives. But the people responsible for Java have to improve Java itself -- they are responsible for it, after all. The only alternative is to simply drop Java, and forego all benefits that result from controlling it. Commented May 2, 2012 at 18:56
  • @Daniel C. Sobral: IMO a programming language is a bit like a piece of software: at the beginning it can be clean and well-design but the more you play with it the more it gets messy. So I think it would be in the interest of developers to freeze Java as a language and concentrate the development on (1) creating new libraries or improving existing ones, (2) improving the JVM (if possible), (3) developing new languages. But as you said there are people who are responsible for Java and who want to keep selling upgrades. So they are going to extend it to keep it "cool". Just my 2 cents.
    – Giorgio
    Commented May 2, 2012 at 19:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.