I disagree that the C# example is contrived, having accidentally made the
mistake they show.

On Thu, Sep 15, 2011 at 9:37 AM, opinali <[email protected]> wrote:

> Oh got it. I agree that return/break/continue (the so-called non-local
> returns) are a problem, although they are only such a big problem if we
> don't want to improve the classfile/bytecode/VM specs to have a specialized
> mechanism for this in order to not depend on the exception hack.
> Unfortunately, too many Java language improvements are tainted by this
> criteria of desiring as few changes to the VM platform as possible.
>
> But I don't see this problem as a justification for the separate issue of
> mutable capture. We're talking about completely distinct features. Capturing
> mutable local vars has a trivial implementation (lifting the variable to a
> field of the closure object, visible both from the defining scope and from
> the closure code).
>
> I read the C# example, and it didn't impress me; it's not just contrived,
> it's a VERY contrived example. You can easily build such examples to show
> that every single feature of any language can be involved in some
> incorrect/confusing code. In the example, the bug is not caused only by
> mutable capture - it's mostly likely caused by programmer's failure to
> realize that the execution of the closure will be deferred. This is the most
> fundamental property of a closure if compared to a regular block or
> expression inside the containing method; developers can shoot themselves in
> the foot all day long if they fail to be aware of when the code of closures
> is actually executed, without even needing mutable capture. Taking a page
> from lambda-dev (from Neal Gafter IIRC), closures (including mutable
> capture) are an ages-old feature which use is time-proven by numerous
> languages.
>
> A+
> Osvaldo
>
>
> On Thursday, September 15, 2011 3:10:39 AM UTC-4, Ricky Clarkson wrote:
>
>> What I perhaps didn't make clear is that I'm talking about taking some
>> code that's part of a method, and then making it part of a lambda within
>> that method.
>>
>> E.g., in some imaginary syntax:
>>
>> void foo() {
>>   if (Math.random() < 0.5)
>>     return;
>>   System.out.println("Foo");
>> }
>>
>> void foo() {
>>   timeHowLongThisTakes( () => {
>>     if (Math.random() < 0.5)
>>       return;
>>   } );
>>   System.out.println("Foo");
>> }
>>
>> Return is one example; others are break, continue and throw.  The meaning
>> is not kept if you wrap that code into a new Runnable() { public void
>> run()... }
>>
>> Gafter's original, well thought-out, argument was that wrapping code in a
>> closure should not affect its meaning, which makes a lot of sense, but the
>> actual mechanisms needed to do that at least before engaging the VM team are
>> odd, it used exceptions under the hood to manage these things, and there
>> were objections to that.  And (answered) questions about what return; would
>> mean if the lambda were to be executed on a different thread to the
>> surrounding method.
>>
>> I think at this stage it makes sense to stick with a restricted lambda and
>> get that in stone.  The current proposal does not in any way preclude Oracle
>> from adding support for capturing mutable variables, a notation for outer
>> returns, enabling break and continue, and making throws able to be
>> transparent.
>>
>> Regarding mutable variables, I'm sure you read the passage I quoted from
>> the C# specification and can appreciate that it's not all roses without that
>> limitation.  It's not just theoretical, in my brief time on Freenode's
>> ##csharp I noticed it appeared fairly often.  Whether it was deliberate 14
>> years ago I don't think matters any longer.
>> --
>> Skype: ricky_clarkson
>>
>>
>> On Wed, Sep 14, 2011 at 11:12 PM, opinali <[email protected]> wrote:
>>
>>>  On Wednesday, September 14, 2011 9:15:30 PM UTC-4, Ricky Clarkson
>>> wrote:
>>>>
>>>> I think the problem is that whenever you start trying to make sure that
>>>> all code wrapped in a lambda behaves the same as code not wrapped in a
>>>> lambda (return, break, this, continue, throw all behaving the same way) you
>>>> get into odd territory and someone picks up on it and reacts.
>>>
>>>
>>> This seems to be mixing things. Code inside an inner class certainly
>>> behaves exactly like all other code; specifically, you can define mutable
>>> variables and you can assign to these variables. So the typesystem inside
>>> the "closure" is exactly the same. Which in this case, makes inner classes
>>> even more broken, it would be cleaner if inner classes had been designed as
>>> a pure-functional subset of the language that couldn't do destructive
>>> assignments at all.
>>>
>>> See Guy Steele's comments about inner classes: http://people.csail.**
>>> mit.edu/gregs/ll1-discuss-**archive-html/msg04044.html<http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg04044.html>
>>>  -
>>> Java was initially planned to have closures, including mutable capture, but
>>> that was cut from JDK 1.0 and when they introduced inner classes in 1.1, it
>>> didn't have mutable capture and the reason was just "users feared the
>>> performance cost" - maybe reasonable concern with JDK 1.0's VM with the
>>> crappiest GC ever, but an obsolete issue since HotSpot, not to mention that
>>> other language features already ignore any concerns (performance or other)
>>> of implicit allocations, like Steele points. Also, James Gosling referred to
>>> inner classes as an `"uncomfortable compromise ... that didn't really solve
>>> any problems": 
>>> http://blogs.**oracle.com/jag/entry/closures<http://blogs.oracle.com/jag/entry/closures>.
>>> And a third "father of Java", Bill Joy, also wanted full support for
>>> closures since day one: http://www.blinkenlights.**
>>> com/classiccmp/javaorigin.html<http://www.blinkenlights.com/classiccmp/javaorigin.html>
>>>
>>> TL;DR: The mutable capture limitation of inner classes was NOT introduced
>>> by design. Not one of the original Java designers are proud of inner
>>> classes. Any attempt to justify this limitation as something that makes
>>> sense with good language design principles, is rewriting history - "it's not
>>> a bug, it's a feature".
>>>
>>> A+
>>> Osvaldo
>>>
>>>
>>>
>>>>
>>>> Scala actually does some* of what Gafter's original proposal did
>>>> regarding control, and the reality is I've only ever noticed when I
>>>> explicitly tested it to see if I could observe a NonLocalReturnException.
>>>>  However, I don't think we're going to win that fight, and C#'s level of
>>>> lambda support really is a marked improvement over what we have in Java
>>>> today.
>>>>
>>>> * some, because Scala doesn't have continue or break.
>>>>
>>>> --
>>>> Skype: ricky_clarkson
>>>>
>>>>
>>>> On Wed, Sep 14, 2011 at 8:38 PM, opinali <[email protected]> wrote:
>>>>
>>>>>  Hi clay,
>>>>>
>>>>> Ok let's be more formal now. I agree with option A below (instead of
>>>>> B); "closure" is very well defined in numerous classic CS books as the
>>>>> pairing between a function and an environment that provides bindings to 
>>>>> its
>>>>> free variables. The concept comes from lambda calculus where functions can
>>>>> only exist in the form of functions, so I understand view B - but 
>>>>> practical
>>>>> programming languages are very distant from pure lambda calculus; only in
>>>>> the Lisp family (I think) they are really the same because functions are
>>>>> just sugar for a lambda - i.e. a function is a lambda that is bound by 
>>>>> some
>>>>> name to some environment. But there are many other languages, including
>>>>> Java, where this doesn't happen, unless you interpret the concept of
>>>>> "environment" as something more general, including the all scoping rules,
>>>>> classloaders, etc. IMHO this is going a bit too far, I'm happy with a
>>>>> definition of closures that does not depend from lambdas.
>>>>>
>>>>> Now back to my points 1/2, let's try to refine the discussion to its
>>>>> true essentials: the major point of debate is whether Java's closures 
>>>>> (with
>>>>> or without Java 8's lambdas) are "good enough". So let's try to define 
>>>>> what
>>>>> constitutes good enough. I am a strong advocate of very powerful 
>>>>> closures; I
>>>>> was rooting for BGGA with its non-local returns, control abstractions...,
>>>>> but I concede that these features are only necessary to extend Java's
>>>>> paradigm, allowing significant new idioms. But it's fair to require for
>>>>> "good enough", an implementation of closures that is at least sufficient 
>>>>> to
>>>>> get along with the *existing* language paradigm, idioms and other features
>>>>> (typesystem, OO model etc.) - anything better that that is a bonus. If we
>>>>> agree on this, then "good enough" boils down to orthogonality. And the
>>>>> current support for closures (without capture of mutable variables) is
>>>>> clearly NOT orthogonal, because destructive assignment is a HUGE part of 
>>>>> the
>>>>> Java language. No amount of fancy functional-esque frameworks or 
>>>>> conventions
>>>>> can change this simple fact. It's broken since JDK 1.1's introduction of
>>>>> inner classes, and it will be broken in Java 8's even with lambdas, nice
>>>>> syntax, and tons of new or retrofitted APIs to use closures/lambdas.
>>>>>
>>>>> A+
>>>>> Osvaldo
>>>>>
>>>>>
>>>>> On Tuesday, September 13, 2011 7:58:02 PM UTC-4, clay wrote:
>>>>>>
>>>>>> From the best I can gather, the principle disagreement is definitions.
>>>>>>
>>>>>> There are three views in this thread:
>>>>>>
>>>>>> A) Java has closures. Closures, by definition, do not necessarily
>>>>>> require lambdas or first class functions, which Java doesn't have.
>>>>>> B) Closures, by definition require lambdas and/or first class
>>>>>> functions, so since Java doesn't have those, it can't have closures.
>>>>>> C) Pure closures, by definition, don't limit you to accessing only
>>>>>> "final" variables, so the anonymous class functionality doesn't
>>>>>> qualify as a closure.
>>>>>>
>>>>>> Osvaldo,
>>>>>>
>>>>>> Regarding point #1: First, I think you mean anonymous classes, not
>>>>>> inner classes. Secondly, I'd stress that anonymous functions (lambdas)
>>>>>>
>>>>>> are a distinct feature from closures.  A language can have one feature
>>>>>>
>>>>>> but not the other. Java has closures, but not lambdas. And I can't
>>>>>> think of them off the top of my head, but I'm sure there are languages
>>>>>>
>>>>>> with lambdas that don't close over the defining environment, and
>>>>>> therefore don't have closures.
>>>>>>
>>>>>> Regarding point #2: I'm not sure what you are getting at here. Sure,
>>>>>> Java is behind the pack in terms of immutable programming and
>>>>>> functional programming support, but you can use third party libraries
>>>>>> like Functional Java and adopt that style as a programmer. Only a few
>>>>>> languages like Haskell really force those concepts on you and
>>>>>> guarantee safety from mutability issues. In Scala, immutable code and
>>>>>> functional programming still requires programmer compliance and it's
>>>>>> easy to write imperative mutable code. Regardless, this seems like a
>>>>>> tangential issue.
>>>>>>
>>>>>> Kevin,
>>>>>>
>>>>>> I'm not arguing that Java has closures because you can achieve the
>>>>>> same goals without real language level support. I'm arguing that
>>>>>> closures are inner functions/methods that can access variables from
>>>>>> the outer function/method scope, and the Java language syntax
>>>>>> completely supports that. You are claiming that closures require
>>>>>> lambdas by definition, and I disagree with you on that definition.
>>>>>> Java doesn't have lambdas. Sure, you can achieve similar results with
>>>>>> anonymous classes, but the Java language itself doesn't provide
>>>>>> lambdas.
>>>>>>
>>>>>  --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "The Java Posse" group.
>>>>> To view this discussion on the web visit https://groups.google.com/d/*
>>>>> *ms**g/javaposse/-/53VocU4KYT0J<https://groups.google.com/d/msg/javaposse/-/53VocU4KYT0J>
>>>>> .
>>>>>
>>>>> To post to this group, send email to [email protected].
>>>>> To unsubscribe from this group, send email to
>>>>> [email protected]**.
>>>>>
>>>>> For more options, visit this group at http://groups.google.com/**group
>>>>> **/javaposse?hl=en <http://groups.google.com/group/javaposse?hl=en>.
>>>>>
>>>>
>>>>  --
>>> You received this message because you are subscribed to the Google Groups
>>> "The Java Posse" group.
>>> To view this discussion on the web visit https://groups.google.com/d/**
>>> msg/javaposse/-/Fff1UZB3f5EJ<https://groups.google.com/d/msg/javaposse/-/Fff1UZB3f5EJ>
>>> .
>>>
>>> To post to this group, send email to [email protected].
>>> To unsubscribe from this group, send email to
>>> [email protected]**.
>>> For more options, visit this group at http://groups.google.com/**
>>> group/javaposse?hl=en <http://groups.google.com/group/javaposse?hl=en>.
>>>
>>
>>  --
> You received this message because you are subscribed to the Google Groups
> "The Java Posse" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/javaposse/-/W8qWzFi4XtoJ.
>
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/javaposse?hl=en.
>

-- 
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en.

Reply via email to