From rssh at gradsoft.com.ua Wed Apr 1 00:16:19 2009 From: rssh at gradsoft.com.ua (rssh at gradsoft.com.ua) Date: Wed, 1 Apr 2009 10:16:19 +0300 (EEST) Subject: PROPOSAL: Templated Construction Expressions (i.e., Expressions Embedded in Strings) In-Reply-To: References: <3dd3f56a0903181505m517125a0w30f0aa540d1d038b@mail.gmail.com> <977c14e250a47d19b21f818f9aceb1aa.squirrel@wmail.gradsoft.ua> <7D2077BFF677D2429DDDEE095D9A48AC105DFB8D@osiris2.e-spirit.de> <9EA33E4A-C6EB-4F54-93E5-0E06FBD1876F@sun.com> Message-ID: > > On Mar 30, 2009, at 10:37 PM, rssh at gradsoft.com.ua wrote: > >>> On Mar 20, 2009, at 1:50 PM, John Rose wrote: >>> >> 3. COMPABILITY - this breaks all code with use $ in string literals. >> (Or I >> read something incorrectly ?) So better prefix such string with >> something. (may be yet one '$' or '@' ?) > > You read incorrectly. Template constructor expressions are distinct > from string literals. They are prefixed with the token "new". > Thanks, I reread you proposal and see that I missed too many during first reading. With explicit compile, I see that - we already have analogical JSR223 mechanism in language, which would be nice to reuse. >> 4. Why just not call this parser from some method ? I. e. what >> arguments >> for including string templates in language itself, instead library >> call ? > > The usual: Sugar like that can help API designers build APIs whose > code is more maintainable: Less noisy. Template-based systems are > popular for a reason. > This would be difference between new "template-text" and new MyCompiler("template-text") // i. e. main magic is in assigned template-expression to appendable. Thanks, now I understand. Hope will be change implement this in (E x: x>=7): Java x > -- John > From Ulf.Zibis at gmx.de Wed Apr 1 01:39:23 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Wed, 01 Apr 2009 10:39:23 +0200 Subject: Proposal and updates OVERSEEN Message-ID: <49D3283B.4040709@gmx.de> Hi Joe, in the last update of your blog, you have overseen my proposal: http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001163.html and it's update: Extend switch .. case statement for all types and simple expressions Also you've overseen this update: Simply implicit method invocation chaining Hopefully you will update your blog :-) -Ulf From tim.lebedkov at googlemail.com Wed Apr 1 02:00:06 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Wed, 1 Apr 2009 11:00:06 +0200 Subject: PROPOSAL: 'final' without explicit type (update) In-Reply-To: <28bca0ff0903310658k15b0c9abk45270080ab7cf7af@mail.gmail.com> References: <28bca0ff0903301426o7449e309t9de2e43743593ea6@mail.gmail.com> <28bca0ff0903301609y10c30815ice919d750f523745@mail.gmail.com> <28bca0ff0903302340s3aa480a4h3f675ca5e1a00741@mail.gmail.com> <28bca0ff0903310658k15b0c9abk45270080ab7cf7af@mail.gmail.com> Message-ID: Hello Marek, now it's more clear to me why you use 'final'. Thanks Tim On Tue, Mar 31, 2009 at 3:58 PM, Marek Kozie? wrote: > W dniu 31 marca 2009 15:43 u?ytkownik Tim Lebedkov > napisa?: >> Hello Marek, >> >> my proposal (http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001055.html) >> is very similar to yours (it just uses 'auto' instead of 'final'). >> >> Does yours declare variables as final (I mean here 'constant') only >> because you try to avoid introducing a new keyword? Or is there >> another motivation? >> >> Tim >> > > First of all I want Java to have clear separation on variables and values. > And then: > - variables should have explicit type. > - values should have clear context; > > While now people use variables even if they need value, it's because > cost using value is higher than using variable. This provide worse > code, more bugs, and provoke reusing variables. > > > -- > Pozdrowionka. / Regards. > Lasu aka Marek Kozie? > > http://lasu2string.blogspot.com/ > From tim.lebedkov at googlemail.com Wed Apr 1 02:02:53 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Wed, 1 Apr 2009 11:02:53 +0200 Subject: PROPOSAL: 'final' without explicit type (update) In-Reply-To: References: <28bca0ff0903301426o7449e309t9de2e43743593ea6@mail.gmail.com> <28bca0ff0903301609y10c30815ice919d750f523745@mail.gmail.com> <28bca0ff0903302340s3aa480a4h3f675ca5e1a00741@mail.gmail.com> Message-ID: Hello Reinier, 2009/3/31 Reinier Zwitserloot : > FWIW, I'm -strongly- in favour of implicit typing for final local method > variables, and opposed to extending this for non-finals, not just because > its hard to come up with a syntax for it, due to there being no readily > available keywords or operators to do it with. := comes to mind, but that's > about it. > > NB2: If you want to push forward with this proposal anyway, I strongly > suggest you rewrite it to this, which would be far more backwards > compatible: > > foo := expression; > > instead of: > > auto foo = expression; Thank you for the suggestion, but I think 'auto' is better and fits better in the current language. Regards --Tim From Ulf.Zibis at gmx.de Wed Apr 1 02:17:30 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Wed, 01 Apr 2009 11:17:30 +0200 Subject: Extend switch .. case statement for all types and simple expressions In-Reply-To: <49D14427.5070105@gmx.de> References: <49D14427.5070105@gmx.de> Message-ID: <49D33129.2090600@gmx.de> I would like to add, that the MAJOR ADVANTAGE of my proposal is, that the numerous grades/levels of this proposal could be implemented step by step, depending on the complexity of changes, which could be done for JDK 7. More sophisticated grades/levels could be seamlessly added later. This would be impossible, if the concurring syntax of "Strings in switch", which only compares for equality, comes to account. Also Multiple switch expressions and case ranges could seamlessly be integrated in my proposal. As I argued more detailed before, default semantic of "switch..case" should stay on determining the cases by IDENTITY. Strings, which are equal, could simply be made identical by String#intern(). Example: switch (myStringFromElsewere.intern()) { case STRING1 : ...; // all constants are interned by definition case STRING2 : ...; // " " case "foo" : ...; // automatically interned case "bar" : ...; // " " ... } -Ulf Am 31.03.2009 00:13, Ulf Zibis schrieb: > AUTHOR(S): Ulf Zibis, Cologne, Germany > > OVERVIEW > FEATURE SUMMARY: Extend switch .. case statement for all types and simple expressions. > MAJOR ADVANTAGE: > - Increases readability of source in concurrence to if .. else if .. else syntax. > - Sophisticated jumps. > - maybe in some cases javac and hotspot has chance to compute better optimized code. > MAJOR BENEFIT: > Stop some programmers escaping to some modern scripting language. > MAJOR DISADVANTAGE: > Programmers from other languages, especially C, may be confused about such rich syntax. > > EXAMPLES > SIMPLE EXAMPLE: > (1): > switch( myObject) { > case CONSTANT1 : doSomething(); break; > case CONSTANT2 : doSomethingElse(); break; > default : doSomethingDefault(); > } > (2): > switch( myString) { > case equals("red") : stop(); break; > case equals("green") : go(); break; > default : openYourEyesForCrossingTraffic(); > } > (3): > switch( myString) { > case equalsIgnoreCase("RED") : sureStop(); break; > case equalsIgnoreCase("GREEN") : sureGo(); break; > default : beAwareOfPoliceWachtingYou(); > } > > ADVANCED EXAMPLE: > (4): > switch( primitiveInt) { > case == 10 : doOnlyIf10(); // alternative syntax for 'case 10:' > case < 10 : > case >= 20 : break; > default : doOnlyInRange(); > } > (5): > switch( primitiveInt) { > case (>= 10 && < 20) : doOnlyInRange(); > default : throw new Exception("Out of range"); > } > (6): > switch( myString) { > case contains("foo") : doSomething(); break; > case regionMatches(true, 2, otherString, 4, 6) : doSomethingElse(); break; > default : doSomethingDefault(); > } > (7): > switch( myString.equals()) { // alternative: myString.equals(..) > case "foo" : foo(); break; > case "bar" : bar(); break; > default : dontCare(); > } > (8): > switch( className.startsWith("String", ..)) { // alternative: className.startsWith("String", ?) > case 0 : doForSimpleName(); break; > case 9 : doForFullName(); break; > default : canNotDecide(); > } > (9): > switch( anyObjectOrPrimitive instanceof) { // note, that casting is solved implicit > case boolean, byte, ... float : break; // Don't do anything > case double : forDouble(anyObjectOrPrimitive); > case HashMap : > case TreeMap : forPlattformMap(anyObjectOrPrimitive); break; > case Map : forOtherMap(anyObjectOrPrimitive); break; > default : forObject(anyObjectOrPrimitive); > } > (10): (minimizee chance for NPE) > switch( .equals(myString)) { // alternative: ?.equals(myString) > case "foo" : foo(); break; > case "bar" : bar(); break; > default : dontCare(); > } > (11): > switch( some_lethargic_function_we_cant_call_much().equals(..) ) { > case "this": > case "that": this_or_that(); break; > case "bigjump": big(); // fall > case "jump": jump(); break; > case "secondlastchance": > case "lastchance": last_chance(); break; > default: do_default(); > } > .. as replacement for: > String sSomeString = some_lethargic_function_we_cant_call_much(); > if( sSomeString.equals( "this" ) || sSomeString.equals( "that" ) ) > this_or_that(); > else if( sSomeString.equals( "jump" ) || sSomeString.equals( "bigjump" ) ) > { > if( sSomeString.equals( "bigjump" ) ) > big(); > jump(); > } else if( sSomeString.equals( "secondlastchance" ) || > sSomeString.equals( "lastchance" ) ) > { > last_chance(); > } else do_default(); > > ALTERNATIVES: > (12): > switch( myString) { // note the '.', I personally would prefer this alternative! > case .equals("red") : stop(); break; > case .equals("green") : go(); break; > default : openYourEyesForCrossingTraffic(); > } > (13): > switch( primitiveInt) { // note the '.' > case (. >= 10 && . < 20) : doOnlyInRange(); > // case (? >= 10 && ? < 20) : doOnlyInRange(); // alternative > default : throw new Exception("Out of range"); > } > > > DETAILS > SPECIFICATION: > The new syntax should be interpreted as > switch ( leftExpressionPart ) { > case rightExpressionPart1 : > case rightExpressionPart2 : > ... > default : > } > The result of entire expression should be boolean type. > There is shortcut for: > leftExpressionPart: intVariable > rightExpressionPart: == intLiteral > (the '==' could be ommitted.) > > COMPILATION: > Compiler could first pre-compile to appropriate if..then..else syntax. > Bytecode would not be affected, but in special cases it could be more compact, if noted > pre-compilation would be replaced by sophisticated optimization. > TESTING: > Compiler byte-code results for new syntax should be same than from equivalent hand-coded legacy > if..then..else syntax > . Exception: sophisticated optimization. > LIBRARY SUPPORT: No supporting libraries are needed for the feature? > REFLECTIVE APIS: There should not be any affection to reflection API. > OTHER CHANGES: No. > MIGRATION: > No refactoring is needed to stay compatible. > > COMPATIBILITY > BREAKING CHANGES: > No previously valid programs are now invalid. > ... but ATTENTION: > If proposals from some other guys regarding "Strings in switch" would be taken into JDK 7, there > won't be any compatible way to implement my more general proposal in future version of JDK !!! > --> So switch .. case statement should compare for IDENTITY if not syntactically determined otherwise. > --> compare for EQUALITY would also break semantic of existing switch .. case statement. > Another reason, why I'm against comparing for equality by default syntax, is, that it is good > practice to use String constants instead of widely spreaded String literals with same signature for > numerous reasons (performance, error prone, ...). The "only-for-String" syntax would lead > programmers to stay on widely spreaded String literals of same value. > If constant is not available for switch variable (e.g. if read from stream), variable could be > internalized before, so it's instance becomes identical to the existing constant. > ===>> If just "Strings in switch" is taken over for JDK 7, there is NO NEED, to compare for equality. > EXISTING PROGRAMS: > Source and class files of earlier platform versions interact with the feature without any notice. > > REFERENCES > http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000001.html > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000213.html > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000855.html > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001089.html > http://forums.java.net/jive/thread.jspa?messageID=27781沅 > http://forums.java.net/jive/thread.jspa?messageID=15769㶙 > http://forums.java.net/jive/thread.jspa?messageID=27773汽 > http://forums.java.net/jive/thread.jspa?messageID=11393ⲁ > http://lasu2string.blogspot.com/2008/12/string-switch-small-language-changes-on.html > EXISTING BUGS: > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5012262 > URL FOR PROTOTYPE (optional): > > > > > > > > From jl0235 at yahoo.com Wed Apr 1 06:21:39 2009 From: jl0235 at yahoo.com (james lowden) Date: Wed, 1 Apr 2009 06:21:39 -0700 (PDT) Subject: Opportunity Cost and Proposal Selection In-Reply-To: <49D2CA2F.1040401@sun.com> Message-ID: <751882.88756.qm@web63706.mail.re1.yahoo.com> Joe- I noticed that the version of the "large arrays" linked from your blog is the older (and messier) one; I updated it to this one: http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000869.html --- On Tue, 3/31/09, Joe Darcy wrote: > From: Joe Darcy > Subject: Opportunity Cost and Proposal Selection > To: "coin-dev at openjdk.java.net" > Date: Tuesday, March 31, 2009, 8:58 PM > Hello. > > There has been some traffic on the list about criteria for > proposal > selection (and non-selection) and I wanted to discuss that > briefly. > > First, a reminder from some earlier blog entries describing > the context > for Project Coin: > > "Especially with the maturity of the Java platform, > the onus is on the > proposer to convince that a language change should go in; > the onus is > not to prove the change should stay out." > http://blogs.sun.com/darcy/entry/criteria_for_desirable_small_language > December 23, 2008 > > "Given the rough timeline for JDK 7 and other on-going > efforts to change > the language, such as modules and annotations on types, > only a limited > number of small changes can be considered for JDK 7." > http://blogs.sun.com/darcy/entry/guidance_measure_language_change_size > December 11, 2008 > > With nearly 70 proposals submitted to the mailing list and > the Sun bug > database having well over 100 open "requests for > enhancements" (rfe's) > for the language, the large majority of those proposals and > rfe's will > *not* be included in JDK 7 as part of Project Coin or any > other effort. > > Project Coin will be limited to around 5 proposals total. > That's it. > > Therefore for Project Coin, in addition to determining > whether a > proposal to change the language is in and of itself > appropriate, a > determination also has to be made as to whether the change > is more > compelling than all but four or so other proposals. > > In economic terms, there an an opportunity cost in the > proposal > selection; that is, because of finite resources, choosing > to have a > particular proposal in the platform removes the opportunity > to do other > proposals. > > There will be good, compelling proposals that would improve > the language > *not* selected for Project Coin because there are a full > set of better, > more compelling proposals that are more useful to include > instead. > > Having available prototypes for proposals, running the > existing tests, > and writing new tests can only better inform the > forthcoming proposal > evaluation and selection. > > -Joe From glenn.a.marshall at gmail.com Wed Apr 1 07:12:40 2009 From: glenn.a.marshall at gmail.com (Glenn A. Marshall) Date: Wed, 1 Apr 2009 10:12:40 -0400 Subject: PROPOSAL: open and close brace optional for single statement try, catch, finally, method declaration In-Reply-To: <15e8b9d20903310751m2da11e10q97ea59c4ffed1bd2@mail.gmail.com> References: <49d02e12.18038e0a.6c4e.ffffa859@mx.google.com> <980366fa0903300445y6727dfaehc885c184d0dbe2c6@mail.gmail.com> <49D0C82D.1000208@sun.com> <980366fa0903310522u31ac7641r6a1554c188122175@mail.gmail.com> <15e8b9d20903310751m2da11e10q97ea59c4ffed1bd2@mail.gmail.com> Message-ID: <980366fa0904010712r5ce024c6xaf0185cf923dc068@mail.gmail.com> I understand that the grammar to handle this, if it was implemented in the obvious way (analogous to the dangling else) is hackish and thus not preferred. I sympathize and agree with this. I agree that this increases the effort/cost to implement this proposal, as well as make the grammar more hackish on an ongoing basis. Part of the assessment is to consider the cost, thus this is a relevant point. This proposal is still in an early state, and does not have an prototype implementation, nor a proposed grammar, both of which would reduce the cost to implement this proposal. I understand that some implementation questions will be resolved if the grammar component of the implementation was available, and it was unambiguous, from a grammar perspective. But you seem to be saying something else - that, conceptually, from a code perspective this proposal isn't clear. Can you elaborate please? I believe the code snippet you originally provided is handled. Tom: you seemed to be saying that you thought this was clear, originally, then later you also raised questions - have your questions been answered? On Tue, Mar 31, 2009 at 10:51 AM, Neal Gafter wrote: > On Tue, Mar 31, 2009 at 5:22 AM, Glenn A. Marshall > wrote: > > Indeed, the grammar would change. It was my hope that this proposal was > > sufficiently detailed that the grammar changes needed would be clear, > > conceptually. Are they? > > Not to me. Seeing the (unambiguous) grammar for your proposal would > clear up a bunch of questions. > From glenn.a.marshall at gmail.com Wed Apr 1 07:33:35 2009 From: glenn.a.marshall at gmail.com (Glenn A. Marshall) Date: Wed, 1 Apr 2009 10:33:35 -0400 Subject: Opportunity Cost and Proposal Selection Message-ID: <980366fa0904010733o5655fe5di10aa2c44883f7a6e@mail.gmail.com> Will the details of the proposal evaluations be published? The thinking here is that for proposals that almost made the cut, perhaps the evaluations would reveal where a bit more work might push them over the line for the next round - increase benefit/decrease cost. This is assuming there will be a next round. Any thoughts on round II? It would seem to be worth considering, given the level of interest. It would, of course, have to wait until Java 8, but why not start early? Surely you're busy with round I for now, but perhaps there could be a parallel effort, with the initial effort primarily around email. thanks for doing all of this, Glenn From neal at gafter.com Wed Apr 1 07:39:57 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 1 Apr 2009 07:39:57 -0700 Subject: PROPOSAL: open and close brace optional for single statement try, catch, finally, method declaration In-Reply-To: <980366fa0904010712r5ce024c6xaf0185cf923dc068@mail.gmail.com> References: <49d02e12.18038e0a.6c4e.ffffa859@mx.google.com> <980366fa0903300445y6727dfaehc885c184d0dbe2c6@mail.gmail.com> <49D0C82D.1000208@sun.com> <980366fa0903310522u31ac7641r6a1554c188122175@mail.gmail.com> <15e8b9d20903310751m2da11e10q97ea59c4ffed1bd2@mail.gmail.com> <980366fa0904010712r5ce024c6xaf0185cf923dc068@mail.gmail.com> Message-ID: <15e8b9d20904010739w3d877199k2846e84cb7cb47b@mail.gmail.com> On Wed, Apr 1, 2009 at 7:12 AM, Glenn A. Marshall wrote: > But you seem to be saying something else - that, conceptually, from a code > perspective this proposal isn't clear.? Can you elaborate please?? I believe > the code snippet you originally provided is handled. The usual technique for handling the dangling else problem is to rewrite the grammar so that it is no longer ambiguous. In other words, programs that under an ambiguous grammar would have more than one interpretation will, under the rewritten grammar, get a single interpretation. I gave an example that is ambiguous in your proposal. Instead of suggesting that it would be handled in one way or another, you said that it would be illegal. That's not the same solution normally applied to the dangling-else problem. A more precise specification in the form of a grammar would help us better understand what you have in mind. However, I believe the question is moot because I don't believe this proposal has any chance of being considered. Besides lacking a specification, it doesn't address a common pain point for Java programmers or add to the expressive power of the language. From fw at deneb.enyo.de Wed Apr 1 08:56:27 2009 From: fw at deneb.enyo.de (Florian Weimer) Date: Wed, 01 Apr 2009 17:56:27 +0200 Subject: PROPOSAL: 'final' without explicit type References: <28bca0ff0903261305x2de00436r5ca8183fe01578d4@mail.gmail.com> <87fxgwzfew.fsf@mid.deneb.enyo.de> <28bca0ff0903291422s77f11c44j4ddf6ea45ec0b669@mail.gmail.com> Message-ID: <87zlf0pduc.fsf@mid.deneb.enyo.de> * Marek Kozie?: > void noInterection(T t,K k){ > if (boo)t=k; // Type mismatch: cannot convert from K to T > ... > } The assignment is not type-safe anyway, as the following modification shows: T noInterection(T t,K k){ if (boo)t=k; // Type mismatch: cannot convert from K to T return t; } This would allow to convert values of any type which implements I1 and I2 to any other type which implements the two interfaces, which is clearly bogus. Consequently, I think your snippet doesn't show what you claim. From alexandre.makarenko at free.fr Wed Apr 1 10:16:54 2009 From: alexandre.makarenko at free.fr (alexandre.makarenko at free.fr) Date: Wed, 1 Apr 2009 19:16:54 +0200 (CEST) Subject: Naked dot - accessing object fields through unqualified "." [C1] In-Reply-To: <28bca0ff0903310631o2cb0b4dey19e857514cece0e8@mail.gmail.com> Message-ID: <14413946.4511781238606214731.JavaMail.root@spooler2-g27.priv.proxad.net> Hi Marek, could you comment this please Read: class Bar { public String name; public Bar right; } class Root { public Bar right; public Bar left; public Root(Bar right, Bar left) { this.left = this.// left is set here right = right; } } alex ----- Original Message ----- From: "Marek Kozie?" To: "Derek Foster" Cc: coin-dev at openjdk.java.net Sent: Tuesday, March 31, 2009 3:31:13 PM GMT +01:00 Amsterdam / Berlin / Bern / Rome / Stockholm / Vienna Subject: Re: Naked dot - accessing object fields through unqualified "." [C1] 2009/3/29 Derek Foster : > The major problem I have with this proposal is that it does not address the point of why I use a prefix on field names. As such, I would still continue to use a prefix even if this proposal were implemented. > > In short, I use a prefix to avoid typographical mistakes, like this one: > > void setFoo(Thing foob) { // Typo! > ? ?this.foo = foo; > } > > This will compile, and no warnings are produced, but it ends up assigning foo to itself, which is not what was intended. > > Your proposal has exactly the same problem: > > void setFoo(Thing foob) { // Typo! > ? ?.foo = foo; > } > > It therefore does not substitute for a field prefix, which WILL fix the problem: > > void setFoo(Thing foob) { // Typo! > ? ?_foo = foo; // ERROR! Undefined variable 'foo'. > } > You can use: Eclipse -> Java -> Code Style -> Edit -> Member Access -> Use 'this' qualifier for field access. (Always) > So unless you had some way to make use of the dot prefix mandatory and the only legal way to access fields (which I would like, but which would be an extremely backwards-incompatible change that will never happen in Java), I don't see that adding an optional dot prefix helps the situation except to reduce typing in constructor and setter methods slightly. > > (Note: I would love a "self-assignment is forbidden" change to Java. If I have time after my other proposals, I might write one up. (Anyone else want to volunteer? This one is easy!) I might be willing to forego prefixes and use the "this.foo = foo" approach, or even the ".foo = foo" approach, if I was sure it wouldn't cause me to fall into the self-assignment trap.) > > Derek > > > Read: class Bar { public String name; public Bar right; } class Root { public Bar right; public Bar left; public Root(Bar right, Bar left) { this.left = left// left is set here .right = right; } } Did you noticed missing semicolon? -- Pozdrowionka. / Regards. Lasu aka Marek Kozie? http://lasu2string.blogspot.com/ From christian at fi12.de Wed Apr 1 11:03:14 2009 From: christian at fi12.de (Christian Fischer) Date: Wed, 1 Apr 2009 20:03:14 +0200 (CEST) Subject: Proposal: Sameness operators In-Reply-To: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.n et> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> Message-ID: These $-operators doesn't seem intuitive to me, but replacing equal-calls sounds interesting. Maybe a better solution would be something like this: if (a eq b) // equals if (a ne b) // not equal if (a lt b) // lesser than if (a le b) // lesser or equal .... From Thomas.Hawtin at Sun.COM Wed Apr 1 11:26:43 2009 From: Thomas.Hawtin at Sun.COM (Tom Hawtin) Date: Wed, 01 Apr 2009 19:26:43 +0100 Subject: Proposal: Sameness operators In-Reply-To: References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> Message-ID: <49D3B1E3.8070109@sun.com> Christian Fischer wrote: > These $-operators doesn't seem intuitive to me, but replacing equal-calls > sounds interesting. > > Maybe a better solution would be something like this: > if (a eq b) // equals > if (a ne b) // not equal > if (a lt b) // lesser than > if (a le b) // lesser or equal Along with other concerns, four new keywords?! Theoretically they could be context sensitive, but then we are boxing in the grammar. If something like this were to be done (and let's face it, operator overloading ain't gonna happen in JDK7), then I think there needs to be to changes in fundamental direction of the proposal. * We need new symbols. .<. and the like were proposed in another similar proposal. So long as the symbol is a sequence of characters which is not valid in an existing Java program (outside of comments and literal strings). * I think it's clear that we can't use Comparable.compareTo and Object.equals. It requires a new method for each operator. Tom From Joe.Darcy at Sun.COM Wed Apr 1 11:54:40 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Wed, 01 Apr 2009 11:54:40 -0700 Subject: Opportunity Cost and Proposal Selection In-Reply-To: <751882.88756.qm@web63706.mail.re1.yahoo.com> References: <751882.88756.qm@web63706.mail.re1.yahoo.com> Message-ID: <49D3B870.7030601@sun.com> james lowden wrote: > Joe- > > I noticed that the version of the "large arrays" linked from your blog is the older (and messier) one; I updated it to this one: > > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000869.html > Hello. I added a link to the revised version. -Joe From Joe.Darcy at Sun.COM Wed Apr 1 12:55:14 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Wed, 01 Apr 2009 12:55:14 -0700 Subject: Proposal and updates OVERSEEN In-Reply-To: <49D3283B.4040709@gmx.de> References: <49D3283B.4040709@gmx.de> Message-ID: <49D3C6A2.2040505@sun.com> Ulf Zibis wrote: > Hi Joe, > > in the last update of your blog, you have overseen my proposal: > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001163.html > and it's update: > Extend switch .. case statement for all types and simple expressions > > > Also you've overseen this update: > Simply implicit method invocation chaining > > > Hopefully you will update your blog :-) > > -Ulf > > Blog updated accordingly. Thanks, -Joe From howard.lovatt at iee.org Wed Apr 1 13:34:07 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Thu, 2 Apr 2009 07:34:07 +1100 Subject: Proposal idea - generators In-Reply-To: <15e8b9d20903310749n4bb99322ldd92a96e3aa965c0@mail.gmail.com> References: <3dd3f56a0903310414w4c579d63xbc8f31ff0ff82021@mail.gmail.com> <15e8b9d20903310749n4bb99322ldd92a96e3aa965c0@mail.gmail.com> Message-ID: <3dd3f56a0904011334n50b17e59rd2ffaab5985b018a@mail.gmail.com> Hi Neal, I couldn't see in your blog where the problem is. Note I am not proposing, and I don't believe the original poster was either, a continuation style yield. More a Scala and other non-lazy functional language style were the results are stored in a Map and the Map is returned, i.e. like applying (mapping) a function to each element of a list but with more control (in particular break and continue functionality). Maybe you read the original post differently to me. -- Howard. 2009/4/1 Neal Gafter : > On Tue, Mar 31, 2009 at 4:14 AM, Howard Lovatt wrote: >> You can write a library to do this and also have break/continue >> control and parallel processing if needed: >> >> ? ? ? http://www.artima.com/weblogs/viewpost.jsp?thread=240412 > > Howard- > > Your library does not "do this". ?See > http://gafter.blogspot.com/2007/07/internal-versus-external-iterators.html > for an explanation of why not. > > Regards, > Neal > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > From neal at gafter.com Wed Apr 1 14:41:34 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 1 Apr 2009 14:41:34 -0700 Subject: Proposal idea - generators In-Reply-To: <3dd3f56a0904011334n50b17e59rd2ffaab5985b018a@mail.gmail.com> References: <3dd3f56a0903310414w4c579d63xbc8f31ff0ff82021@mail.gmail.com> <15e8b9d20903310749n4bb99322ldd92a96e3aa965c0@mail.gmail.com> <3dd3f56a0904011334n50b17e59rd2ffaab5985b018a@mail.gmail.com> Message-ID: <15e8b9d20904011441l3736b6b4me3ac78808bb9f450@mail.gmail.com> On Wed, Apr 1, 2009 at 1:34 PM, Howard Lovatt wrote: > Note I am not > proposing, and I don't believe the original poster was either, a > continuation style yield. More a Scala and other non-lazy functional > language style were the results are stored in a Map and the Map is > returned, i.e. like applying (mapping) a function to each element of a > list but with more control (in particular break and continue > functionality). Scala's comprehensions using their standard libraries are lazy. See, for example, Iterator.range. C#'s iterator methods are translated into a state machine (i.e. coroutines) and are inherently lazy. F# and OCaml are the most widely used non-lazy functional languages, but their comprehensions are lazy too. So I'm not sure what you're saying your proposal is comparable to. From neal at gafter.com Wed Apr 1 14:56:34 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 1 Apr 2009 14:56:34 -0700 Subject: Proposal idea - generators In-Reply-To: <15e8b9d20904011441l3736b6b4me3ac78808bb9f450@mail.gmail.com> References: <3dd3f56a0903310414w4c579d63xbc8f31ff0ff82021@mail.gmail.com> <15e8b9d20903310749n4bb99322ldd92a96e3aa965c0@mail.gmail.com> <3dd3f56a0904011334n50b17e59rd2ffaab5985b018a@mail.gmail.com> <15e8b9d20904011441l3736b6b4me3ac78808bb9f450@mail.gmail.com> Message-ID: <15e8b9d20904011456r8084a0dsf4f6878c1fa4a5a8@mail.gmail.com> On Wed, Apr 1, 2009 at 2:41 PM, Neal Gafter wrote: > On Wed, Apr 1, 2009 at 1:34 PM, Howard Lovatt wrote: >> Note I am not >> proposing, and I don't believe the original poster was either, a >> continuation style yield. More a Scala and other non-lazy functional >> language style were the results are stored in a Map and the Map is >> returned, i.e. like applying (mapping) a function to each element of a >> list but with more control (in particular break and continue >> functionality). > > Scala's comprehensions using their standard libraries are lazy. ?See, > for example, Iterator.range. ?C#'s iterator methods are translated > into a state machine (i.e. coroutines) and are inherently lazy. ?F# > and OCaml are the most widely used non-lazy functional languages, but > their comprehensions are lazy too. ?So I'm not sure what you're saying > your proposal is comparable to. I may be wrong about OCaml's generators. From develop4lasu at gmail.com Wed Apr 1 15:28:15 2009 From: develop4lasu at gmail.com (=?UTF-8?Q?Marek_Kozie=C5=82?=) Date: Thu, 2 Apr 2009 00:28:15 +0200 Subject: Proposal and updates OVERSEEN In-Reply-To: <49D3C6A2.2040505@sun.com> References: <49D3283B.4040709@gmx.de> <49D3C6A2.2040505@sun.com> Message-ID: <28bca0ff0904011528p1041b241yc1d41bcb546bc2ad@mail.gmail.com> 2009/4/1 Joseph D. Darcy : > > Blog updated accordingly. > > Thanks, > > -Joe > Hi. I'll add my: Updated proposals: - Return 'this' http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001185.html - 'final' without explicit type http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001178.html Can be removed: - 'This' type - while it require from generics to have tagged types it's not possible to introduce it into language. - Enhanced while statement - It was created only to show complex problems with loops. Missed: - Delegation proposal http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000477.html - 'forget' keyword http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001093.html Even if they were missed by reason I would like to know that. -- Pozdrowionka. / Regards. Lasu aka Marek Kozie? http://lasu2string.blogspot.com/ From develop4lasu at gmail.com Wed Apr 1 16:05:38 2009 From: develop4lasu at gmail.com (=?UTF-8?Q?Marek_Kozie=C5=82?=) Date: Thu, 2 Apr 2009 01:05:38 +0200 Subject: Naked dot - accessing object fields through unqualified "." [C1] In-Reply-To: <14413946.4511781238606214731.JavaMail.root@spooler2-g27.priv.proxad.net> References: <28bca0ff0903310631o2cb0b4dey19e857514cece0e8@mail.gmail.com> <14413946.4511781238606214731.JavaMail.root@spooler2-g27.priv.proxad.net> Message-ID: <28bca0ff0904011605x6d65fd7cqf87d058ae0d3724d@mail.gmail.com> 2009/4/1 : > Hi Marek, > could you comment this please > > Read: > ? ? class Bar { > ? ? ? ? ?public String ? ? name; > ? ? ? ? ?public Bar ? ? ? ? ?right; > ? ? } > > ? ? class Root { > ? ? ? ? ?public Bar ? ? right; > ? ? ? ? ?public Bar ? ? left; > > ? ? ? ? ?public Root(Bar right, Bar left) { > ? ? ? ? ? ? ? this.left = this.// left is set here > ? ? ? ? ? ? ? right = right; > ? ? ? ? ?} > > ? ? } > > > alex > Hi. This was measured that if you split expresion into more lines operator should be placed at start: Operator(s) (during splitting exprestion into two lines) should be placed in a new line, like: String s = "could you comment this please " // + "\n\nRead:"; This is easier to read, bacause it shows directly that previous line need to be checked to understand this one. What's more, operator placed in the end of the line can be over the screen. So, this line: this.left = this.// left is set here is consider to be bad style. -- Pozdrowionka. / Regards. Lasu aka Marek Kozie? http://lasu2string.blogspot.com/ From neal at gafter.com Wed Apr 1 17:20:43 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 1 Apr 2009 17:20:43 -0700 Subject: Proposal idea - generators In-Reply-To: <5090A08F-7225-477B-A390-D3A73A62823E@gmail.com> References: <3dd3f56a0903310414w4c579d63xbc8f31ff0ff82021@mail.gmail.com> <15e8b9d20903310749n4bb99322ldd92a96e3aa965c0@mail.gmail.com> <3dd3f56a0904011334n50b17e59rd2ffaab5985b018a@mail.gmail.com> <15e8b9d20904011441l3736b6b4me3ac78808bb9f450@mail.gmail.com> <15e8b9d20904011456r8084a0dsf4f6878c1fa4a5a8@mail.gmail.com> <5090A08F-7225-477B-A390-D3A73A62823E@gmail.com> Message-ID: <15e8b9d20904011720t349fd2e4x98ee29b16328cd86@mail.gmail.com> On Wed, Apr 1, 2009 at 4:13 PM, Howard Lovatt wrote: > My reading of the Scala Language Specification, page 83, is that the for > loop is translated into a map call (or similar). Therefore whether this is > lazy or not is an implementation detail. So I think it is valid to eagerly > evaluate the loop and store the results in a hash map. After all, the > current Java for loop evaluates eagerly. Whether a given Iterator used in a Java for-each loop produces its values eagerly or lazily is an implementation detail of that iterator. Requiring it to be eager reduces the flexibility. From howard.lovatt at gmail.com Wed Apr 1 16:13:08 2009 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Thu, 2 Apr 2009 10:13:08 +1100 Subject: Proposal idea - generators In-Reply-To: <15e8b9d20904011456r8084a0dsf4f6878c1fa4a5a8@mail.gmail.com> References: <3dd3f56a0903310414w4c579d63xbc8f31ff0ff82021@mail.gmail.com> <15e8b9d20903310749n4bb99322ldd92a96e3aa965c0@mail.gmail.com> <3dd3f56a0904011334n50b17e59rd2ffaab5985b018a@mail.gmail.com> <15e8b9d20904011441l3736b6b4me3ac78808bb9f450@mail.gmail.com> <15e8b9d20904011456r8084a0dsf4f6878c1fa4a5a8@mail.gmail.com> Message-ID: <5090A08F-7225-477B-A390-D3A73A62823E@gmail.com> My reading of the Scala Language Specification, page 83, is that the for loop is translated into a map call (or similar). Therefore whether this is lazy or not is an implementation detail. So I think it is valid to eagerly evaluate the loop and store the results in a hash map. After all, the current Java for loop evaluates eagerly. Functional languages like Mathematica, which are extensively used in Science and maths, eagerly evalate and store the results. In fact this is a common array generation means. -- Howard On 02/04/2009, at 8:56 AM, Neal Gafter wrote: > On Wed, Apr 1, 2009 at 2:41 PM, Neal Gafter wrote: >> On Wed, Apr 1, 2009 at 1:34 PM, Howard Lovatt >> wrote: >>> Note I am not >>> proposing, and I don't believe the original poster was either, a >>> continuation style yield. More a Scala and other non-lazy functional >>> language style were the results are stored in a Map and the Map is >>> returned, i.e. like applying (mapping) a function to each element >>> of a >>> list but with more control (in particular break and continue >>> functionality). >> >> Scala's comprehensions using their standard libraries are lazy. See, >> for example, Iterator.range. C#'s iterator methods are translated >> into a state machine (i.e. coroutines) and are inherently lazy. F# >> and OCaml are the most widely used non-lazy functional languages, but >> their comprehensions are lazy too. So I'm not sure what you're >> saying >> your proposal is comparable to. > > I may be wrong about OCaml's generators. > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ From markmahieu at googlemail.com Wed Apr 1 23:05:17 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Thu, 2 Apr 2009 07:05:17 +0100 Subject: Proposal and updates OVERSEEN In-Reply-To: <28bca0ff0904011528p1041b241yc1d41bcb546bc2ad@mail.gmail.com> References: <49D3283B.4040709@gmx.de> <49D3C6A2.2040505@sun.com> <28bca0ff0904011528p1041b241yc1d41bcb546bc2ad@mail.gmail.com> Message-ID: One more :) The 'Rethrows Clause' proposal was also updated with JLS references, here: http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001198.html (The proposal and prototype linked to at http://slm888.com/javac/coin-rethrows.html has a further minor adjustment to simplify the rules around exception type constructors which themselves throw checked exceptions). Mark 2009/4/1 Marek Kozie? > 2009/4/1 Joseph D. Darcy : > > > > Blog updated accordingly. > > > > Thanks, > > > > -Joe > > > > Hi. > I'll add my: > > > Updated proposals: > - Return 'this' > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001185.html > > - 'final' without explicit type > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001178.html > > > > Can be removed: > - 'This' type - while it require from generics to have tagged types > it's not possible to introduce it into language. > - Enhanced while statement - It was created only to show complex > problems with loops. > > > > Missed: > - Delegation proposal > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000477.html > > - 'forget' keyword > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001093.html > > Even if they were missed by reason I would like to know that. > > > -- > Pozdrowionka. / Regards. > Lasu aka Marek Kozie? > > http://lasu2string.blogspot.com/ > > From scolebourne at joda.org Thu Apr 2 04:39:56 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Thu, 2 Apr 2009 12:39:56 +0100 Subject: Helping to find the usefulness of a proposal Message-ID: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> All, One possible way I'd like to suggest that the coin evaluation could be helped would be to write a script to find out how frequently the specific issue comes up in real code. It should be possible to devise, write and run a script to find the number of LOCs affected by many of the proposals. For example: - strings in switch (find if else on constant strings) - multi-catch (find duplicate catch blocks) - elvis operator (find ternary and if else defaulting) - for each where the iterator remove can be accessed (% of loops that access iterator) - for each where index is needed (% of loops that use int looping) - method and field literals - byte and short literals and probably many others (I've just listed some proposals I remember) Ideally, any script would be ASM/BCEL based, but grep style might work too. I mention all this because I don't have the spare time to write such a script, but if you do, then I'm sure we'd all like to run it and discuss the results ;-) Stephen From markmahieu at googlemail.com Thu Apr 2 04:44:21 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Thu, 2 Apr 2009 12:44:21 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> Message-ID: Definitely. I did that for the Auto-assigned Parameters proposal actually, but I chose to use javac's parser and then did my own analysis based on the AST. There might be something generically useful I can split out from that hacked-up code, if people want to use the same technique. Mark 2009/4/2 Stephen Colebourne > All, > One possible way I'd like to suggest that the coin evaluation could be > helped would be to write a script to find out how frequently the > specific issue comes up in real code. > > It should be possible to devise, write and run a script to find the > number of LOCs affected by many of the proposals. For example: > > - strings in switch (find if else on constant strings) > - multi-catch (find duplicate catch blocks) > - elvis operator (find ternary and if else defaulting) > - for each where the iterator remove can be accessed (% of loops that > access iterator) > - for each where index is needed (% of loops that use int looping) > - method and field literals > - byte and short literals > and probably many others (I've just listed some proposals I remember) > > Ideally, any script would be ASM/BCEL based, but grep style might work too. > > I mention all this because I don't have the spare time to write such a > script, but if you do, then I'm sure we'd all like to run it and > discuss the results ;-) > > Stephen > > From reinier at zwitserloot.com Thu Apr 2 04:46:30 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 2 Apr 2009 13:46:30 +0200 Subject: Proposal: Sameness operators In-Reply-To: <49D3B1E3.8070109@sun.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> Message-ID: <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> Why can't we use compareTo and equals? .<. syntax had severe problems that disqualified them - see the archive of this mailing list. 'is' has slightly more precedence than 'eq' and the set 'eq', 'ne', 'lt', and 'le' need 'gt' and 'ge' as well, which makes them rather unwieldy. You can reduce a thing or two by going with just 'eq', 'lt' and 'gt', filling the holes with && and ! as usual (not equal becomes ! (a eq b)), or even a !eq b, but this is all devolving into way too much slap-dash language design unless those become global, non-context sensitive keywords. I'm okay with that, but Joe Darcy definitely isn't, so that's right out, at least for now. More symbols is similarly unwieldy; there are no appropriate symbols for these operations available. It would be an even greater mistake to come up with some non-standard and unwieldly syntax for them, such as $=. That way lies perl cartoon-swearing craziness and nobody wants that. Wholesale operator overloading would be far preferable to that situation. ":=" for some sort of inference typing would make some sense and is still free, but that's about where it ends. The cleanest solution to me remains a cleaning of the slate, so to speak, and an explicit demarkation in your source file that you're on 'new java', such as with "source 1.8". With that at the top, "a == b" is compiled the same way as old java's "a == null ? b == null : a.equals(b)" for non-boxable objects (for unboxables and primitives, Unbox everything you can, then do a numeric comparison, or if it's primitive v. object, error), "a < b" and its ilk translate to .compareTo for non-unboxable Comparables, lead to unboxing for unboxables, no change for primitives, and error otherwise. Past mistakes are rectified, blahblahblah. We've been over this before, I'm sure most coin-dev readers have a good idea about how such a thing would work and the decade+ timerift it would cause between code bases that (stubbornly?) stay with non-new java. --Reinier Zwitserloot Like it? Tip it! http://tipit.to On Apr 1, 2009, at 20:26, Tom Hawtin wrote: > Christian Fischer wrote: >> These $-operators doesn't seem intuitive to me, but replacing equal- >> calls >> sounds interesting. >> >> Maybe a better solution would be something like this: >> if (a eq b) // equals >> if (a ne b) // not equal >> if (a lt b) // lesser than >> if (a le b) // lesser or equal > > Along with other concerns, four new keywords?! Theoretically they > could > be context sensitive, but then we are boxing in the grammar. > > If something like this were to be done (and let's face it, operator > overloading ain't gonna happen in JDK7), then I think there needs to > be > to changes in fundamental direction of the proposal. > > * We need new symbols. .<. and the like were proposed in another > similar proposal. So long as the symbol is a sequence of characters > which is not valid in an existing Java program (outside of comments > and > literal strings). > > * I think it's clear that we can't use Comparable.compareTo and > Object.equals. It requires a new method for each operator. > > Tom > From peter.levart at gmail.com Thu Apr 2 04:59:25 2009 From: peter.levart at gmail.com (Peter Levart) Date: Thu, 2 Apr 2009 13:59:25 +0200 Subject: Proposal: Automatic Resource Management Message-ID: Hello Coiners! The debate about ARM proposal has calmed down lately and I was thinking about it last few days. Initially I submitted a comment that got lost by list processor and was about using a "marker" interface as a supertype of sigle-method disposable interfaces like this: package java.lang; public interface AutomaticResource {} ... and for example, retroffiting java.io.Closeable: package java.io; public interface Closeable extends AutomaticResource { void close() throws IOException; } ... this way even the name of the method would not be "coined". There would have to be some rules that compiler will enforce to make sure it can uniquely identify the method to be called on resource disposal (for example: the static type of the resource should not directly or indirectly implement or extend two different single-method interfaces marked with AutomaticResource marker superinterface). But then I thought. Why would this language feature even have to be tied to a particular interface. The "foreach" loop did take this approach with java.lang.Iterable, but this had nothing to do with exceptions and catching them and ignoring them silently. A language construct that hides this often cited "bad practice" under the carpet is no good! For example, this snippet of code, written to the proposed ARM spec., submited by Bob Lee in this thread a month ago, asking Neal Gafter to demonstrate how the equivalent BGGA version would look like: try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest)) { byte[] buf = new byte[8 * 1024]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); } catch (IOException e) { showDialog("Copy failed."); } ... is flawed. This code does not guarantee that in the absence of shown exception the file has been copied in it's intirety. Ignoring exception thrown on an InputStream.close() might be desireable, but ignoring exception thrown on OutputStream.close() migh mean that you don't mind missing writing some final bytes into the file. Closing OutputStream should not be part of automatic resource disposal but part of main code block. This brings us to the question how is ARM supposed to be able do differentiate InputStream from OutputStream if both implement Closeable? So I thought how to circumvent these two weeknesses. My take on this is something like the following: try (InputStream in = new FileInputStream("inputFile"); OutputStream out = new FileOutputStream("outputFile")) { // try body } catch (IOException e) { // catch body } finally (IOException e1 : in.close(); IOException e2 : out.close()) { // finally body } ... would be translated to ... { IOException e1 = null; IOException e2 = null; try { InputStream in = new FileInputStream("inputFile"); try { OutputStream out = new FileOutputStream("outputFile"); try { // try body } finally { try { out.close(); } catch (IOException $$e) { e2 = $$e; } } } finally { try { in.close(); } catch (IOException $$e) { e1 = $$e; } } } catch (IOException e) { // catch body } finally { // finally body } } ... no special interfaces are used here. The code to dispose of resources is clearly visible (it has to be writen, yes, but that also means that it can be read, which is a good thing). The above example is the "full monty" version. The thing to note is that a try (...; ...; ...) construct is to be matched by an optional finally (...; ...; ...) construct in that both, if the second is specified, must have an equal number of semicolons. Each "statement" in the try construct gets it's own slot that must be matched by the coresponding slot in the finally (...; ...; ...) construct. Any slot in finally construct can be left empty (like any of the 3 slots in the for (;;) statement). The following minimal version is also possible (in this example no catching of exceptions on resource cleanup is attempted): int i, j; ReadWriteLock iLock = ...; ReadWriteLock jLock = ...; // ... try (jLock.readLock().lock(); iLock.writeLock().lock()) { i += j; } finally (jLock.readLock().unlock(); iLock.writeLock().unlock()) ... gets translated to: { jLock.readLock().lock(); try { iLock.writeLock().lock(); try { i += j; } finally { iLock.writeLock().unlock(); } } finally { jLock.readLock().unlock(); } } All this will have to be formalized. This is just an idea to keep the debate going. Regards, Peter From rssh at gradsoft.com.ua Thu Apr 2 05:03:33 2009 From: rssh at gradsoft.com.ua (rssh at gradsoft.com.ua) Date: Thu, 2 Apr 2009 15:03:33 +0300 (EEST) Subject: Helping to find the usefulness of a proposal In-Reply-To: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> Message-ID: <9ca625bf5b892e4a94f495a155f66e6f.squirrel@wmail.gradsoft.ua> > All, > One possible way I'd like to suggest that the coin evaluation could be > helped would be to write a script to find out how frequently the > specific issue comes up in real code. > > It should be possible to devise, write and run a script to find the > number of LOCs affected by many of the proposals. For example: > Clever idea. If I would know, that one will used, I will wrote one during next week-end. > - strings in switch (find if else on constant strings) > - multi-catch (find duplicate catch blocks) > - elvis operator (find ternary and if else defaulting) > - for each where the iterator remove can be accessed (% of loops that > access iterator) > - for each where index is needed (% of loops that use int looping) > - method and field literals > - byte and short literals > and probably many others (I've just listed some proposals I remember) > > Ideally, any script would be ASM/BCEL based, but grep style might work > too. > > I mention all this because I don't have the spare time to write such a > script, but if you do, then I'm sure we'd all like to run it and > discuss the results ;-) > > Stephen > > From pdoubleya at gmail.com Thu Apr 2 05:15:35 2009 From: pdoubleya at gmail.com (Patrick Wright) Date: Thu, 2 Apr 2009 14:15:35 +0200 Subject: Helping to find the usefulness of a proposal In-Reply-To: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> Message-ID: <64efa1ba0904020515m679910b4n1be9cce0034e474d@mail.gmail.com> This would be useful. One might be able to start by building on the infrastructure in Checkstyle, PMD or FindBugs for some of these. I don't know about FindBugs, but the other two allow you to write your own matching rules. Jackpot could be used as well, but it's no longer maintained as an independent project (now part of NB refactoring infrastructure). One would have to use a slightly older version of it. Patrick From scolebourne at joda.org Thu Apr 2 05:24:32 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Thu, 2 Apr 2009 13:24:32 +0100 Subject: Proposal: Sameness operators In-Reply-To: <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> Message-ID: <4b4f45e00904020524p27741baeo40483e83d71dc768@mail.gmail.com> The best alternative operator symbols I've come up with yet are bracketed ones: a (==) b a (<) b I don't think that the symbols are ideal, but they do look reasonably readable, and its way better than .equals(). Do I expect anything to happen here? No. There is a long history of "operator overloading" being frowned on in the Java language. The net result is more of an argument to use Groovy, Scala, Fan etc. Stephen 2009/4/2 Reinier Zwitserloot : > Why can't we use compareTo and equals? > > .<. syntax had severe problems that disqualified them - see the > archive of this mailing list. > > 'is' has slightly more precedence than 'eq' and the set 'eq', 'ne', > 'lt', and 'le' need 'gt' and 'ge' as well, which makes them rather > unwieldy. You can reduce a thing or two by going with just 'eq', 'lt' > and 'gt', filling the holes with && and ! as usual (not equal becomes ! > (a eq b)), or even a !eq b, but this is all devolving into way too > much slap-dash language design unless those become global, non-context > sensitive keywords. I'm okay with that, but Joe Darcy definitely > isn't, so that's right out, at least for now. > > More symbols is similarly unwieldy; there are no appropriate symbols > for these operations available. It would be an even greater mistake to > come up with some non-standard and unwieldly syntax for them, such as > $=. That way lies perl cartoon-swearing craziness and nobody wants > that. Wholesale operator overloading would be far preferable to that > situation. ":=" for some sort of inference typing would make some > sense and is still free, but that's about where it ends. > > > The cleanest solution to me remains a cleaning of the slate, so to > speak, and an explicit demarkation in your source file that you're on > 'new java', such as with "source 1.8". With that at the top, "a == b" > is compiled the same way as old java's "a == null ? b == null : > a.equals(b)" for non-boxable objects (for unboxables and primitives, > Unbox everything you can, then do a numeric comparison, or if it's > primitive v. object, error), "a < b" and its ilk translate > to .compareTo for non-unboxable Comparables, lead to unboxing for > unboxables, no change for primitives, and error otherwise. Past > mistakes are rectified, blahblahblah. We've been over this before, I'm > sure most coin-dev readers have a good idea about how such a thing > would work and the decade+ timerift it would cause between code bases > that (stubbornly?) stay with non-new java. > > > > ?--Reinier Zwitserloot > Like it? Tip it! > http://tipit.to > > > > On Apr 1, 2009, at 20:26, Tom Hawtin wrote: > >> Christian Fischer wrote: >>> These $-operators doesn't seem intuitive to me, but replacing equal- >>> calls >>> sounds interesting. >>> >>> Maybe a better solution would be something like this: >>> if (a eq b) // equals >>> if (a ne b) // not equal >>> if (a lt b) // lesser than >>> if (a le b) // lesser or equal >> >> Along with other concerns, four new keywords?! Theoretically they >> could >> be context sensitive, but then we are boxing in the grammar. >> >> If something like this were to be done (and let's face it, operator >> overloading ain't gonna happen in JDK7), then I think there needs to >> be >> to changes in fundamental direction of the proposal. >> >> ?* We need new symbols. .<. and the like were proposed in another >> similar proposal. So long as the symbol is a sequence of characters >> which is not valid in an existing Java program (outside of comments >> and >> literal strings). >> >> ?* I think it's clear that we can't use Comparable.compareTo and >> Object.equals. It requires a new method for each operator. >> >> Tom >> > > > From reinier at zwitserloot.com Thu Apr 2 05:24:42 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 2 Apr 2009 14:24:42 +0200 Subject: Proposal: Automatic Resource Management In-Reply-To: References: Message-ID: <370F8DB1-A374-43B4-9F83-ABCD5A925D93@zwitserloot.com> I remember quite a bit of discussion on that. Some of the problems no one really solved: - What if one object ends up implementing multiple interfaces that are all AutomaticResource subtypes? Call all of them? Compile-time error? What if that situation happens at runtime due to updating a library? Class Validation? Close all of them in that case, but compile- time error if the compiler detects such a situation? Runtime exception? - What if one implements AutomaticResource but has multiple methods? Who is responsible for warning? Compiler? What if I construct a class file with this 'bug' in it? Its easy even without ASM: Use jruby, jython, or just an older version of javac. Piece of pie. The JVM can't just up and crash when it encounters such a type, so some sort of behaviour must be specified. You also seem to mistaken about the ARM proposal's 'exception hiding' principle. As I understand it, this is relevant ONLY if the guarded scope (=contents of the try block) threw an exception of its own. You can't throw 2 exceptions simultaneously in java, so one of them has to win out. Normally, in try/finally blocks, whatever the finally block does wins, but for ARM, the idea is that the try block's exception wins, because often .close() will fail if some method on the resource itself also failed, and the problem is probably better described with a more useful stack trace on the original. If a try block ends normally, but during resource cleanup the .close() causes an exception, that exception will propagate out, it will NOT be ignored! There is no need to catch exceptions wafting off of InputStream.close() because they basically never happen. The thing that is strongly preferable is to take the annoyance of having to worry about InputStream.close() away from the programmer, which ARM essentially does. The problem isn't IOExceptions being thrown by close(), the problem is InputStream.close()'s declaration that it throws this exception, which forces you to handle it. This isn't the only erroneous checked exception in java (new String(somebytes, "UTF-8") declares that it can throw the checked UnsupportedEncodingException, eventhough it actually cant, because UTF-8 is guaranteed by the JVM spec to exist. The appropriate way to handle this is to catch the UEncEx, and rethrow it as an InternalError("JVM Bug"). But I digress - at any rate, InputStream.close() in practice doesn't throw exceptions unless there's a good reason for it, whereas the UEncEx from String. is *defined* that it MUST NOT throw that exception, which puts it in a different ballpark). Your proposal is vague to me: What, exactly, are e1 and e2? Will one of them be non-null if there is an exception? What happens if I leave my finally body empty, which is what I imagine most people who are in a hurry will do? Just get ignored? That would be very bad. Having to remember the order of the try-block's parameters because these are applied to the finally parameters also strikes me as particularly bad design; making mistakes in ordering seems like a great way to make a puzzler. --Reinier Zwitserloot On Apr 2, 2009, at 13:59, Peter Levart wrote: > Hello Coiners! > > The debate about ARM proposal has calmed down lately and I was > thinking > about it last few days. Initially I submitted a comment that got > lost by > list processor and was about using a "marker" interface as a > supertype of > sigle-method disposable interfaces like this: > > > package java.lang; > > public interface AutomaticResource {} > > > ... and for example, retroffiting java.io.Closeable: > > > package java.io; > > public interface Closeable extends AutomaticResource { > void close() throws IOException; > } > > > ... this way even the name of the method would not be "coined". > There would > have to be some rules that compiler will enforce to make sure it can > uniquely identify the method to be called on resource disposal (for > example: > the static type of the resource should not directly or indirectly > implement > or extend two different single-method interfaces marked with > AutomaticResource marker superinterface). > > But then I thought. Why would this language feature even have to be > tied to > a particular interface. The "foreach" loop did take this approach with > java.lang.Iterable, but this had nothing to do with exceptions and > catching > them and ignoring them silently. A language construct that hides > this often > cited "bad practice" under the carpet is no good! > > For example, this snippet of code, written to the proposed ARM spec., > submited by Bob Lee in this thread a month ago, asking Neal Gafter to > demonstrate how the equivalent BGGA version would look like: > > try (InputStream in = new FileInputStream(src); > OutputStream out = new FileOutputStream(dest)) { > byte[] buf = new byte[8 * 1024]; > int n; > while ((n = in.read(buf)) >= 0) > out.write(buf, 0, n); > } catch (IOException e) { > showDialog("Copy failed."); > } > > ... is flawed. This code does not guarantee that in the absence of > shown > exception the file has been copied in it's intirety. > > Ignoring exception thrown on an InputStream.close() might be > desireable, but > ignoring exception thrown on OutputStream.close() migh mean that you > don't > mind missing writing some final bytes into the file. Closing > OutputStream > should not be part of automatic resource disposal but part of main > code > block. This brings us to the question how is ARM supposed to be able > do > differentiate InputStream from OutputStream if both implement > Closeable? > > So I thought how to circumvent these two weeknesses. My take on this > is > something like the following: > > > try (InputStream in = new FileInputStream("inputFile"); > OutputStream out = new FileOutputStream("outputFile")) > { > // try body > } > catch (IOException e) > { > // catch body > } > finally (IOException e1 : in.close(); > IOException e2 : out.close()) > { > // finally body > } > > > ... would be translated to ... > > > { > IOException e1 = null; > IOException e2 = null; > > try > { > InputStream in = new FileInputStream("inputFile"); > > try > { > OutputStream out = new > FileOutputStream("outputFile"); > > try > { > // try body > } > finally > { > try > { > out.close(); > } > catch (IOException $$e) > { > e2 = $$e; > } > } > } > finally > { > try > { > in.close(); > } > catch (IOException $$e) > { > e1 = $$e; > } > } > } > catch (IOException e) > { > // catch body > } > finally > { > // finally body > } > } > > > > ... no special interfaces are used here. The code to dispose of > resources is > clearly visible (it has to be writen, yes, but that also means that > it can > be read, which is a good thing). > > The above example is the "full monty" version. The thing to note is > that a > try (...; ...; ...) construct is to be matched by an optional > finally (...; > ...; ...) construct in that both, if the second is specified, must > have an > equal number of semicolons. Each "statement" in the try construct > gets it's > own slot that must be matched by the coresponding slot in the > finally (...; > ...; ...) construct. Any slot in finally construct can be left empty > (like > any of the 3 slots in the for (;;) statement). > > The following minimal version is also possible (in this example no > catching > of exceptions on resource cleanup is attempted): > > int i, j; > ReadWriteLock iLock = ...; > ReadWriteLock jLock = ...; > > // ... > > try (jLock.readLock().lock(); iLock.writeLock().lock()) { > i += j; > } > finally (jLock.readLock().unlock(); iLock.writeLock().unlock()) > > > ... gets translated to: > > > { > jLock.readLock().lock(); > try { > iLock.writeLock().lock(); > try { > i += j; > } > finally { > iLock.writeLock().unlock(); > } > } > finally { > jLock.readLock().unlock(); > } > } > > > All this will have to be formalized. This is just an idea to keep > the debate > going. > > Regards, Peter > From reinier at zwitserloot.com Thu Apr 2 05:25:38 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 2 Apr 2009 14:25:38 +0200 Subject: Helping to find the usefulness of a proposal In-Reply-To: <64efa1ba0904020515m679910b4n1be9cce0034e474d@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <64efa1ba0904020515m679910b4n1be9cce0034e474d@mail.gmail.com> Message-ID: <8FD8F030-FE9E-4225-ABD0-40E043B6F1ED@zwitserloot.com> ... or resurrect it by ripping it out of netbeans. I love the idea of jackpot and am saddened that it is no longer a stand-alone thing. --Reinier Zwitserloot On Apr 2, 2009, at 14:15, Patrick Wright wrote: > This would be useful. > > One might be able to start by building on the infrastructure in > Checkstyle, PMD or FindBugs for some of these. I don't know about > FindBugs, but the other two allow you to write your own matching > rules. Jackpot could be used as well, but it's no longer maintained as > an independent project (now part of NB refactoring infrastructure). > One would have to use a slightly older version of it. > > > > Patrick > From develop4lasu at gmail.com Thu Apr 2 05:28:13 2009 From: develop4lasu at gmail.com (=?UTF-8?Q?Marek_Kozie=C5=82?=) Date: Thu, 2 Apr 2009 14:28:13 +0200 Subject: Helping to find the usefulness of a proposal In-Reply-To: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> Message-ID: <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> 2009/4/2 Stephen Colebourne : > All, > One possible way I'd like to suggest that the coin evaluation could be > helped would be to write a script to find out how frequently the > specific issue comes up in real code. > > It should be possible to devise, write and run a script to find the > number of LOCs affected by many of the proposals. For example: > > - strings in switch (find if else on constant strings) > - multi-catch (find duplicate catch blocks) > - elvis operator (find ternary and if else defaulting) > - for each where the iterator remove can be accessed (% of loops that > access iterator) > - for each where index is needed (% of loops that use int looping) > - method and field literals > - byte and short literals > and probably many others (I've just listed some proposals I remember) > > Ideally, any script would be ASM/BCEL based, but grep style might work too. > > I mention all this because I don't have the spare time to write such a > script, but if you do, then I'm sure we'd all like to run it and > discuss the results ;-) > > Stephen > > We may list all proposals and write opinions & statistics (as we think). -- Pozdrowionka. / Regards. Lasu aka Marek Kozie? http://lasu2string.blogspot.com/ From Thomas.Hawtin at Sun.COM Thu Apr 2 05:29:17 2009 From: Thomas.Hawtin at Sun.COM (Tom Hawtin) Date: Thu, 02 Apr 2009 13:29:17 +0100 Subject: Proposal: Sameness operators In-Reply-To: <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> Message-ID: <49D4AF9D.9090407@sun.com> Reinier Zwitserloot wrote: > Why can't we use compareTo and equals? * compareTo may well be unreasonably inefficient. * equals handles nulls (asymmetrically), compareTo does not * equals does test-and-cast (event for generic types - urgh), compareTo uses generics * equals does not throw ClassCastException, compareTo does (but probably shouldn't with generics) Therefore, new methods please. I'm sure you are aware the whole subject of operator overloading in general is a minefield. > .<. syntax had severe problems that disqualified them - see the > archive of this mailing list. Other than reminding me of the F-language, as a lexical token it is perfectly upstanding. The IDE behaviour is a bonus (well I find menus popping up as I type almost as annoying as Flash adverts and b***king cursors, but you get what I mean). > The cleanest solution to me remains a cleaning of the slate, so to Making a slight change wouldn't be an effective cleaning of the slate, IMO. Lots of downsides (not necessarily to you in particular) and not enough upsides. Anyway, I think we all knew which way the wind was blowing on proposals like this one from the start of the process. Tom Hawtin From reinier at zwitserloot.com Thu Apr 2 05:36:24 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 2 Apr 2009 14:36:24 +0200 Subject: Proposal: Sameness operators In-Reply-To: <4b4f45e00904020524p27741baeo40483e83d71dc768@mail.gmail.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <4b4f45e00904020524p27741baeo40483e83d71dc768@mail.gmail.com> Message-ID: <275433EA-A420-42C8-891D-3B0C2629222A@zwitserloot.com> It's certainly the best backwards compatible alternative that I have ever seen, but they are still FAR from ideal. Take your average programmer who is just reading some code. He first sees: a == b He rightly assumes this is some sort of equality check, though he would probably be surprised to learn that in java, it's object pointer identity, not object equality, if a and b are objects. Still, that's one sort of (mostly useless) equality, and it is the same as C's meaning for this operation, which is not an unimportant benefit, because many things in java that look indistinguishable from C code do roughly the same thing. Then he sees: a (==) b a few lines down, and now he's just confused and will need to hit the books to figure any of this out. I'll grant you that the readability of the current situation is not very good either, and I will certainly grant that the practical nature of the == operator is very bad indeed (In fact, when this comes up in discussion, I always suggest just dropping support for object identity altogether in the language, and moving that to System.identicalPointers(a, b) or some such. Who needs to know about this stuff? Nobody. It's like copying arrays quickly. Yes, java should be capable of doing it, but not even close to useful enough to warrant an operator!) Crazy idea: We can get a little closer to ideal by creating a class in java lang with useful static methods which you can then import, like: public static void is(Object x, Object y) { if ( x == null ) return y == null; return x.equals(y); } public static void is(Object x, int y) { // Yes, you'd need a few gazillion is methods to cover all the primitives on either side, but 1 static import will grab all of them } ... loads more is methods Then same with lt, gt, le, ge. Then you could write: if ( is(a, b) ) { //doStuff } Which is a small improvement. Add an ability to specify 'as infix' in static imports, and you have pretty much what we all want without backwards compatibility issues: import static java.lang.Equality.is infix; if ( a is b ) { //do something } I'd consider that a large improvement. In my perfect world: ':=' is assignment, assignment to a boolean is no longer an expression but just a statement to avoid bugs, '=' is equality, and '==' is a deprecated syntax for System.identicalPointer, or just '=' for primitives/unboxables. That would no longer be even remotely compatible with java as is, though. --Reinier Zwitserloot On Apr 2, 2009, at 14:24, Stephen Colebourne wrote: > The best alternative operator symbols I've come up with yet are > bracketed ones: > > a (==) b > a (<) b > > I don't think that the symbols are ideal, but they do look reasonably > readable, and its way better than .equals(). > > Do I expect anything to happen here? No. There is a long history of > "operator overloading" being frowned on in the Java language. The net > result is more of an argument to use Groovy, Scala, Fan etc. > > Stephen > > > 2009/4/2 Reinier Zwitserloot : >> Why can't we use compareTo and equals? >> >> .<. syntax had severe problems that disqualified them - see the >> archive of this mailing list. >> >> 'is' has slightly more precedence than 'eq' and the set 'eq', 'ne', >> 'lt', and 'le' need 'gt' and 'ge' as well, which makes them rather >> unwieldy. You can reduce a thing or two by going with just 'eq', 'lt' >> and 'gt', filling the holes with && and ! as usual (not equal >> becomes ! >> (a eq b)), or even a !eq b, but this is all devolving into way too >> much slap-dash language design unless those become global, non- >> context >> sensitive keywords. I'm okay with that, but Joe Darcy definitely >> isn't, so that's right out, at least for now. >> >> More symbols is similarly unwieldy; there are no appropriate symbols >> for these operations available. It would be an even greater mistake >> to >> come up with some non-standard and unwieldly syntax for them, such as >> $=. That way lies perl cartoon-swearing craziness and nobody wants >> that. Wholesale operator overloading would be far preferable to that >> situation. ":=" for some sort of inference typing would make some >> sense and is still free, but that's about where it ends. >> >> >> The cleanest solution to me remains a cleaning of the slate, so to >> speak, and an explicit demarkation in your source file that you're on >> 'new java', such as with "source 1.8". With that at the top, "a == b" >> is compiled the same way as old java's "a == null ? b == null : >> a.equals(b)" for non-boxable objects (for unboxables and primitives, >> Unbox everything you can, then do a numeric comparison, or if it's >> primitive v. object, error), "a < b" and its ilk translate >> to .compareTo for non-unboxable Comparables, lead to unboxing for >> unboxables, no change for primitives, and error otherwise. Past >> mistakes are rectified, blahblahblah. We've been over this before, >> I'm >> sure most coin-dev readers have a good idea about how such a thing >> would work and the decade+ timerift it would cause between code bases >> that (stubbornly?) stay with non-new java. >> >> >> >> --Reinier Zwitserloot >> Like it? Tip it! >> http://tipit.to >> >> >> >> On Apr 1, 2009, at 20:26, Tom Hawtin wrote: >> >>> Christian Fischer wrote: >>>> These $-operators doesn't seem intuitive to me, but replacing >>>> equal- >>>> calls >>>> sounds interesting. >>>> >>>> Maybe a better solution would be something like this: >>>> if (a eq b) // equals >>>> if (a ne b) // not equal >>>> if (a lt b) // lesser than >>>> if (a le b) // lesser or equal >>> >>> Along with other concerns, four new keywords?! Theoretically they >>> could >>> be context sensitive, but then we are boxing in the grammar. >>> >>> If something like this were to be done (and let's face it, operator >>> overloading ain't gonna happen in JDK7), then I think there needs to >>> be >>> to changes in fundamental direction of the proposal. >>> >>> * We need new symbols. .<. and the like were proposed in another >>> similar proposal. So long as the symbol is a sequence of characters >>> which is not valid in an existing Java program (outside of comments >>> and >>> literal strings). >>> >>> * I think it's clear that we can't use Comparable.compareTo and >>> Object.equals. It requires a new method for each operator. >>> >>> Tom >>> >> >> >> > From mthornton at optrak.co.uk Thu Apr 2 05:48:15 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Thu, 02 Apr 2009 13:48:15 +0100 Subject: Proposal: Sameness operators In-Reply-To: <49D4AF9D.9090407@sun.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <49D4AF9D.9090407@sun.com> Message-ID: <49D4B40F.2010100@optrak.co.uk> Tom Hawtin wrote: > Reinier Zwitserloot wrote: > >> Why can't we use compareTo and equals? >> > > * compareTo may well be unreasonably inefficient. > * equals handles nulls (asymmetrically), compareTo does not > * equals does test-and-cast (event for generic types - urgh), > compareTo uses generics > * equals does not throw ClassCastException, compareTo does (but > probably shouldn't with generics) > > Therefore, new methods please. I'm sure you are aware the whole subject > of operator overloading in general is a minefield. > a.compareTo(b) == 0 and a.equals(b) are not always the same, sometimes for very good reasons. I seem to remember that there is at least one such class in the Java platform. Mark Thornton From rssh at gradsoft.com.ua Thu Apr 2 05:56:20 2009 From: rssh at gradsoft.com.ua (rssh at gradsoft.com.ua) Date: Thu, 2 Apr 2009 15:56:20 +0300 (EEST) Subject: Helping to find the usefulness of a proposal In-Reply-To: <64efa1ba0904020515m679910b4n1be9cce0034e474d@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <64efa1ba0904020515m679910b4n1be9cce0034e474d@mail.gmail.com> Message-ID: <7a2038dee31c8246dde1340615ec8b3a.squirrel@wmail.gradsoft.ua> > This would be useful. > > One might be able to start by building on the infrastructure in > Checkstyle, PMD or FindBugs for some of these. I don't know about > FindBugs, but the other two allow you to write your own matching > rules. Jackpot could be used as well, but it's no longer maintained as > an independent project (now part of NB refactoring infrastructure). > One would have to use a slightly older version of it. > With JavaChecker infrastructure (http://redmine.gradsoft.ua/projects/show/javachecker) it's easy to write declarative rules for counting source-code patterns. For example, rule for catching exception with empty catch block look's like: catch($x,Block(NIL)) -> true [ violationDiscovered(EmptyCatchBlock, "empty catch block",$x) ]. And as I know, this is one tool, which contains own Java resolver. (jackport can use javacc resolver, CheckStyle and PMD does not have resolvers yet; FindBugs work with .class files, so it can check only compiled stuff). But I will have time to write rules only during next week-end; if anybody want to write this rules earlier - I recommend use JavaChecker as starting point Reading sources and some introductory article: (for example http://www.gradsoft.ua/eng/whitepapers/secr2008/secr2008-1.html) must be enough for starting hacking. > > > Patrick > > From david.goodenough at linkchoose.co.uk Thu Apr 2 06:07:21 2009 From: david.goodenough at linkchoose.co.uk (David Goodenough) Date: Thu, 2 Apr 2009 14:07:21 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> Message-ID: <200904021407.24330.david.goodenough@linkchoose.co.uk> On Thursday 02 April 2009, Stephen Colebourne wrote: > All, > One possible way I'd like to suggest that the coin evaluation could be > helped would be to write a script to find out how frequently the > specific issue comes up in real code. > > It should be possible to devise, write and run a script to find the > number of LOCs affected by many of the proposals. For example: > > - strings in switch (find if else on constant strings) > - multi-catch (find duplicate catch blocks) > - elvis operator (find ternary and if else defaulting) > - for each where the iterator remove can be accessed (% of loops that > access iterator) > - for each where index is needed (% of loops that use int looping) > - method and field literals > - byte and short literals > and probably many others (I've just listed some proposals I remember) > > Ideally, any script would be ASM/BCEL based, but grep style might work too. > > I mention all this because I don't have the spare time to write such a > script, but if you do, then I'm sure we'd all like to run it and > discuss the results ;-) > > Stephen As a matter of interest, how would you go about finding the instances of the problem that my lightweight properties proposal aims to solve, i.e. field names in strings (binding frameworks, SQL and Criteria strings, and PropertyChangeSupport events). You could always just build a list of fields and look for all strings that contained those string values (they might be EL strings, or parts of an SQL statement), but I think you would come up with a large number of false positives. There are plenty of instances of this out there, but I am not at all sure how you would count them accurately. This lack of ability to check them was of course the point of needing a solution. David From rssh at gradsoft.com.ua Thu Apr 2 06:10:39 2009 From: rssh at gradsoft.com.ua (rssh at gradsoft.com.ua) Date: Thu, 2 Apr 2009 16:10:39 +0300 (EEST) Subject: Helping to find the usefulness of a proposal In-Reply-To: <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> Message-ID: Yes, yet one idea - create poll, where each proposal is listed with link and rated from -5 to 5 // -5 - I strongly against this in Java; +5 - I strongly for; 0 - neutral. (by default all is null)) and publish somewhere. // better different instances for controlled and non-controlled auditory. It will be interesting. > 2009/4/2 Stephen Colebourne : >> All, >> One possible way I'd like to suggest that the coin evaluation could be >> helped would be to write a script to find out how frequently the >> specific issue comes up in real code. >> >> It should be possible to devise, write and run a script to find the >> number of LOCs affected by many of the proposals. For example: >> >> - strings in switch (find if else on constant strings) >> - multi-catch (find duplicate catch blocks) >> - elvis operator (find ternary and if else defaulting) >> - for each where the iterator remove can be accessed (% of loops that >> access iterator) >> - for each where index is needed (% of loops that use int looping) >> - method and field literals >> - byte and short literals >> and probably many others (I've just listed some proposals I remember) >> >> Ideally, any script would be ASM/BCEL based, but grep style might work >> too. >> >> I mention all this because I don't have the spare time to write such a >> script, but if you do, then I'm sure we'd all like to run it and >> discuss the results ;-) >> >> Stephen >> >> > > We may list all proposals and write opinions & statistics (as we think). > > -- > Pozdrowionka. / Regards. > Lasu aka Marek Kozie?? > > http://lasu2string.blogspot.com/ > > From mthornton at optrak.co.uk Thu Apr 2 06:14:24 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Thu, 02 Apr 2009 14:14:24 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <200904021407.24330.david.goodenough@linkchoose.co.uk> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <200904021407.24330.david.goodenough@linkchoose.co.uk> Message-ID: <49D4BA30.8070702@optrak.co.uk> David Goodenough wrote: > On Thursday 02 April 2009, Stephen Colebourne wrote: > >> All, >> One possible way I'd like to suggest that the coin evaluation could be >> helped would be to write a script to find out how frequently the >> specific issue comes up in real code. >> >> It should be possible to devise, write and run a script to find the >> number of LOCs affected by many of the proposals. For example: >> >> - strings in switch (find if else on constant strings) >> - multi-catch (find duplicate catch blocks) >> - elvis operator (find ternary and if else defaulting) >> - for each where the iterator remove can be accessed (% of loops that >> access iterator) >> - for each where index is needed (% of loops that use int looping) >> - method and field literals >> - byte and short literals >> and probably many others (I've just listed some proposals I remember) >> >> Ideally, any script would be ASM/BCEL based, but grep style might work too. >> >> I mention all this because I don't have the spare time to write such a >> script, but if you do, then I'm sure we'd all like to run it and >> discuss the results ;-) >> >> Stephen >> > > As a matter of interest, how would you go about finding the instances of > the problem that my lightweight properties proposal aims to solve, i.e. > There are a number of types of change which are hard to verify or quantify using existing code. For example escape analysis may fail to show benefits from eliminating allocation because the programmers have already done it manually. In particular they might have used integer loops instead of an iterator when looping over an ArrayList. I still have quite a few old style loops simply because there hasn't been a sufficiently good reason to change them yet. Mark Thornton From rssh at gradsoft.com.ua Thu Apr 2 06:14:44 2009 From: rssh at gradsoft.com.ua (rssh at gradsoft.com.ua) Date: Thu, 2 Apr 2009 16:14:44 +0300 (EEST) Subject: Helping to find the usefulness of a proposal In-Reply-To: <200904021407.24330.david.goodenough@linkchoose.co.uk> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <200904021407.24330.david.goodenough@linkchoose.co.uk> Message-ID: <2d40714ad6407ff97935bcf5acf6b1fc.squirrel@wmail.gradsoft.ua> > As a matter of interest, how would you go about finding the instances of > the problem that my lightweight properties proposal aims to solve, i.e. .... afraid none = scripts will works only for simple proposals. From markmahieu at googlemail.com Thu Apr 2 06:25:15 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Thu, 2 Apr 2009 14:25:15 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> Message-ID: Wow. http://www.geekherocomic.com/comics-highres/2009-02-25-coding-overkill.png Here are the important bits from my quick hack. Took under half an hour to get it finding cases where Auto-assignment Parameters would and wouldn't work across large source trees. Of course, javac makes much more than parsing available if you need it... import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.parser.JavacParser; import com.sun.tools.javac.parser.ParserFactory; import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; ... // create a TreeScanner to do your analysis TreeScanner scanner = new TreeScanner() { @Override public void visitMethodDef(JCMethodDecl tree) { // look at a method's parameters for (List l = params; l.nonEmpty(); l = l.tail) { JCVariableDecl param = l.head; // examine param or whatever } // continue recursively scanning the method body etc super.visitMethodDef(tree); } }; ... Context context = new Context(); JavacFileManager.preRegister(context); ParserFactory factory = ParserFactory.instance(context); String sourceCode = readSourceFromFile(...); JavacParser parser = (JavacParser) factory.newParser(sourceCode, false, false, false); JCCompilationUnit cu = parser.parseCompilationUnit(); // do your analysis scanner.scan(cu); From misterm at gmail.com Thu Apr 2 06:34:05 2009 From: misterm at gmail.com (Michael Nascimento) Date: Thu, 2 Apr 2009 10:34:05 -0300 Subject: Helping to find the usefulness of a proposal In-Reply-To: References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> Message-ID: <389b9d740904020634u321941d0l9c61c56d9d7ea295@mail.gmail.com> Using JDK 6, you can write an annotation processor for all sources that uses the Tree API for that. Regards, Michael Nascimento Santos https://genesis.dev.java.net/ https://jsr-310.dev.java.net/ On Thu, Apr 2, 2009 at 10:25 AM, Mark Mahieu wrote: > Wow. > > http://www.geekherocomic.com/comics-highres/2009-02-25-coding-overkill.png > > > Here are the important bits from my quick hack. ?Took under half an hour to > get it finding cases where Auto-assignment Parameters would and wouldn't > work across large source trees. > > Of course, javac makes much more than parsing available if you need it... > > > > import com.sun.tools.javac.file.JavacFileManager; > import com.sun.tools.javac.parser.JavacParser; > import com.sun.tools.javac.parser.ParserFactory; > import com.sun.tools.javac.tree.TreeScanner; > import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; > import com.sun.tools.javac.tree.JCTree.JCMethodDecl; > import com.sun.tools.javac.tree.JCTree.JCVariableDecl; > import com.sun.tools.javac.util.Context; > import com.sun.tools.javac.util.List; > > ... > > // create a TreeScanner to do your analysis > TreeScanner scanner = new TreeScanner() { > > @Override > public void visitMethodDef(JCMethodDecl tree) { > ?// look at a method's parameters > for (List l = params; l.nonEmpty(); l = l.tail) { > JCVariableDecl param = l.head; > ?// examine param or whatever > } > ?// continue recursively scanning the method body etc > super.visitMethodDef(tree); > } > }; > > ... > > Context context = new Context(); > JavacFileManager.preRegister(context); > ParserFactory factory = ParserFactory.instance(context); > > String sourceCode = readSourceFromFile(...); > > JavacParser parser = (JavacParser) factory.newParser(sourceCode, false, > false, false); > JCCompilationUnit cu = parser.parseCompilationUnit(); > > // do your analysis > scanner.scan(cu); > > From markmahieu at googlemail.com Thu Apr 2 06:47:26 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Thu, 2 Apr 2009 14:47:26 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <389b9d740904020634u321941d0l9c61c56d9d7ea295@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <389b9d740904020634u321941d0l9c61c56d9d7ea295@mail.gmail.com> Message-ID: Yep, which is a better option if the code is going to be more than a quick throwaway. The advantage with using the javac versions of those types is that you get familiarity with other APIs you need to interact with when building an actual prototype... Mark 2009/4/2 Michael Nascimento > Using JDK 6, you can write an annotation processor for all sources > that uses the Tree API for that. > > Regards, > Michael Nascimento Santos > https://genesis.dev.java.net/ > https://jsr-310.dev.java.net/ > > On Thu, Apr 2, 2009 at 10:25 AM, Mark Mahieu > wrote: > > Wow. > > > > > http://www.geekherocomic.com/comics-highres/2009-02-25-coding-overkill.png > > > > > > Here are the important bits from my quick hack. Took under half an hour > to > > get it finding cases where Auto-assignment Parameters would and wouldn't > > work across large source trees. > > > > Of course, javac makes much more than parsing available if you need it... > > > > > > > > import com.sun.tools.javac.file.JavacFileManager; > > import com.sun.tools.javac.parser.JavacParser; > > import com.sun.tools.javac.parser.ParserFactory; > > import com.sun.tools.javac.tree.TreeScanner; > > import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; > > import com.sun.tools.javac.tree.JCTree.JCMethodDecl; > > import com.sun.tools.javac.tree.JCTree.JCVariableDecl; > > import com.sun.tools.javac.util.Context; > > import com.sun.tools.javac.util.List; > > > > ... > > > > // create a TreeScanner to do your analysis > > TreeScanner scanner = new TreeScanner() { > > > > @Override > > public void visitMethodDef(JCMethodDecl tree) { > > // look at a method's parameters > > for (List l = params; l.nonEmpty(); l = l.tail) { > > JCVariableDecl param = l.head; > > // examine param or whatever > > } > > // continue recursively scanning the method body etc > > super.visitMethodDef(tree); > > } > > }; > > > > ... > > > > Context context = new Context(); > > JavacFileManager.preRegister(context); > > ParserFactory factory = ParserFactory.instance(context); > > > > String sourceCode = readSourceFromFile(...); > > > > JavacParser parser = (JavacParser) factory.newParser(sourceCode, false, > > false, false); > > JCCompilationUnit cu = parser.parseCompilationUnit(); > > > > // do your analysis > > scanner.scan(cu); > > > > > > From david.goodenough at linkchoose.co.uk Thu Apr 2 06:28:25 2009 From: david.goodenough at linkchoose.co.uk (David Goodenough) Date: Thu, 2 Apr 2009 14:28:25 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <2d40714ad6407ff97935bcf5acf6b1fc.squirrel@wmail.gradsoft.ua> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <200904021407.24330.david.goodenough@linkchoose.co.uk> <2d40714ad6407ff97935bcf5acf6b1fc.squirrel@wmail.gradsoft.ua> Message-ID: <200904021428.26371.david.goodenough@linkchoose.co.uk> On Thursday 02 April 2009, rssh at gradsoft.com.ua wrote: > > As a matter of interest, how would you go about finding the instances of > > the problem that my lightweight properties proposal aims to solve, i.e. > > .... afraid none = scripts will works only for simple proposals. Well I suppose a first pass would simply be to count all occurences of String values who's value matched a field name, but how deep do you go looking for fields - probably just in the user's code not the libraries even though you would then miss lots of PropertyChange fires and all the named properties inside Swing. Could your code do the simple string == fieldname scan? That would under-count, but it would be a start. David From rssh at gradsoft.com.ua Thu Apr 2 07:18:26 2009 From: rssh at gradsoft.com.ua (rssh at gradsoft.com.ua) Date: Thu, 2 Apr 2009 17:18:26 +0300 (EEST) Subject: Helping to find the usefulness of a proposal In-Reply-To: <200904021428.26371.david.goodenough@linkchoose.co.uk> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <200904021407.24330.david.goodenough@linkchoose.co.uk> <2d40714ad6407ff97935bcf5acf6b1fc.squirrel@wmail.gradsoft.ua> <200904021428.26371.david.goodenough@linkchoose.co.uk> Message-ID: <69bcb3eed8382ed8d1ca39bc49797501.squirrel@wmail.gradsoft.ua> > On Thursday 02 April 2009, rssh at gradsoft.com.ua wrote: >> > As a matter of interest, how would you go about finding the instances >> of >> > the problem that my lightweight properties proposal aims to solve, >> i.e. >> >> .... afraid none = scripts will works only for simple proposals. > > Well I suppose a first pass would simply be to count all occurences of > String values who's value matched a field name, but how deep do you > go looking for fields - probably just in the user's code not the libraries > even though you would then miss lots of PropertyChange fires and > all the named properties inside Swing. > > Could your code do the simple string == fieldname scan? That would > under-count, but it would be a start. > Yes, this is possible. But if we have class X with field "fx", than String "fx" somewhere in class Y - how count this ? This can be undercount or overcount. Knowledge about Y import (i. e. X is accessible from X or not) also give us nothing, because exists possibility, that this is something generic in Y. So, we can receive some counts and they would have some correlation with property access, but all with some level of 'vagueness' in interpretation. > David > > From david.goodenough at linkchoose.co.uk Thu Apr 2 07:29:27 2009 From: david.goodenough at linkchoose.co.uk (David Goodenough) Date: Thu, 2 Apr 2009 15:29:27 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <69bcb3eed8382ed8d1ca39bc49797501.squirrel@wmail.gradsoft.ua> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <200904021428.26371.david.goodenough@linkchoose.co.uk> <69bcb3eed8382ed8d1ca39bc49797501.squirrel@wmail.gradsoft.ua> Message-ID: <200904021529.29938.david.goodenough@linkchoose.co.uk> On Thursday 02 April 2009, rssh at gradsoft.com.ua wrote: > > On Thursday 02 April 2009, rssh at gradsoft.com.ua wrote: > >> > As a matter of interest, how would you go about finding the instances > >> > >> of > >> > >> > the problem that my lightweight properties proposal aims to solve, > >> > >> i.e. > >> > >> .... afraid none = scripts will works only for simple proposals. > > > > Well I suppose a first pass would simply be to count all occurences of > > String values who's value matched a field name, but how deep do you > > go looking for fields - probably just in the user's code not the > > libraries even though you would then miss lots of PropertyChange fires > > and all the named properties inside Swing. > > > > Could your code do the simple string == fieldname scan? That would > > under-count, but it would be a start. > > Yes, this is possible. But if we have class X with field "fx", than String > "fx" somewhere in class Y - how count this ? > This can be undercount or overcount. > Knowledge about Y import (i. e. X is accessible from X or not) also give > us nothing, because exists possibility, that this is something generic in > Y. > > So, we can receive some counts and they would have some correlation with > property access, but all with some level of 'vagueness' in interpretation. It would be a start I suppose. It would probably overcount, but then this test is also missing all the field names embedded in Criteria or similar APIs and in SQL and related beasts. David > > > David From peter.levart at gmail.com Thu Apr 2 07:33:49 2009 From: peter.levart at gmail.com (Peter Levart) Date: Thu, 2 Apr 2009 16:33:49 +0200 Subject: Proposal: Automatic Resource Management In-Reply-To: <370F8DB1-A374-43B4-9F83-ABCD5A925D93@zwitserloot.com> References: <370F8DB1-A374-43B4-9F83-ABCD5A925D93@zwitserloot.com> Message-ID: I apologise! The code snipped submitted by Bob Lee is not flawed at all as I have suggested in my previous message. I did not read ARM specification correctly. Nevertheless with increasing number of resources managed by a single ARM construct, the track of which method has thrown exception and why is lost. This is also true if to many statements that can throw the same exception are written in a single try block. Ideally all thrown exceptions should be individually accessible together within a single block (being catch or finally block I don't know which). This way any additional logic can act on the whole failure context. So in this respect my proposed construct is no better because it separates exception thrown in initialization and try block from exceptions thrown in clean-up code which are accessible in finally block. I understand that sometimes one just wants to be passed a single variable that holds the "most meaningful" exception thrown among several and that is what ARM proposal is trying to solve. A programmer using ARM construct will have to evaluate whether ARM is the correct tool for the particular problem and not blindly accept it because it is the correct tool for most problems (and it is so easy to use). On the other hand the try-catch-finally statement as we have now in Java is always the right tool (if used correctly) but it unfortunately can too easily be used incorrectly. Regards, Peter From reinier at zwitserloot.com Thu Apr 2 08:18:25 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 2 Apr 2009 17:18:25 +0200 Subject: Helping to find the usefulness of a proposal In-Reply-To: References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> Message-ID: <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> Polling has many, many problems associated with it: 1. It does not reliably measure impact. Let's say generics gets a 9.0 in the polls, and the foreach loop gets only an 8.0. The right answer is to implement foreach, eventhough it scored lower. It's easier and has less impact. implementing difficulty can be decided by an expert group, but there's also the concept of impact. A nice case in point: Almost everyone rated operator support for BigDecimal and BigInteger as very low in Stephen Colebourne's polls, but is that reflective? I don't think so. It's just the one with the lowest impact - no body cares about that a lot, and some care about it not at all. It is, however, hard to see how operator support for BigDecimal/BigInteger can break, well, anything. The value of any proposal is its positive impact divided by its negative impact, and dividing by a very small number gives you a very large number. 2. Not all know about intricacies. For example, with generics, I bet many who vocally supported them did not know the details about reification, the sheer complexity of co/contra-variance (which just cannot be simplified, the core concept is difficult, period), etcetera. By not being aware of the weight put on future expansions and patchy stopgaps in the proposal itself, some proposals that are technically (but not obviously) complex get an unfairly inflated poll score. Perhaps a fairer way would be to first reduce the list to a manageable number, and then to poll, but only amongst those who have attempted to read and fully grok all proposals on the list, and can be expected to know enough repercussions to make a fair analysis, and to poll not just on 'how much would you like this in java?' but also on 'how much would you NOT like this in java?' - in order to give the simpler stuff like e.g. operators for BigDecimal/Integer a fighting chance. How do you determine that someone is both skilled enough to understand AND has attempted to grok all proposals on the short-list? I have no idea. --Reinier Zwitserloot On Apr 2, 2009, at 15:10, rssh at gradsoft.com.ua wrote: > > > Yes, yet one idea - create poll, where each proposal is listed with > link > and rated from -5 to 5 > // -5 - I strongly against this in Java; +5 - I strongly for; 0 - > neutral. > (by default all is null)) and publish somewhere. > // better different instances for controlled and non-controlled > auditory. > > It will be interesting. > > > >> 2009/4/2 Stephen Colebourne : >>> All, >>> One possible way I'd like to suggest that the coin evaluation >>> could be >>> helped would be to write a script to find out how frequently the >>> specific issue comes up in real code. >>> >>> It should be possible to devise, write and run a script to find the >>> number of LOCs affected by many of the proposals. For example: >>> >>> - strings in switch (find if else on constant strings) >>> - multi-catch (find duplicate catch blocks) >>> - elvis operator (find ternary and if else defaulting) >>> - for each where the iterator remove can be accessed (% of loops >>> that >>> access iterator) >>> - for each where index is needed (% of loops that use int looping) >>> - method and field literals >>> - byte and short literals >>> and probably many others (I've just listed some proposals I >>> remember) >>> >>> Ideally, any script would be ASM/BCEL based, but grep style might >>> work >>> too. >>> >>> I mention all this because I don't have the spare time to write >>> such a >>> script, but if you do, then I'm sure we'd all like to run it and >>> discuss the results ;-) >>> >>> Stephen >>> >>> >> >> We may list all proposals and write opinions & statistics (as we >> think). >> >> -- >> Pozdrowionka. / Regards. >> Lasu aka Marek Kozie?? >> >> http://lasu2string.blogspot.com/ >> >> > > > From Joe.Darcy at Sun.COM Thu Apr 2 08:27:56 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 02 Apr 2009 08:27:56 -0700 Subject: Helping to find the usefulness of a proposal In-Reply-To: <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> Message-ID: <49D4D97C.5090808@sun.com> Reinier Zwitserloot wrote: > Polling has many, many problems associated with it: > I will treat any polling information as strictly informative and in no way binding on the decisions that get made. Polling is the limit case of design by committee and not well-suited to technical decisions. -Joe From rssh at gradsoft.com.ua Thu Apr 2 09:09:28 2009 From: rssh at gradsoft.com.ua (rssh at gradsoft.com.ua) Date: Thu, 2 Apr 2009 19:09:28 +0300 (EEST) Subject: Helping to find the usefulness of a proposal In-Reply-To: <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> Message-ID: > Polling has many, many problems associated with it: > yes. But we have no other ways to know 'meaning of mass'. I. e. 'design by poll' is not good idea, but 'design without any information from real word' is not good idea also. It's well-known problem in sociology, where, unlike computer science, we have no correct instruments at all. Exists some 'non-direct' ways to know how correct is poll: controlled auditories, same poll in different cases, but all this is not panacea. > 1. It does not reliably measure impact. Let's say generics gets a 9.0 > in the polls, and the foreach loop gets only an 8.0. The right answer > is to implement foreach, eventhough it scored lower. It's easier and > has less impact. implementing difficulty can be decided by an expert > group, but there's also the concept of impact. > Yes. I think all understand this. // btw, near all proposals in project coin are easy implementable. > A nice case in point: Almost everyone rated operator support for > BigDecimal and BigInteger as very low in Stephen Colebourne's polls, > but is that reflective? I don't think so. It's just the one with the > lowest impact - no body cares about that a lot, and some care about it > not at all. It is, however, hard to see how operator support for > BigDecimal/BigInteger can break, well, anything. The value of any > proposal is its positive impact divided by its negative impact, and > dividing by a very small number gives you a very large number. > I also have question to Stephen polls: i. e. I can't understand why multiline strings rated so low. Anybody, who works with databases know, that analyzing query plan or copy non-trivial query test in java is a big pain, and most of Java project in corporate sector use non-trivial sql queris". Only one answer, which I can suggest - that auditory which attend Java conferences does not reflect auditory of Java users: most of Java conferences attenders do system programming or research and have nothing with most of database projects which is not so interesting and rare have academics interest. To verify this, possible repeat his poll on some programmer event, which is not so academics. > 2. Not all know about intricacies. For example, with generics, I bet > many who vocally supported them did not know the details about > reification, the sheer complexity of co/contra-variance (which just > cannot be simplified, the core concept is difficult, period), > etcetera. By not being aware of the weight put on future expansions > and patchy stopgaps in the proposal itself, some proposals that are > technically (but not obviously) complex get an unfairly inflated poll > score. > Filtration by proposal size, as I know, already was done. > > > Perhaps a fairer way would be to first reduce the list to a manageable > number, and then to poll, but only amongst those who have attempted to > read and fully grok all proposals on the list, and can be expected to Or just does not touch proposals, which was not readed. (mark as 0, 'neutral') > know enough repercussions to make a fair analysis, and to poll not > just on 'how much would you like this in java?' but also on 'how much > would you NOT like this in java?' - in order to give the simpler stuff > like e.g. operators for BigDecimal/Integer a fighting chance. How do Yes. > you determine that someone is both skilled enough to understand AND > has attempted to grok all proposals on the short-list? I have no idea. > 'Skilled enough', sorry, I think that people, which skilled enough prefer haskell and will poll for haskell-like features, which is not ordinary Java programmer want ;) Also will be wery interested difference between this audience (subscribers of the list) and general audience of Java programmers. Note, that I does not propose use polls as one and only one criteria. I just tell that see result of such poll will be interest. // btw - from other side, all this activity is overkill, I can suggest, // that accepted proposals would be exactly same, which was listed in // project-coin description (before coin was started) // http://blogs.sun.com/darcy/entry/project_coin // +ARM +jsr292 and ... it's already 6, which is more than 5 :) I. e. doing project coin with external auditory was a 'Sun system error', I guess; if they want some feedback from community, correct way was at first implement own stuff, than ask community for something new ;) > > --Reinier Zwitserloot > > > > On Apr 2, 2009, at 15:10, rssh at gradsoft.com.ua wrote: > >> >> >> Yes, yet one idea - create poll, where each proposal is listed with >> link >> and rated from -5 to 5 >> // -5 - I strongly against this in Java; +5 - I strongly for; 0 - >> neutral. >> (by default all is null)) and publish somewhere. >> // better different instances for controlled and non-controlled >> auditory. >> >> It will be interesting. >> >> >> >>> 2009/4/2 Stephen Colebourne : >>>> All, >>>> One possible way I'd like to suggest that the coin evaluation >>>> could be >>>> helped would be to write a script to find out how frequently the >>>> specific issue comes up in real code. >>>> >>>> It should be possible to devise, write and run a script to find the >>>> number of LOCs affected by many of the proposals. For example: >>>> >>>> - strings in switch (find if else on constant strings) >>>> - multi-catch (find duplicate catch blocks) >>>> - elvis operator (find ternary and if else defaulting) >>>> - for each where the iterator remove can be accessed (% of loops >>>> that >>>> access iterator) >>>> - for each where index is needed (% of loops that use int looping) >>>> - method and field literals >>>> - byte and short literals >>>> and probably many others (I've just listed some proposals I >>>> remember) >>>> >>>> Ideally, any script would be ASM/BCEL based, but grep style might >>>> work >>>> too. >>>> >>>> I mention all this because I don't have the spare time to write >>>> such a >>>> script, but if you do, then I'm sure we'd all like to run it and >>>> discuss the results ;-) >>>> >>>> Stephen >>>> >>>> >>> >>> We may list all proposals and write opinions & statistics (as we >>> think). >>> >>> -- >>> Pozdrowionka. / Regards. >>> Lasu aka Marek Kozie????? >>> >>> http://lasu2string.blogspot.com/ >>> >>> >> >> >> > > From reinier at zwitserloot.com Thu Apr 2 09:15:22 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 2 Apr 2009 18:15:22 +0200 Subject: Proposal: Sameness operators In-Reply-To: <49D4B40F.2010100@optrak.co.uk> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <49D4AF9D.9090407@sun.com> <49D4B40F.2010100@optrak.co.uk> Message-ID: <27F0EA9D-8936-4330-A5FE-97F522C290F0@zwitserloot.com> The argument that .compareTo should not be used because it isn't entirely congruent with either the meaning of .equals() or the meanings of all the comparison operators (from == to <) on the primitives, just doesn't hold water, for this simple reason: They make absolutely no sense now, either, and nobody cares about that. Here's some fun facts (all asserts are true): int x = 0/0; //ArithmeticException double x = 0/0.0; //okay, x = NaN double y = 0/0.0; assert x != y; assert ! (x == y); assert Double.valueOf(x).equals(Double.valueOf(y)); //WTF! assert Double.valueOf(x).equals(y); //WTF! Clearly, equals is fundamentally broken. We need a new equals! Oh no! assert ! (x < y); assert ! (x <= y); assert Double.valueOf(x).compareTo(y) == 0; //WTF! So, compareTo is broken as well. Just like equals is. assert x < "foo"; //Compiler Error: Cant compare those two. assert Double.valueOf(x).compareTo("foo"); //With java 1.4: Runtime error. assert Double.valueOf(x).compareTo("foo"); //With java 1.5+: Compile time error. A compiler error is better, but these two results certainly are consistent. In fact, in java 1.5+, you DO get a compiler error. So, if x < "foo" would be rewritten to the version below that after comparison operator support is added that uses compareTo, you get roughly the same situation: A compiler error that tells you that the compiler didn't expect a String there. The exact text of the error is slightly different, but other than that, it's the same. Why is this a problem? The fix to me seems relatively simple: 1. Anything that is legal now needs to stay legal. I would write down the rules for this, except they are totally nuts, as the above samples show. So, just do whatever java 6 does for everything that would have been legal in 6. In particular, this involves unboxing both sides if both sides can be unboxed. And unbox one side if the other side is a numeric primitive. Yes, this leads to crazy puzzlers, such as: Double x = Double.valueOf(Double.NaN); double y = 0; if ( x != y && !(x < y) && !(x > y) ) System.out.println("This line prints? Whoa!"); But that's what we're stuck with. Unless Lovatt's and my crazy idea of breaking backwards compatibility with an explicit source keyword is implemented, this craziness can't go away, we're stuck with it. 2. First unbox whatever can be unboxed, then continue to: 3. If either LHS or RHS implements Comparable, we'll use that. Note that primitives do not implement Comparable. Comparison operations between primitives are hardcoded into the JLS spec. If both sides do implement Comparable, LHS wins. If only the RHS does, the order is mathematically reversed (a > b becomes b < a). If the winning HS is willing to take Number according to the generics bound of Comparable (which means RAW types *DO*, as they take all objects), then numeric primitives are boxed. If neither side implements Comparable, compiler error. If a side does, but the type of the other side isn't compatible with Comparable's bound, or is a non-numeric primitive (boolean - char is actually numeric, because this didn't look quite enough like a Salvador Dali painting yet, go figure) you get a compile-time error, even if the other way around would have worked. 4. BigDecimal and BigInteger are changed to implement Comparable instead. The fact that they currently don't is something I don't really understand would consider filing as a bug if I worked more with mixed BI/BD and primitives math. By doing this, something like: 5 < new BigInteger("10") would work out the way you expect it to (that would return 'true'). BI/BD's comparison methods can't just convert the incoming primitive to a BI/BD, because NaN and the infinities don't convert, yet the answer to this expression: Double.NEGATIVE_INFINITY < BigInteger.ZERO should clearly be true. The above plan can make that happen by adding more logic to BI/BD's compareTo methods. The reason Double and company need to unbox is because their implementations of compareTo can then stay blissfully unaware of BI and BD's existence. There's a problem if you attempt to compare 2 numeric entities that aren't hardcoded into the JVM, but I don't think a perfect solution is possible here. This proposal is not entirely consistent with the primitive's compare operators, but attempting to be consistent with the current mess that is comparison operators between primitives is not a goal that we should aspire to, IMO. The concept of 'I'll give you an answer if there is a mathematical answer, and if there isn't, I will give you a compile-time error if I can, and a runtime error otherwise' seems perfect to me. That's compareTo's current semantics, so, lucky us! NB: Attempting to integrate equality into compareTo is probably a bad idea, eventhough we are stuck with some funny puzzlers where equality and comparison clearly aren't consistent. The real problem is that numeric equality is just different from object equality (numerically, NaN is not equal to NaN, but as objects, they are, and asking if apple == pear makes no sense numerically, but as objects, there's a logical answer: No, they aren't). I don't see us getting out of that one. Possibly use <> as an operator that specifically means: Not Numerically equal, and !<> as numerically equal. Yeah, that doesn't really look too readable to me either. --Reinier Zwitserloot On Apr 2, 2009, at 14:48, Mark Thornton wrote: > Tom Hawtin wrote: >> Reinier Zwitserloot wrote: >> >>> Why can't we use compareTo and equals? >>> >> >> * compareTo may well be unreasonably inefficient. >> * equals handles nulls (asymmetrically), compareTo does not >> * equals does test-and-cast (event for generic types - urgh), >> compareTo uses generics >> * equals does not throw ClassCastException, compareTo does (but >> probably shouldn't with generics) >> >> Therefore, new methods please. I'm sure you are aware the whole >> subject of operator overloading in general is a minefield. >> > a.compareTo(b) == 0 and a.equals(b) are not always the same, > sometimes for very good reasons. I seem to remember that there is at > least one such class in the Java platform. > > Mark Thornton > From develop4lasu at gmail.com Thu Apr 2 10:34:24 2009 From: develop4lasu at gmail.com (=?UTF-8?Q?Marek_Kozie=C5=82?=) Date: Thu, 2 Apr 2009 19:34:24 +0200 Subject: Helping to find the usefulness of a proposal In-Reply-To: References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> Message-ID: <28bca0ff0904021034w40f2c5d1nfa8b574e99f61a11@mail.gmail.com> As pool I would suggest, while [yes/no] do not give any knowledge: Problem: -> Analyzed(0~5~6) // did you took much time to analyze it? // (0 = no) (5 = a lot) -> IHadSuchProblem(0~5~6) // how often you had such problem ? (0 = no) (5 = often) (6 = almost all time) -> IWouldUseIt(0~5~6) // would you use in new JDK ? (0 = no) (5= a lot) -> Problems(0~5~6[,sample]) // like: to many interactions, to complicated, potential problems .... (0 = none) (5 = a lot) -> OtherSolutionWouldSolveProblem(0~5~6[,SolutionName]) // do you know other solution (0 = do not know any) (5 = in 100%) (6 = 100% and would be better) -> SolutionNotComplete(0~5~6[,description]) // what is missing in yours opinion? (0 = none) (5 = incomplete) -> Except(0~5~6,what) // some parts of this solution should be removed (0 = none) -> Extend(0~5~6,what) // this soultion need to be extended to work correctly (0 = no need) (5 = to weak to solve problem at current version) where (in YOUR opinion): 0 : none ~ 5 : much 6 : very much Like: [Marek Kozie?] StringInSwitch: -> Analyzed(5) -> IHadSuchProblem(3) -> IWouldUseIt(1) -> Problems(3) -> OtherSolutionWouldSolveProblem(6,enum) -> SolutionNotComplete(5,onlyForStaticData) -> Exclude(0) -> Extend(6,dynamicData comparator) NextSolution/Proposal: ... Explanation: -> Analyzed(5) : I took a lot of time to analyze it -> IHadSuchProblem(3) : i had it some times -> IWouldUseIt(1) : I think this solution have no much use for me (to weak = no dynamic data). -> Problems(3) : would cause bad style -> OtherSolutionWouldSolveProblem(6,enum) : can have all those and more -> SolutionNotComplete(5,onlyForStaticData) : -> Exclude(0) : nothing to exclude -> Extend(6,dynamicData asymetricComparator) : should be extended with ... and It would help a lot This could be parsed to bring some critical informations (like potential problem). -- Pozdrowionka. / Regards. Lasu aka Marek Kozie? http://lasu2string.blogspot.com/ From mthornton at optrak.co.uk Thu Apr 2 10:42:21 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Thu, 02 Apr 2009 18:42:21 +0100 Subject: Proposal: Sameness operators In-Reply-To: <27F0EA9D-8936-4330-A5FE-97F522C290F0@zwitserloot.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <49D4AF9D.9090407@sun.com> <49D4B40F.2010100@optrak.co.uk> <27F0EA9D-8936-4330-A5FE-97F522C290F0@zwitserloot.com> Message-ID: <49D4F8FD.4080909@optrak.co.uk> Reinier Zwitserloot wrote: > The argument that .compareTo should not be used because it isn't > entirely congruent with either the meaning of .equals() or the > meanings of all the comparison operators (from == to <) on the > primitives, just doesn't hold water, for this simple reason: > I merely meant that if you want to have a set of comparison operators with some of them based on compareTo, then they all must be based on compareTo --- you can't use equals (or ==) for the equality comparisons. Therefore you have three sets of operations ==, System.identityHashCode(), plus for some types <, <=, >, >= Object.equals(), Object.hashCode() Comparable.compareTo() All these need to remain clearly distinct because their existing behaviour is not always compatible. Mark Thornton From Jonathan.Gibbons at Sun.COM Thu Apr 2 11:16:09 2009 From: Jonathan.Gibbons at Sun.COM (Jonathan Gibbons) Date: Thu, 02 Apr 2009 11:16:09 -0700 Subject: Helping to find the usefulness of a proposal In-Reply-To: References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> Message-ID: <49D500E9.3050106@sun.com> For all this sort of analysis, you'd do better to use the combination of javac's annotation processing framework and the javac Tree API, than to use direct access into private javac API. Annotation processing isn't just for processing annotations ;-) You can write a processor that will be called on all types, and you can bridge from the processing world (javax.lang.model.*) to the java Tree API (com.sun.source.*) using com.sun.source.util.Trees. This allows you to write utilities to analyze ASTs without requiring the use of any javac internal API. -- Jon Mark Mahieu wrote: > Wow. > > http://www.geekherocomic.com/comics-highres/2009-02-25-coding-overkill.png > > > Here are the important bits from my quick hack. Took under half an hour to > get it finding cases where Auto-assignment Parameters would and wouldn't > work across large source trees. > > Of course, javac makes much more than parsing available if you need it... > > > > import com.sun.tools.javac.file.JavacFileManager; > import com.sun.tools.javac.parser.JavacParser; > import com.sun.tools.javac.parser.ParserFactory; > import com.sun.tools.javac.tree.TreeScanner; > import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; > import com.sun.tools.javac.tree.JCTree.JCMethodDecl; > import com.sun.tools.javac.tree.JCTree.JCVariableDecl; > import com.sun.tools.javac.util.Context; > import com.sun.tools.javac.util.List; > > ... > > // create a TreeScanner to do your analysis > TreeScanner scanner = new TreeScanner() { > > @Override > public void visitMethodDef(JCMethodDecl tree) { > // look at a method's parameters > for (List l = params; l.nonEmpty(); l = l.tail) { > JCVariableDecl param = l.head; > // examine param or whatever > } > // continue recursively scanning the method body etc > super.visitMethodDef(tree); > } > }; > > ... > > Context context = new Context(); > JavacFileManager.preRegister(context); > ParserFactory factory = ParserFactory.instance(context); > > String sourceCode = readSourceFromFile(...); > > JavacParser parser = (JavacParser) factory.newParser(sourceCode, false, > false, false); > JCCompilationUnit cu = parser.parseCompilationUnit(); > > // do your analysis > scanner.scan(cu); > > From mthornton at optrak.co.uk Thu Apr 2 11:31:51 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Thu, 02 Apr 2009 19:31:51 +0100 Subject: Proposal: Sameness operators In-Reply-To: <27F0EA9D-8936-4330-A5FE-97F522C290F0@zwitserloot.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <49D4AF9D.9090407@sun.com> <49D4B40F.2010100@optrak.co.uk> <27F0EA9D-8936-4330-A5FE-97F522C290F0@zwitserloot.com> Message-ID: <49D50497.4020801@optrak.co.uk> Reinier Zwitserloot wrote: > > BI/BD's comparison methods can't just convert the incoming primitive > to a BI/BD, because NaN and the infinities don't convert, yet the > answer to this expression: > > Double.NEGATIVE_INFINITY < BigInteger.ZERO > > should clearly be true. The above plan can make that happen by adding > more logic to BI/BD's compareTo methods. The 754R decimal format does include NaN and +-infinite, so perhaps the answer here is to modify Java's BigDecimal to match. Joe could probably tell us more about the possibility of such a change. Mark Thornton From Joe.Darcy at Sun.COM Thu Apr 2 11:33:45 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 02 Apr 2009 11:33:45 -0700 Subject: Helping to find the usefulness of a proposal In-Reply-To: <49D500E9.3050106@sun.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <49D500E9.3050106@sun.com> Message-ID: <49D50509.4020909@sun.com> On 04/02/09 11:16 AM, Jonathan Gibbons wrote: > For all this sort of analysis, you'd do better to use the combination of > javac's > annotation processing framework and the javac Tree API, than to use direct > access into private javac API. > > Annotation processing isn't just for processing annotations ;-) You can > write > a processor that will be called on all types, and you can bridge from the > processing world (javax.lang.model.*) to the java Tree API > (com.sun.source.*) > using com.sun.source.util.Trees. This allows you to write utilities to > analyze ASTs without requiring the use of any javac internal API. > +1 The annotation processing in javac with JSR 269 (and apt before it) is a general purpose meta-programming framework. Combined with the javac tree API, many program analyses can be performed. -Joe > -- Jon > > > > Mark Mahieu wrote: > >> Wow. >> >> http://www.geekherocomic.com/comics-highres/2009-02-25-coding-overkill.png >> >> >> Here are the important bits from my quick hack. Took under half an hour to >> get it finding cases where Auto-assignment Parameters would and wouldn't >> work across large source trees. >> >> Of course, javac makes much more than parsing available if you need it... >> >> >> >> import com.sun.tools.javac.file.JavacFileManager; >> import com.sun.tools.javac.parser.JavacParser; >> import com.sun.tools.javac.parser.ParserFactory; >> import com.sun.tools.javac.tree.TreeScanner; >> import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; >> import com.sun.tools.javac.tree.JCTree.JCMethodDecl; >> import com.sun.tools.javac.tree.JCTree.JCVariableDecl; >> import com.sun.tools.javac.util.Context; >> import com.sun.tools.javac.util.List; >> >> ... >> >> // create a TreeScanner to do your analysis >> TreeScanner scanner = new TreeScanner() { >> >> @Override >> public void visitMethodDef(JCMethodDecl tree) { >> // look at a method's parameters >> for (List l = params; l.nonEmpty(); l = l.tail) { >> JCVariableDecl param = l.head; >> // examine param or whatever >> } >> // continue recursively scanning the method body etc >> super.visitMethodDef(tree); >> } >> }; >> >> ... >> >> Context context = new Context(); >> JavacFileManager.preRegister(context); >> ParserFactory factory = ParserFactory.instance(context); >> >> String sourceCode = readSourceFromFile(...); >> >> JavacParser parser = (JavacParser) factory.newParser(sourceCode, false, >> false, false); >> JCCompilationUnit cu = parser.parseCompilationUnit(); >> >> // do your analysis >> scanner.scan(cu); >> >> >> > > > From reinier at zwitserloot.com Thu Apr 2 11:53:18 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 2 Apr 2009 20:53:18 +0200 Subject: Proposal: Sameness operators In-Reply-To: <49D4F8FD.4080909@optrak.co.uk> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <49D4AF9D.9090407@sun.com> <49D4B40F.2010100@optrak.co.uk> <27F0EA9D-8936-4330-A5FE-97F522C290F0@zwitserloot.com> <49D4F8FD.4080909@optrak.co.uk> Message-ID: Why must == also run off of compareTo? (Or, alternatively, why do you - need- an equality-checking operation based on compareTo that isn't ==)? Java cannot enforce contracts in that way; for example, it's perfectly legal syntactically, eventhough you're breaking the API contract, to always "return 1;" in response to a compareTo. Unless an actual compare operation attempts both the stated comparison and the mathematically equivalent reverse (a < b and b > a) and throws an exception if the results aren't equal, there's no guarantee that compareTo makes any sense. The current situation with boxing primitives is that == and <> and extremely inconsistent; new Double(5) vs. new Double(5) isn't == equal, but they are equal as far as compareTo is concerned. Nevertheless, people -do- apply comparisons in java. Making it easier ought to help. To further complicate things, introducing a new Comparable-like interface that doesn't suffer from these problems as badly (for example by wanting an enum back instead of a positive/ negative/zero value) will not be compatible with the existing Comparable, which would be awkard for HashSet. My point is thus: There is a perfect world, and java doesn't have it. And it never will. Either we do this, or we give up and never have any sort of improvement to the comparable situation. If that's the choice, I want comparator operators, even with the glitches. --Reinier Zwitserloot On Apr 2, 2009, at 19:42, Mark Thornton wrote: > Reinier Zwitserloot wrote: >> The argument that .compareTo should not be used because it isn't >> entirely congruent with either the meaning of .equals() or the >> meanings of all the comparison operators (from == to <) on the >> primitives, just doesn't hold water, for this simple reason: >> > I merely meant that if you want to have a set of comparison > operators with some of them based on compareTo, then they all must > be based on compareTo --- you can't use equals (or ==) for the > equality comparisons. Therefore you have three sets of operations > > ==, System.identityHashCode(), plus for some types <, <=, >, >= > > Object.equals(), Object.hashCode() > > Comparable.compareTo() > > All these need to remain clearly distinct because their existing > behaviour is not always compatible. > > Mark Thornton > > > > From mthornton at optrak.co.uk Thu Apr 2 12:18:29 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Thu, 02 Apr 2009 20:18:29 +0100 Subject: Proposal: Sameness operators In-Reply-To: References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <49D4AF9D.9090407@sun.com> <49D4B40F.2010100@optrak.co.uk> <27F0EA9D-8936-4330-A5FE-97F522C290F0@zwitserloot.com> <49D4F8FD.4080909@optrak.co.uk> Message-ID: <49D50F85.4040401@optrak.co.uk> Reinier Zwitserloot wrote: > My point is thus: There is a perfect world, and java doesn't have it. > And it never will. Either we do this, or we give up and never have any > sort of improvement to the comparable situation. If that's the choice, > I want comparator operators, even with the glitches. > A new set of operators like (==), (<), etc, all based on compareTo would work, but I don't know how likely such a change is. In their favour, these operators would NOT be overloaded so the usual complaints about operators wouldn't apply. Mark From peter.levart at gmail.com Thu Apr 2 12:30:10 2009 From: peter.levart at gmail.com (Peter Levart) Date: Thu, 2 Apr 2009 21:30:10 +0200 Subject: Proposal: Automatic Resource Management In-Reply-To: <370F8DB1-A374-43B4-9F83-ABCD5A925D93@zwitserloot.com> References: <370F8DB1-A374-43B4-9F83-ABCD5A925D93@zwitserloot.com> Message-ID: Hello Coiners! I played with ARM a little more and also considered Reinier Zwitserloot's remarks to my idea of making ARM more SARM (Semi Automatic Resource Management). I apologise again of accusing Bob Lee's example as flawed. Now that I fully understand Joshua Bloch's ARM proposal, I'm convinced that it's exception suppressing logic is correct for most usage scenarios. One weakness that the ARM spec does not address yet is about how AutomaticResource interface should be handled in obscure situations of multiple inheritance. So I'm still trying to get rid of the need for special interface altogether. Here's my second take: try (InputStream in = new FileInputStream(inputFile); in.close()) { // try block } catch(IOException e) { // catch block } finally { // finally block } ... to be translated into: try { InputStream in = new FileInputStream(inputFile); boolean $$suppress = false; try { // try block } catch (final Throwable $$t) { $$suppress = true; throw $$t; } finally { if ($$suppress) try { in.close(); } catch (Throwable $$ignore) {} else in.close(); } } catch (IOException e) { // catch block } finally { // finally block } ... that's not much different from Joshua's original proposal. In fact it uses the same exception suppressing logic. There are only 3 differences: - does not use a special interface - disposal is explicit (Semi Automatic) - handles only a single resource But with both "catch" and "finally" parts as optional, the following: try (InputStream in = new FileInputStream(inputFile); in.close()) { // try block } ... is translated into: { InputStream in = new FileInputStream(inputFile); boolean $$suppress = false; try { // try block } catch (final Throwable $$t) { $$suppress = true; throw $$t; } finally { if ($$suppress) try { in.close(); } catch (Throwable $$ignore) {} else in.close(); } } ... and so, single-resource SARM constructs can then be nested to construct for example this: try (InputStream in = new FileInputStream(inputFile); in.close()) { try (OutputStream out = new FileOutputStream(outputFile); out.close()) { // try block } } catch(IOException e) { // catch block } ... one more with locking: ReadWriteLock rwl = ... try (rwl.writeLock().lock(); rwl.writeLock().unlock()) { i++; } That's it. What dou you think? Regards, Peter From develop4lasu at gmail.com Thu Apr 2 12:33:10 2009 From: develop4lasu at gmail.com (=?UTF-8?Q?Marek_Kozie=C5=82?=) Date: Thu, 2 Apr 2009 21:33:10 +0200 Subject: Proposal: Automatic Resource Management In-Reply-To: References: Message-ID: <28bca0ff0904021233u2fae0949tb0a9c4171cd9ab1e@mail.gmail.com> 2009/4/2 Peter Levart : > Hello Coiners! > > The debate about ARM proposal has calmed down lately and I was thinking > about it last few days. Initially I submitted a comment that got lost by > list processor and was about using a "marker" interface as a supertype of > sigle-method disposable interfaces like this: > > > package java.lang; > > public interface AutomaticResource {} > > > ... and for example, retroffiting java.io.Closeable: > > > package java.io; > > public interface Closeable extends AutomaticResource { > ? ?void close() throws IOException; > } > > > ... this way even the name of the method would not be "coined". There would > have to be some rules that compiler will enforce to make sure it can > uniquely identify the method to be called on resource disposal (for example: > the static type of the resource should not directly or indirectly implement > or extend two different single-method interfaces marked with > AutomaticResource marker superinterface). > > But then I thought. Why would this language feature even have to be tied to > a particular interface. The "foreach" loop did take this approach with > java.lang.Iterable, but this had nothing to do with exceptions and catching > them and ignoring them silently. A language construct that hides this often > cited "bad practice" under the carpet is no good! > > For example, this snippet of code, written to the proposed ARM spec., > submited by Bob Lee in this thread a month ago, asking Neal Gafter to > demonstrate how the equivalent BGGA version would look like: > > ?try (InputStream in = new FileInputStream(src); > ? ? ?OutputStream out = new FileOutputStream(dest)) { > ? ?byte[] buf = new byte[8 * 1024]; > ? ?int n; > ? ?while ((n = in.read(buf)) >= 0) > ? ? ?out.write(buf, 0, n); > ?} catch (IOException e) { > ? ?showDialog("Copy failed."); > ?} > > ... is flawed. This code does not guarantee that in the absence of shown > exception the file has been copied in it's intirety. > > Ignoring exception thrown on an InputStream.close() might be desireable, but > ignoring exception thrown on OutputStream.close() migh mean that you don't > mind missing writing some final bytes into the file. Closing OutputStream > should not be part of automatic resource disposal but part of main code > block. This brings us to the question how is ARM supposed to be able do > differentiate InputStream from OutputStream if both implement Closeable? > > So I thought how to circumvent these two weeknesses. My take on this is > something like the following: > > > ? ? ? ?try (InputStream in = new FileInputStream("inputFile"); > ? ? ? ? ? ? OutputStream out = new FileOutputStream("outputFile")) > ? ? ? ?{ > ? ? ? ? ?// try body > ? ? ? ?} > ? ? ? ?catch (IOException e) > ? ? ? ?{ > ? ? ? ? ?// catch body > ? ? ? ?} > ? ? ? ?finally (IOException e1 : in.close(); > ? ? ? ? ? ? ? ? IOException e2 : out.close()) > ? ? ? ?{ > ? ? ? ? ?// finally body > ? ? ? ?} > > > ... would be translated to ... > > > ? ? ? ?{ > ? ? ? ? ? ?IOException e1 = null; > ? ? ? ? ? ?IOException e2 = null; > > ? ? ? ? ? ?try > ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ?InputStream in = new FileInputStream("inputFile"); > > ? ? ? ? ? ? ? ?try > ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ?OutputStream out = new FileOutputStream("outputFile"); > > ? ? ? ? ? ? ? ? ? ?try > ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ?// try body > ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ? ? ?finally > ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ?try > ? ? ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ? ? ?out.close(); > ? ? ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ? ? ? ? ?catch (IOException $$e) > ? ? ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ? ? ?e2 = $$e; > ? ? ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?finally > ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ?try > ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ?in.close(); > ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ? ? ?catch (IOException $$e) > ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ?e1 = $$e; > ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?} > ? ? ? ? ? ?} > ? ? ? ? ? ?catch (IOException e) > ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ?// catch body > ? ? ? ? ? ?} > ? ? ? ? ? ?finally > ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ?// finally body > ? ? ? ? ? ?} > ? ? ? ?} > > > > ... no special interfaces are used here. The code to dispose of resources is > clearly visible (it has to be writen, yes, but that also means that it can > be read, which is a good thing). > > The above example is the "full monty" version. The thing to note is that a > try (...; ...; ...) construct is to be matched by an optional finally (...; > ...; ...) construct in that both, if the second is specified, must have an > equal number of semicolons. Each "statement" in the try construct gets it's > own slot that must be matched by the coresponding slot in the finally (...; > ...; ...) construct. Any slot in finally construct can be left empty (like > any of the 3 slots in the for (;;) statement). > > The following minimal version is also possible (in this example no catching > of exceptions on resource cleanup is attempted): > > int i, j; > ReadWriteLock iLock = ...; > ReadWriteLock jLock = ...; > > // ... > > try (jLock.readLock().lock(); iLock.writeLock().lock()) { > ?i += j; > } > finally (jLock.readLock().unlock(); iLock.writeLock().unlock()) > > > ... gets translated to: > > > { > ? ?jLock.readLock().lock(); > ? ?try { > ? ? ?iLock.writeLock().lock(); > ? ? ?try { > ? ? ? ?i += j; > ? ? ?} > ? ? ?finally { > ? ? ? ?iLock.writeLock().unlock(); > ? ? ?} > ? ?} > ? ?finally { > ? ? ?jLock.readLock().unlock(); > ? ?} > } > > > All this will have to be formalized. This is just an idea to keep the debate > going. > > Regards, Peter > > If I can I would suggest: try (InputStream in = new FileInputStream("inputFile"); OutputStream out = new FileOutputStream("outputFile")) { // try body } catch (IOException e) { // catch body } finally (IOException e1 : in.close(); IOException e2 : out.close()) { // finally body } change to: catch: catch(variable = Type); catch(variable = Type exceptionVariable){}; catch(Type exceptionVariable){}; allow mix try with new : new try Constructor catch ....; variable would be null is exception occurs. IOException exception = null; InputStream in = new try FileInputStream("inputFile") catch (exception = IOException); if (in == null) return ...; OutputStream out = new try FileOutputStream("outputFile")) catch (exception = IOException); if ( (in != null) && (out != null) ) try{ ... } catch (exception = IOException); if (in != null) try {in.close(); } catch (exception = IOException); if (out != null) try {out.close(); } catch (exception = IOException); if (exception != null) throw exception; ... But I didn't analyzed all interactions. for locks I still think that they should be done by: synchronize.write(lock){} -- Pozdrowionka. / Regards. Lasu aka Marek Kozie? http://lasu2string.blogspot.com/ From develop4lasu at gmail.com Thu Apr 2 12:48:30 2009 From: develop4lasu at gmail.com (=?UTF-8?Q?Marek_Kozie=C5=82?=) Date: Thu, 2 Apr 2009 21:48:30 +0200 Subject: PROPOSAL: 'final' without explicit type In-Reply-To: <87zlf0pduc.fsf@mid.deneb.enyo.de> References: <28bca0ff0903261305x2de00436r5ca8183fe01578d4@mail.gmail.com> <87fxgwzfew.fsf@mid.deneb.enyo.de> <28bca0ff0903291422s77f11c44j4ddf6ea45ec0b669@mail.gmail.com> <87zlf0pduc.fsf@mid.deneb.enyo.de> Message-ID: <28bca0ff0904021248t336d38d2tb1b4a7d8a6d51137@mail.gmail.com> 2009/4/1 Florian Weimer : > * Marek Kozie?: > >> ? ? ? void noInterection(T t,K k){ >> ? ? ? ? ? ? ? if (boo)t=k; // Type mismatch: cannot convert from K to T >> ? ? ? ? ? ? ? ... >> ? ? ? } > > The assignment is not type-safe anyway, as the following modification > shows: > > > ? ? ? ? T noInterection(T t,K k){ > ? ? ? ? ? ? ? ?if (boo)t=k; // Type mismatch: cannot convert from K to T > ? ? ? ? ? ? ? ?return t; > ? ? ? ?} > > This would allow to convert values of any type which implements I1 and > I2 to any other type which implements the two interfaces, which is > clearly bogus. > > Consequently, I think your snippet doesn't show what you claim. > I wanted to show when assignment is possible : Intersection : I1 & I2 Bounds : $ extends I1 & I2 Intersection = Bounds // OK Intersection = Intersection // OK Bounds = Intersection // Error Bounds = Bounds // Error -- Pozdrowionka. / Regards. Lasu aka Marek Kozie? http://lasu2string.blogspot.com/ From Joe.Darcy at Sun.COM Thu Apr 2 12:48:54 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 02 Apr 2009 12:48:54 -0700 Subject: Helping to find the usefulness of a proposal In-Reply-To: References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> Message-ID: <49D516A6.6000404@sun.com> On 04/02/09 09:09 AM, rssh at gradsoft.com.ua wrote: >> Polling has many, many problems associated with it: >> >> > > yes. But we have no other ways to know 'meaning of mass'. I. e. 'design > by poll' is not good idea, but 'design without any information from real > word' is not good idea also. > > It's well-known problem in sociology, where, unlike computer science, we > have no correct instruments at all. Exists some 'non-direct' ways > to know how correct is poll: controlled auditories, same poll in different > cases, but all this is not panacea. > > >> 1. It does not reliably measure impact. Let's say generics gets a 9.0 >> in the polls, and the foreach loop gets only an 8.0. The right answer >> is to implement foreach, eventhough it scored lower. It's easier and >> has less impact. implementing difficulty can be decided by an expert >> group, but there's also the concept of impact. >> >> > > Yes. I think all understand this. > // btw, near all proposals in project coin are easy implementable. > I do not share that opinion. There are no simple language changes in Java. Given the relative scarcity of prototypes, to say nothing of prototypes with a thorough test suite, we can at best make informed estimates of the difficulty of various changes, but I'm certain there will be surprises down the line, as there were for every JDK 5 language change. >> A nice case in point: Almost everyone rated operator support for >> BigDecimal and BigInteger as very low in Stephen Colebourne's polls, >> but is that reflective? I don't think so. It's just the one with the >> lowest impact - no body cares about that a lot, and some care about it >> not at all. It is, however, hard to see how operator support for >> BigDecimal/BigInteger can break, well, anything. The value of any >> proposal is its positive impact divided by its negative impact, and >> dividing by a very small number gives you a very large number. >> >> > > I also have question to Stephen polls: i. e. I can't understand why > multiline strings rated so low. Anybody, who works with databases > know, that analyzing query plan or copy non-trivial query test > in java is a big pain, and most of Java project in corporate sector use > non-trivial sql queris". > Only one answer, which I can suggest - that auditory which attend Java > conferences does not reflect auditory of Java users: most of Java > conferences attenders do system programming or research and have nothing > with most of database projects which is not so interesting and rare > have academics interest. > To verify this, possible repeat his poll on some programmer event, which > is not so academics. > On this point, I've long thought the Java platform is like the elephant in the parable about the blind men and the elephant: http://en.wikipedia.org/wiki/Blind_Men_and_an_Elephant That is, while each of us may know and understand our own usage of Java quite and well and have valid ideas about how Java could be changed to improve programming in our own areas of interest (properties! operator overloading! design by contract! your favorite feature!), evolving the platform with an eye toward optimizing it *as a whole* will mean at least some areas don't get what they want. [snip] > Note, that I does not propose use polls as one and only one criteria. I > just tell that see result of such poll will be interest. > > // btw - from other side, all this activity is overkill, I can suggest, > // that accepted proposals would be exactly same, which was listed in > // project-coin description (before coin was started) > // http://blogs.sun.com/darcy/entry/project_coin > // +ARM +jsr292 and ... it's already 6, which is more than 5 :) > Your own sentence disproves your point since ARM was not listed among the five proposal areas under consideration before Project Coin started. > I. e. doing project coin with external auditory was a 'Sun system error', > I guess; if they want some feedback from community, correct way was at > first implement own stuff, than ask community for something new ;) > The call of proposal phase of Project Coin is an effort both to solicit feedback from the external community and also to invite the external community to participate more directly in evolving the language. That opportunity to participate also implies participating in the large amount of work required to go from "I have this great idea!" to "I have this great idea and here is a carefully considered review of all the implications of the idea, along with a prototype." The blogs I wrote last year and the proposal form itself are part of an effort to explain and expose what this language work entails so more people can get involved. Unfortunately, many of the submitted proposals did not do a credible job of analyzing the true effect the proposal would have, which has a rather strong relation to why many were not chosen for further consideration. For example, let's take the "'This' type" proposal: http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000107.html Including a this type/self type notion in a programming language type system is a well-studied problem in type systems; as I sent to the list, papers continue to be written on this topic in the programming language literature. It known to *not* be a simple change to the type system. Let's look at the specification section of the proposal: > SPECIFICATION: > (I did not have time to analyze this completely.) > The analysis is the part that matters most! This proposal appears completely oblivious to and ignorant of the large amount of prior work on this topic. It is not as if the notion of adding a self type to Java is a new idea; there is already a Sun bug for this from several years ago: 6479372 Add self types (type of 'this' aka ThisClass) to the language http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6479372 So in total, this "proposal" added *nothing* to the understanding of what adding a this type to Java would mean and how the change could be done. Those factors weighed quite strongly in why this particular proposal did not more on to "for further consideration." Language design, especially additions to an existing language, is not an endeavor where enthusiasm can overcome lack of diligence and expertise. -Joe From markmahieu at googlemail.com Thu Apr 2 13:53:45 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Thu, 2 Apr 2009 21:53:45 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <49D500E9.3050106@sun.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <49D500E9.3050106@sun.com> Message-ID: Hi Jon, Invoking the parser directly seemed like the quickest way of grabbing some figures at the time, but you (and Michael) are quite right of course. The main point I was trying to get across was there are easily approachable ways that people can attempt to do some of the analysis Stephen mentioned, without ripping components out of Netbeans etc to do it, great though they may be. But I shouldn't be spreading my bad habits around with abandon like that, quick hack or not :) My apologies. Mark 2009/4/2 Jonathan Gibbons > For all this sort of analysis, you'd do better to use the combination of > javac's > annotation processing framework and the javac Tree API, than to use direct > access into private javac API. > > Annotation processing isn't just for processing annotations ;-) You can > write > a processor that will be called on all types, and you can bridge from the > processing world (javax.lang.model.*) to the java Tree API > (com.sun.source.*) > using com.sun.source.util.Trees. This allows you to write utilities to > analyze ASTs without requiring the use of any javac internal API. > > -- Jon > > > > > Mark Mahieu wrote: > >> Wow. >> >> http://www.geekherocomic.com/comics-highres/2009-02-25-coding-overkill.png >> >> >> Here are the important bits from my quick hack. Took under half an hour >> to >> get it finding cases where Auto-assignment Parameters would and wouldn't >> work across large source trees. >> >> Of course, javac makes much more than parsing available if you need it... >> >> >> >> import com.sun.tools.javac.file.JavacFileManager; >> import com.sun.tools.javac.parser.JavacParser; >> import com.sun.tools.javac.parser.ParserFactory; >> import com.sun.tools.javac.tree.TreeScanner; >> import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; >> import com.sun.tools.javac.tree.JCTree.JCMethodDecl; >> import com.sun.tools.javac.tree.JCTree.JCVariableDecl; >> import com.sun.tools.javac.util.Context; >> import com.sun.tools.javac.util.List; >> >> ... >> >> // create a TreeScanner to do your analysis >> TreeScanner scanner = new TreeScanner() { >> >> @Override >> public void visitMethodDef(JCMethodDecl tree) { >> // look at a method's parameters >> for (List l = params; l.nonEmpty(); l = l.tail) { >> JCVariableDecl param = l.head; >> // examine param or whatever >> } >> // continue recursively scanning the method body etc >> super.visitMethodDef(tree); >> } >> }; >> >> ... >> >> Context context = new Context(); >> JavacFileManager.preRegister(context); >> ParserFactory factory = ParserFactory.instance(context); >> >> String sourceCode = readSourceFromFile(...); >> >> JavacParser parser = (JavacParser) factory.newParser(sourceCode, false, >> false, false); >> JCCompilationUnit cu = parser.parseCompilationUnit(); >> >> // do your analysis >> scanner.scan(cu); >> >> >> > > From develop4lasu at gmail.com Thu Apr 2 13:59:02 2009 From: develop4lasu at gmail.com (=?UTF-8?Q?Marek_Kozie=C5=82?=) Date: Thu, 2 Apr 2009 22:59:02 +0200 Subject: Helping to find the usefulness of a proposal In-Reply-To: <49D516A6.6000404@sun.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> <49D516A6.6000404@sun.com> Message-ID: <28bca0ff0904021359v4ea9aa05i1ed7782f60c7e84e@mail.gmail.com> 2009/4/2 Joe Darcy : > On 04/02/09 09:09 AM, rssh at gradsoft.com.ua wrote: >>> Polling has many, many problems associated with it: >>> >>> >> >> ?yes. ?But we have no other ways to know 'meaning of mass'. I. e. 'design >> by poll' is not good idea, but 'design without any information from real >> word' is not good idea also. >> >> It's well-known problem in sociology, where, unlike computer science, we >> ?have no correct instruments at all. Exists some 'non-direct' ways >> ?to know how correct is poll: controlled auditories, same poll in different >> cases, but all this is not panacea. >> >> >>> 1. It does not reliably measure impact. Let's say generics gets a 9.0 >>> in the polls, and the foreach loop gets only an 8.0. The right answer >>> is to implement foreach, eventhough it scored lower. It's easier and >>> has less impact. implementing difficulty can be decided by an expert >>> group, but there's also the concept of impact. >>> >>> >> >> ?Yes. I think all understand this. >> // btw, near all proposals in project coin are easy implementable. >> > > I do not share that opinion. > > There are no simple language changes in Java. > > Given the relative scarcity of prototypes, to say nothing of prototypes > with a thorough test suite, we can at best make informed estimates of > the difficulty of various changes, but I'm certain there will be > surprises down the line, as there were for every JDK 5 language change. > >>> A nice case in point: Almost everyone rated operator support for >>> BigDecimal and BigInteger as very low in Stephen Colebourne's polls, >>> but is that reflective? I don't think so. It's just the one with the >>> lowest impact - no body cares about that a lot, and some care about it >>> not at all. It is, however, hard to see how operator support for >>> BigDecimal/BigInteger can break, well, anything. The value of any >>> proposal is its positive impact divided by its negative impact, and >>> dividing by a very small number gives you a very large number. >>> >>> >> >> I also have question to Stephen polls: i. e. I can't understand why >> multiline strings rated so low. ?Anybody, who works with databases >> ?know, that analyzing query plan or copy non-trivial query test >> ?in java is a big pain, and most of Java project in corporate sector use >> non-trivial sql queris". >> ? Only one answer, which I can suggest - that auditory which attend Java >> conferences does not reflect auditory of Java users: most of Java >> conferences attenders do system programming or research and have nothing >> with most of ?database projects which is not so interesting and rare >> have academics interest. >> ? To verify this, possible repeat his poll on some programmer event, which >> is not so academics. >> > > On this point, I've long thought the Java platform is like the elephant > in the parable about the blind men and the elephant: > > ? ?http://en.wikipedia.org/wiki/Blind_Men_and_an_Elephant > > That is, while each of us may know and understand our own usage of Java > quite and well and have valid ideas about how Java could be changed to > improve programming in our own areas of interest (properties! operator > overloading! design by contract! ?your favorite feature!), evolving the > platform ?with an eye toward optimizing it *as a whole* will ?mean at > least some areas don't get what they want. > > [snip] > >> Note, that I does not propose use polls as one and only one criteria. I >> just tell that see result of such poll will be interest. >> >> // btw - from other side, all this activity is overkill, I can suggest, >> // that ?accepted proposals would be exactly same, which was listed in >> // project-coin description (before coin was started) >> // ? ? http://blogs.sun.com/darcy/entry/project_coin >> // ? +ARM ?+jsr292 ?and ... ?it's already 6, which is more than 5 :) >> > > Your own sentence disproves your point since ARM was not listed among > the five proposal areas under consideration before Project Coin started. > >> I. e. doing project coin with external auditory ?was a 'Sun system error', >> I guess; if they want some feedback from community, correct way was at >> first implement own stuff, than ask community for something new ;) >> > > The call of proposal phase of Project Coin is an effort both to solicit > feedback from the external community and also to invite the external > community to participate more directly in evolving the language. ?That > opportunity to participate also implies participating in the large > amount of work required to go from "I have this great idea!" to "I have > this great idea and here is a carefully considered review of all the > implications of the idea, along with a prototype." ?The blogs I wrote > last year and the proposal form itself are part of an effort to explain > and expose what this language work entails so more people can get involved. > > Unfortunately, many of the submitted proposals did not do a credible job > of analyzing the true effect the proposal would have, which has a rather > strong relation to why many were not chosen for further consideration. > For example, let's take the "'This' type" proposal: > > ? ?http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000107.html > > Including a this type/self type notion in a programming language type > system is a well-studied problem in type systems; as I sent to the list, > papers continue to be written on this topic in the programming language > literature. ?It known to *not* be a simple change to the type system. > Let's look at the specification section of the proposal: > >> SPECIFICATION: >> (I did not have time to analyze this completely.) >> > > The analysis is the part that matters most! ?This proposal appears > completely oblivious to and ignorant of the large amount of prior work > on this topic. > > It is not as if the notion of adding a self type to Java is a new idea; > there is already a Sun bug for this from several years ago: > > ? ?6479372 Add self types (type of 'this' aka ThisClass) to the language > ? ?http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6479372 > > So in total, this "proposal" added *nothing* to the understanding of > what adding a this type to Java would mean and how the change could be done. > > Those factors weighed quite strongly in why this particular proposal did > not more on to "for further consideration." > > Language design, especially additions to an existing language, is not an > endeavor where enthusiasm can overcome lack of diligence and expertise. > > -Joe > > > YES I do make mistakes. You already said that. While I'm against splitting Java into more languages, I'll be happy even if one proposal will make Java better and more frendly. So if you think that i didn't helped at all then remove me from the group. -- Pozdrowionka. / Regards. Lasu aka Marek Kozie? http://lasu2string.blogspot.com/ From Jonathan.Gibbons at Sun.COM Thu Apr 2 14:02:54 2009 From: Jonathan.Gibbons at Sun.COM (Jonathan Gibbons) Date: Thu, 02 Apr 2009 14:02:54 -0700 Subject: Helping to find the usefulness of a proposal In-Reply-To: References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <49D500E9.3050106@sun.com> Message-ID: <49D527FE.3050105@sun.com> Mark, Quick hacks are good. My point was just that once you know the coding pattern, it can be even easier/quicker to hack up an annotation processor to do what you want than to learn the innards of the compiler. The internal API has never been intended for public consumption, and there are often undocumented quirks or constraints about individual specific methods, meaning it is very much a case of "proceed at your own risk". The good news is that is now a goal to support utilities such as you all have been describing, and that JSR 199, JSR 269 and the Tree API, are all part of the formal support for such work. -- Jon Mark Mahieu wrote: > Hi Jon, > > Invoking the parser directly seemed like the quickest way of grabbing > some figures at the time, but you (and Michael) are quite right of course. > > The main point I was trying to get across was there are easily > approachable ways that people can attempt to do some of the analysis > Stephen mentioned, without ripping components out of Netbeans etc to > do it, great though they may be. > > But I shouldn't be spreading my bad habits around with abandon like > that, quick hack or not :) > > My apologies. > > Mark > > > 2009/4/2 Jonathan Gibbons > > > For all this sort of analysis, you'd do better to use the > combination of javac's > annotation processing framework and the javac Tree API, than to > use direct > access into private javac API. > > Annotation processing isn't just for processing annotations ;-) > You can write > a processor that will be called on all types, and you can bridge > from the > processing world (javax.lang.model.*) to the java Tree API > (com.sun.source.*) > using com.sun.source.util.Trees. This allows you to write > utilities to > analyze ASTs without requiring the use of any javac internal API. > > -- Jon > > > > > Mark Mahieu wrote: > > Wow. > > http://www.geekherocomic.com/comics-highres/2009-02-25-coding-overkill.png > > > Here are the important bits from my quick hack. Took under > half an hour to > get it finding cases where Auto-assignment Parameters would > and wouldn't > work across large source trees. > > Of course, javac makes much more than parsing available if you > need it... > > > > import com.sun.tools.javac.file.JavacFileManager; > import com.sun.tools.javac.parser.JavacParser; > import com.sun.tools.javac.parser.ParserFactory; > import com.sun.tools.javac.tree.TreeScanner; > import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; > import com.sun.tools.javac.tree.JCTree.JCMethodDecl; > import com.sun.tools.javac.tree.JCTree.JCVariableDecl; > import com.sun.tools.javac.util.Context; > import com.sun.tools.javac.util.List; > > ... > > // create a TreeScanner to do your analysis > TreeScanner scanner = new TreeScanner() { > > @Override > public void visitMethodDef(JCMethodDecl tree) { > // look at a method's parameters > for (List l = params; l.nonEmpty(); l = l.tail) { > JCVariableDecl param = l.head; > // examine param or whatever > } > // continue recursively scanning the method body etc > super.visitMethodDef(tree); > } > }; > > ... > > Context context = new Context(); > JavacFileManager.preRegister(context); > ParserFactory factory = ParserFactory.instance(context); > > String sourceCode = readSourceFromFile(...); > > JavacParser parser = (JavacParser) > factory.newParser(sourceCode, false, > false, false); > JCCompilationUnit cu = parser.parseCompilationUnit(); > > // do your analysis > scanner.scan(cu); > > > > > From Joe.Darcy at Sun.COM Thu Apr 2 14:28:28 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 02 Apr 2009 14:28:28 -0700 Subject: Helping to find the usefulness of a proposal In-Reply-To: <28bca0ff0904021359v4ea9aa05i1ed7782f60c7e84e@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> <49D516A6.6000404@sun.com> <28bca0ff0904021359v4ea9aa05i1ed7782f60c7e84e@mail.gmail.com> Message-ID: <49D52DFC.9020306@sun.com> On 04/02/09 01:59 PM, Marek Kozie? wrote: > 2009/4/2 Joe Darcy : > >> On 04/02/09 09:09 AM, rssh at gradsoft.com.ua wrote: >> >>>> Polling has many, many problems associated with it: >>>> >>>> >>>> > > YES I do make mistakes. > You already said that. > The problem is not that you made mistake; the problem is that despite being informed how and why your your proposals were inadequate, you proceed to submit more than half a dozen other proposals of the same character. > While I'm against splitting Java into more languages, I'll be happy > even if one proposal will make Java better and more frendly. > We do not have a deficiency of ideas for proposals; just in Sun's bug database there are dozens of valid ways to improve the language. The analysis of the proposals is the scarce and valuable factor. > So if you think that i didn't helped at all then remove me from the group > As you wish. -Joe From markmahieu at googlemail.com Thu Apr 2 14:53:23 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Thu, 2 Apr 2009 22:53:23 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <49D516A6.6000404@sun.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> <49D516A6.6000404@sun.com> Message-ID: 2009/4/2 Joe Darcy > > Given the relative scarcity of prototypes, to say nothing of prototypes > with a thorough test suite, we can at best make informed estimates of > the difficulty of various changes, but I'm certain there will be > surprises down the line, as there were for every JDK 5 language change. I'd certainly like to see more prototypes, personally; I find them extremely useful for getting to the details of a proposal. However, is there any value in people building test suites even if they can't put together an actual prototype to test them with? I think there may be. Mark From Ulf.Zibis at gmx.de Thu Apr 2 15:02:26 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 03 Apr 2009 00:02:26 +0200 Subject: Helping to find the usefulness of a proposal In-Reply-To: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> Message-ID: <49D535F2.6060009@gmx.de> Am 02.04.2009 13:39, Stephen Colebourne schrieb: > All, > One possible way I'd like to suggest that the coin evaluation could be > helped would be to write a script to find out how frequently the > specific issue comes up in real code. > > It should be possible to devise, write and run a script to find the > number of LOCs affected by many of the proposals. For example: > > - strings in switch (find if else on constant strings) > More general: - objects and simple expressions in switch (find repetitive+nested usage of if else constructs) -Ulf > - multi-catch (find duplicate catch blocks) > - elvis operator (find ternary and if else defaulting) > - for each where the iterator remove can be accessed (% of loops that > access iterator) > - for each where index is needed (% of loops that use int looping) > - method and field literals > - byte and short literals > and probably many others (I've just listed some proposals I remember) > > Ideally, any script would be ASM/BCEL based, but grep style might work too. > > I mention all this because I don't have the spare time to write such a > script, but if you do, then I'm sure we'd all like to run it and > discuss the results ;-) > > Stephen > > > From Joe.Darcy at Sun.COM Thu Apr 2 15:19:40 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 02 Apr 2009 15:19:40 -0700 Subject: Helping to find the usefulness of a proposal In-Reply-To: References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> <49D516A6.6000404@sun.com> Message-ID: <49D539FC.4050005@sun.com> Mark Mahieu wrote: > 2009/4/2 Joe Darcy > > > Given the relative scarcity of prototypes, to say nothing of prototypes > with a thorough test suite, we can at best make informed estimates of > the difficulty of various changes, but I'm certain there will be > surprises down the line, as there were for every JDK 5 language change. > > > I'd certainly like to see more prototypes, personally; I find them > extremely useful for getting to the details of a proposal. Yes; they can help in writing the specification too :-) > However, is there any value in people building test suites even if they > can't put together an actual prototype to test them with? I think there > may be. I was more so thinking of regression style testing in conjunction with developing a prototype, but having a limited number of independent tests might help too. -Joe From forax at univ-mlv.fr Thu Apr 2 15:25:42 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 03 Apr 2009 00:25:42 +0200 Subject: Helping to find the usefulness of a proposal In-Reply-To: <49D535F2.6060009@gmx.de> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <49D535F2.6060009@gmx.de> Message-ID: <49D53B66.2000509@univ-mlv.fr> Ulf Zibis a ?crit : > Am 02.04.2009 13:39, Stephen Colebourne schrieb: > >> All, >> One possible way I'd like to suggest that the coin evaluation could be >> helped would be to write a script to find out how frequently the >> specific issue comes up in real code. >> >> It should be possible to devise, write and run a script to find the >> number of LOCs affected by many of the proposals. For example: >> >> - strings in switch (find if else on constant strings) >> >> > > More general: > - objects and simple expressions in switch (find repetitive+nested usage > of if else constructs) > > -Ulf > Stephen, Ulf, Strings can be stored, by example, in a HashMap, so finding if a part of a program can be retrofit or not is far from simple. R?mi From brucechapman at paradise.net.nz Thu Apr 2 15:35:52 2009 From: brucechapman at paradise.net.nz (brucechapman at paradise.net.nz) Date: Fri, 03 Apr 2009 11:35:52 +1300 (NZDT) Subject: Helping to find the usefulness of a proposal In-Reply-To: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> Message-ID: <1238711752.49d53dc8e0a4c@www.paradise.net.nz> Good idea, Should they each be evaluated against the same corpus and what would be a suitable corpus? http://en.wikipedia.org/wiki/Corpus_linguistics Bruce Quoting Stephen Colebourne : > All, > One possible way I'd like to suggest that the coin evaluation could be > helped would be to write a script to find out how frequently the > specific issue comes up in real code. > > It should be possible to devise, write and run a script to find the > number of LOCs affected by many of the proposals. For example: > > - strings in switch (find if else on constant strings) > - multi-catch (find duplicate catch blocks) > - elvis operator (find ternary and if else defaulting) > - for each where the iterator remove can be accessed (% of loops that > access iterator) > - for each where index is needed (% of loops that use int looping) > - method and field literals > - byte and short literals > and probably many others (I've just listed some proposals I remember) > > Ideally, any script would be ASM/BCEL based, but grep style might work > too. > > I mention all this because I don't have the spare time to write such a > script, but if you do, then I'm sure we'd all like to run it and > discuss the results ;-) > > Stephen > From Joe.Darcy at Sun.COM Thu Apr 2 16:02:56 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 02 Apr 2009 16:02:56 -0700 Subject: Proposal: Sameness operators In-Reply-To: <275433EA-A420-42C8-891D-3B0C2629222A@zwitserloot.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <4b4f45e00904020524p27741baeo40483e83d71dc768@mail.gmail.com> <275433EA-A420-42C8-891D-3B0C2629222A@zwitserloot.com> Message-ID: <49D54420.5090906@sun.com> Reinier Zwitserloot wrote: [snip] > > public static void is(Object x, Object y) { > if ( x == null ) return y == null; > return x.equals(y); > } > > public static void is(Object x, int y) { > // Yes, you'd need a few gazillion is methods to cover all the > primitives on either side, but 1 static import will grab all of them > } > > ... loads more is methods > > > Then same with lt, gt, le, ge. > > Then you could write: > > if ( is(a, b) ) { > //doStuff > } > > Which is a small improvement. > > Add an ability to specify 'as infix' in static imports, and you have > pretty much what we all want without backwards compatibility issues: > > import static java.lang.Equality.is infix; > > if ( a is b ) { > //do something > } > > I'd consider that a large improvement. Yes, in JDK 7 I'd like to see 6797535 Add shared two argument static equals method to the platform http://bugs.sun.com/view_bug.do?bug_id=6797535 addressed in the platform. I was thinking putting it in a place like a new utility class java.util.Object. -Joe From Joe.Darcy at Sun.COM Thu Apr 2 16:13:36 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 02 Apr 2009 16:13:36 -0700 Subject: Proposal: Sameness operators In-Reply-To: <49D50497.4020801@optrak.co.uk> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <49D4AF9D.9090407@sun.com> <49D4B40F.2010100@optrak.co.uk> <27F0EA9D-8936-4330-A5FE-97F522C290F0@zwitserloot.com> <49D50497.4020801@optrak.co.uk> Message-ID: <49D546A0.4010406@sun.com> Mark Thornton wrote: > Reinier Zwitserloot wrote: >> BI/BD's comparison methods can't just convert the incoming primitive >> to a BI/BD, because NaN and the infinities don't convert, yet the >> answer to this expression: >> >> Double.NEGATIVE_INFINITY < BigInteger.ZERO >> >> should clearly be true. The above plan can make that happen by adding >> more logic to BI/BD's compareTo methods. > The 754R decimal format does include NaN and +-infinite, so perhaps the > answer here is to modify Java's BigDecimal to match. Yes, I actually worked on incorporating the decimal changes into the 754R draft while I was editor :-) The "preferred exponent" nomenclature in the new 754 standard came from the JSR 13 BigDecimal specification work in JDK 5. > Joe could probably tell us more about the possibility of such a change. We don't plan to add the non-finite values and negative zero to the set of values recognized by BigDecimal. If someone wanted to do this, I'd recommend creating a wrapper around BigDecimal that supported the new values and otherwise delegated to an internal BigDecimal. -Joe From rssh at gradsoft.com.ua Thu Apr 2 16:30:27 2009 From: rssh at gradsoft.com.ua (rssh at gradsoft.com.ua) Date: Fri, 3 Apr 2009 02:30:27 +0300 (EEST) Subject: Helping to find the usefulness of a proposal In-Reply-To: <49D516A6.6000404@sun.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> <49D516A6.6000404@sun.com> Message-ID: >> >> Yes. I think all understand this. >> // btw, near all proposals in project coin are easy implementable. >> > > I do not share that opinion. > > There are no simple language changes in Java. > Of course, word 'simple' is relative ;) // And to be correct, I mean proposals upward some quality point. ....... > > On this point, I've long thought the Java platform is like the elephant > in the parable about the blind men and the elephant: > > http://en.wikipedia.org/wiki/Blind_Men_and_an_Elephant > > That is, while each of us may know and understand our own usage of Java > quite and well and have valid ideas about how Java could be changed to > improve programming in our own areas of interest (properties! operator > overloading! design by contract! your favorite feature!), evolving the > platform with an eye toward optimizing it *as a whole* will mean at > least some areas don't get what they want. > Good point. In parable elephants exists and each blinder can touch his part. In our case, for some blinders, elephant must not exists ;))) Even if it can be 'build' in such direction, but we choose not to grow elephant in all directions, because we can't grow quickly. And also exists many group of blinders, near different points of elephants, some groups are big but silent, some are small but loud. Elephant designers are also blinders and guided listening ;) > [snip] > >> Note, that I does not propose use polls as one and only one criteria. I >> just tell that see result of such poll will be interest. >> >> // btw - from other side, all this activity is overkill, I can suggest, >> // that accepted proposals would be exactly same, which was listed in >> // project-coin description (before coin was started) >> // http://blogs.sun.com/darcy/entry/project_coin >> // +ARM +jsr292 and ... it's already 6, which is more than 5 :) >> > > Your own sentence disproves your point since ARM was not listed among > the five proposal areas under consideration before Project Coin started. > I mean not 'would be exactly same, which was listed in project-coin description (before coin was started)[url]', but 'would be exactly same, which was listed in project-coin description (before coin was started)[url] +ARM +jsr292', sorry for ambiguity. ARM floating around (and widly discussed) from late 2007 or early 2008. And all we know, that if BGGA will not available, than at least ARM must be included. I. e. I can't say that ARM is 'external' and new or not to be generally known be included in Java 7 before project coin start. I have no pretension about judgement process, It's only about information flow: i. e. Sun have all proposals before and call for new proposals with process of selecting 5 from set of newly received and 5 apriory well-known items, for which we know, that they are necessory, it's near the same, that throw away all non-apriory proposals. I. e. I guess, that when people asked to submit new proposals, they expect that exists demand for new proposals, not demand for choosing from five well-known items. When appointment of all new proposals to be thrown away, with role be backgroung for well-known items, people, which invested some time in such activity, usually frustrated. It's why I think, that call for new proposals, whithout real possibility to implement something new (not well-known before) was an error. If we have slot, for example, in summary for 10 proposals to implement (5 well know and 5 new) - then all ok, it's fair game. >> I. e. doing project coin with external auditory was a 'Sun system >> error', >> I guess; if they want some feedback from community, correct way was at >> first implement own stuff, than ask community for something new ;) >> > > The call of proposal phase of Project Coin is an effort both to solicit > feedback from the external community and also to invite the external > community to participate more directly in evolving the language. That > opportunity to participate also implies participating in the large > amount of work required to go from "I have this great idea!" to "I have > this great idea and here is a carefully considered review of all the > implications of the idea, along with a prototype." The blogs I wrote > last year and the proposal form itself are part of an effort to explain > and expose what this language work entails so more people can get > involved. > It would be great, to participate in language evolution in future. For now I does not see general aviable process for future participation: call closed, all new proposal throwed away. Finish. Fire bug reports is useless - they will live in bugzilla for years. One possible solution: is make 'coin project' regular, for example once a year. (May be with entry barrier as 'required implementation in some form') Another - propose some process (may be long) for author, how to push his proposal (whith implementation) into language after JDK7 (or receive official position, that this change is rejected) > Unfortunately, many of the submitted proposals did not do a credible job > of analyzing the true effect the proposal would have, which has a rather > strong relation to why many were not chosen for further consideration. > For example, let's take the "'This' type" proposal: > ... Problem with inaccurate proposals - it's well known problem, the same with publications, wildly used technique is peer review. (Honesly, overall quality of proposals was better that I was expected). Good entry barrier can be requirement to proposal to be implemented in some form. P.S. Project coin involved me to think about Java more close than before. So, despite my criticism, you achieve goal to raise interest to participate in process of Java language evolution ;) From tim.keith at gmail.com Thu Apr 2 16:49:13 2009 From: tim.keith at gmail.com (Tim Keith) Date: Thu, 2 Apr 2009 16:49:13 -0700 Subject: Proposal: Sameness operators In-Reply-To: <49D54420.5090906@sun.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <4b4f45e00904020524p27741baeo40483e83d71dc768@mail.gmail.com> <275433EA-A420-42C8-891D-3B0C2629222A@zwitserloot.com> <49D54420.5090906@sun.com> Message-ID: I would like to suggest calling the class java.lang.Objects, similar to java.util.Collections and java.util.Arrays. And it would be handy to also have in there a null-safe static method to help in implementing hashCode: public static int hashCode(Object o) { return o == null ? 0 : o.hashCode(); } -- Tim On Thu, Apr 2, 2009 at 4:02 PM, Joe Darcy wrote: > Reinier Zwitserloot wrote: > > [snip] > >> >> public static void is(Object x, Object y) { >> if ( x == null ) return y == null; >> return x.equals(y); >> } >> >> public static void is(Object x, int y) { >> // Yes, you'd need a few gazillion is methods to cover all the >> primitives on either side, but 1 static import will grab all of them >> } >> >> ... loads more is methods >> >> >> Then same with lt, gt, le, ge. >> >> Then you could write: >> >> if ( is(a, b) ) { >> //doStuff >> } >> >> Which is a small improvement. >> >> Add an ability to specify 'as infix' in static imports, and you have >> pretty much what we all want without backwards compatibility issues: >> >> import static java.lang.Equality.is infix; >> >> if ( a is b ) { >> //do something >> } >> >> I'd consider that a large improvement. > > Yes, in JDK 7 I'd like to see > > 6797535 Add shared two argument static equals method to the platform > http://bugs.sun.com/view_bug.do?bug_id=6797535 > > addressed in the platform. I was thinking putting it in a place like a > new utility class java.util.Object. > > -Joe > > From scolebourne at joda.org Thu Apr 2 17:28:02 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Fri, 03 Apr 2009 01:28:02 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <1238711752.49d53dc8e0a4c@www.paradise.net.nz> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <1238711752.49d53dc8e0a4c@www.paradise.net.nz> Message-ID: <49D55812.9010809@joda.org> I think that as a first step, any info on the most likely Coins would be beneficial. I'd suggest publishing the script alongside the results. Stephen brucechapman at paradise.net.nz wrote: > Good idea, > > Should they each be evaluated against the same corpus and what would be a > suitable corpus? > > http://en.wikipedia.org/wiki/Corpus_linguistics > > Bruce > > Quoting Stephen Colebourne : > >> All, >> One possible way I'd like to suggest that the coin evaluation could be >> helped would be to write a script to find out how frequently the >> specific issue comes up in real code. >> >> It should be possible to devise, write and run a script to find the >> number of LOCs affected by many of the proposals. For example: >> >> - strings in switch (find if else on constant strings) >> - multi-catch (find duplicate catch blocks) >> - elvis operator (find ternary and if else defaulting) >> - for each where the iterator remove can be accessed (% of loops that >> access iterator) >> - for each where index is needed (% of loops that use int looping) >> - method and field literals >> - byte and short literals >> and probably many others (I've just listed some proposals I remember) >> >> Ideally, any script would be ASM/BCEL based, but grep style might work >> too. >> >> I mention all this because I don't have the spare time to write such a >> script, but if you do, then I'm sure we'd all like to run it and >> discuss the results ;-) >> >> Stephen >> > > From Joe.Darcy at Sun.COM Thu Apr 2 19:08:43 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 02 Apr 2009 19:08:43 -0700 Subject: Helping to find the usefulness of a proposal In-Reply-To: <1238711752.49d53dc8e0a4c@www.paradise.net.nz> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <1238711752.49d53dc8e0a4c@www.paradise.net.nz> Message-ID: <49D56FAB.8090405@sun.com> brucechapman at paradise.net.nz wrote: > Good idea, > > Should they each be evaluated against the same corpus and what would > be a suitable corpus? > > http://en.wikipedia.org/wiki/Corpus_linguistics On that front, Alex sent me the following: > Analysis of a micro-corpus of your own or your company's code is > unscientific. > > Ewan Tempero and his colleagues at the University of Auckland have > done excellent, peer-reviewed work on how Java language features are > used in real-world code. Their "Qualitas Corpus" consists of over > 100,000 classes - see http://www.cs.auckland.ac.nz/~ewan/corpus/ > > If someone showed that, say, a null check occurs on average every 15 > lines of code in this corpus, and that null-safe operators could > remove those lines without adverse side effects, then that would be a > real contribution to Project Coin. I agree that using a standard, large corpus to empirically examine the utility of the Project Coin proposals would be a fine component of their evaluation. -Joe From Joe.Darcy at Sun.COM Thu Apr 2 19:09:37 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 02 Apr 2009 19:09:37 -0700 Subject: Proposal: Sameness operators In-Reply-To: References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <4b4f45e00904020524p27741baeo40483e83d71dc768@mail.gmail.com> <275433EA-A420-42C8-891D-3B0C2629222A@zwitserloot.com> <49D54420.5090906@sun.com> Message-ID: <49D56FE1.8080601@sun.com> Tim Keith wrote: > I would like to suggest calling the class java.lang.Objects, similar > to java.util.Collections and java.util.Arrays. Since this would be a utility class, I thought it would be better placed in java.util rather than java.lang. > And it would be handy to also have in there a null-safe static method > to help in implementing hashCode: > public static int hashCode(Object o) { > return o == null ? 0 : o.hashCode(); > } I've added this suggestion to the Sun bug. Thanks, -Joe > -- Tim > > On Thu, Apr 2, 2009 at 4:02 PM, Joe Darcy wrote: >> Reinier Zwitserloot wrote: >> >> [snip] >> >>> public static void is(Object x, Object y) { >>> if ( x == null ) return y == null; >>> return x.equals(y); >>> } >>> >>> public static void is(Object x, int y) { >>> // Yes, you'd need a few gazillion is methods to cover all the >>> primitives on either side, but 1 static import will grab all of them >>> } >>> >>> ... loads more is methods >>> >>> >>> Then same with lt, gt, le, ge. >>> >>> Then you could write: >>> >>> if ( is(a, b) ) { >>> //doStuff >>> } >>> >>> Which is a small improvement. >>> >>> Add an ability to specify 'as infix' in static imports, and you have >>> pretty much what we all want without backwards compatibility issues: >>> >>> import static java.lang.Equality.is infix; >>> >>> if ( a is b ) { >>> //do something >>> } >>> >>> I'd consider that a large improvement. >> Yes, in JDK 7 I'd like to see >> >> 6797535 Add shared two argument static equals method to the platform >> http://bugs.sun.com/view_bug.do?bug_id=6797535 >> >> addressed in the platform. I was thinking putting it in a place like a >> new utility class java.util.Object. >> >> -Joe >> >> > From brucechapman at paradise.net.nz Thu Apr 2 20:59:32 2009 From: brucechapman at paradise.net.nz (brucechapman at paradise.net.nz) Date: Fri, 03 Apr 2009 16:59:32 +1300 (NZDT) Subject: Helping to find the usefulness of a proposal In-Reply-To: <49D56FAB.8090405@sun.com> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <1238711752.49d53dc8e0a4c@www.paradise.net.nz> <49D56FAB.8090405@sun.com> Message-ID: <1238731172.49d589a4a3575@www.paradise.net.nz> Comments inline Bruce Quoting Joe Darcy : > brucechapman at paradise.net.nz wrote: > > Good idea, > > > > Should they each be evaluated against the same corpus and what would > > be a suitable corpus? > > > > http://en.wikipedia.org/wiki/Corpus_linguistics > > On that front, Alex sent me the following: > > > Analysis of a micro-corpus of your own or your company's code is > > unscientific. > > > > Ewan Tempero and his colleagues at the University of Auckland have > > done excellent, peer-reviewed work on how Java language features are > > used in real-world code. Their "Qualitas Corpus" consists of over > > 100,000 classes - see http://www.cs.auckland.ac.nz/~ewan/corpus/ > > OK, I was aware of that one because the last JUG meeting here was about visualising code and was working with that corpus. The problem then is that the corpus is HUGE. Even the 20090202r version which only has the latest release of each system (and is probably the appopriate one for coin use) is 1.2Gb (my monthly broadband limit is 1Gb - I'd probably sneakernet it from someone locally). Maybe this is one of those cases where it is better to take the analysis tools to the corpus rather than the other way around. For that we'd need someone to host the corpus and run jobs submitted against it. Let me do some further research on that. Bruce > > If someone showed that, say, a null check occurs on average every 15 > > lines of code in this corpus, and that null-safe operators could > > remove those lines without adverse side effects, then that would be a > > real contribution to Project Coin. > > I agree that using a standard, large corpus to empirically examine the > utility of the Project Coin proposals would be a fine component of their > > evaluation. > > -Joe > From Joe.Darcy at Sun.COM Thu Apr 2 21:30:57 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 02 Apr 2009 21:30:57 -0700 Subject: Of knapsacks and language features Message-ID: <49D59101.6070400@sun.com> A quick note on some additional considerations in language feature selection. I view the selection of language proposals to be a kind of knapsack problem: http://en.wikipedia.org/wiki/Knapsack_problem That is, each feature has some discrete size and complexity to implement and confers some improvement to the language. There is a bounded size and complexity budget and the goal is maximizing the value held in the knapset, the value of improvements shipped in a release. Of note is that implementing a language change has much more of a discrete size (or a small selection of possible sizes) rather than a continuous range of possible sizes. In other words, because of the coordinated set of deliverables associated with a language change, it may be reasonable to implement 0% 50% or 100% of a possible feature but no other fraction. And doing 50% of the feature might take 1/4 of the effort of doing the whole thing or 3/4 of that effort. Even when precise costs and improvements can be quantified, because of these discrete sizes the "greedy" algorithm of putting the highest value / cost item in the knapsack first can lead to globally poor results. If nothing else, having a pre-pass to reduce the number of proposals being considered for further review greatly reduces the combinatorial possibilities of subsets of features that could be included in a release. -Joe From Joe.Darcy at Sun.COM Thu Apr 2 21:48:46 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 02 Apr 2009 21:48:46 -0700 Subject: Opportunity Cost and Proposal Selection In-Reply-To: <980366fa0904010733o5655fe5di10aa2c44883f7a6e@mail.gmail.com> References: <980366fa0904010733o5655fe5di10aa2c44883f7a6e@mail.gmail.com> Message-ID: <49D5952E.9040602@sun.com> On 04/01/09 07:33 AM, Glenn A. Marshall wrote: > Will the details of the proposal evaluations be published? In general, no. I plan to write up some general retrospective comments on the proposals that were and were not chosen for further consideration in the coming weeks. However, there will be more detailed analysis and discussion to get the set of "for further consideration" proposals down to the final set of proposals. > The thinking here is that for proposals that almost made the cut, > perhaps the evaluations would reveal where a bit more work might push > them over the line for the next round - increase benefit/decrease cost. > > This is assuming there will be a next round. > > Any thoughts on round II? I think we have to see how round I works out first ;-) > It would seem to be worth considering, given the level of interest. > It would, of course, have to wait until Java 8, but why not start early? > > Surely you're busy with round I for now, but perhaps there could be a > parallel effort, with the initial effort primarily around email. Thinking about and working on possible language is great fun of course, but I think in the near term the Project Coin list needs to focus on JDK 7 related work. > thanks for doing all of this, It's an interesting project! -Joe From vapor1 at teleport.com Thu Apr 2 23:33:14 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 3 Apr 2009 02:33:14 -0400 (EDT) Subject: PROPOSAL: Simplified StringBuffer/StringBuilder syntax Message-ID: <29484356.1238740394998.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> Replies inline. -----Original Message----- >From: Reinier Zwitserloot >Sent: Mar 31, 2009 5:59 AM >To: Mark Thornton >Cc: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: Simplified StringBuffer/StringBuilder syntax > >+ being overloaded to also mean string concatenation was a mistake in >java 1.0*. Let's not enshrine it by making more of them. Actually, I agree with this. I think they should have come up with a new "concatenation" operator instead of trying to reuse an existing one. However, + is what we have, and that's not going to change. However, it is obnoxious because it isn't really "complete" -- it takes care of one trivial use case in concatenating strings, but it doesn't handle the larger issue of what to do when all the concatenation doesn't occur in the same expression, and it isn't consistent in its coverage of the family of related types (String, StringBuffer, and StringBuilder) that are really used in creating strings. My intent wasn't to create new operators -- it was to fix odd holes and (fairly inconvenient) missing features in the behavior of the existing ones. I just want the behavior of +, =, and += to behave consistently and intuitively when used with the classes that are used to generate Strings (StringBuffer, StringBuilder, and String). For anybody who knows that + means concatenation of strings, it's fairly obvious what: StringBuilder foo = "abc"; foo += "def"; is supposed to do. >Also, if '+' will call .append on any appendables, I guarantee you, >the first thing some clown will create is this: > >public class BigInteger2 extends Number implements Appendable { > //I'm a BigInteger that supports +! Oh - and I'm mutable too :/ >} Two observations: 1) If you are programming alongside clowns, it's probably time to find a new job. 2) This is probably the least of the damage that a clown can do when armed with a Java compiler. See observation #1. >Specific problems with the entire concept: > >1. + so far is strictly a 'create new object with result' kind of of >operation. "x + y" is an expression that does not change either the >value of x, or the value of y. It just creates a new value, and that >is the result of the expression. The same thing happens with strings, >but if you apply this to appendables, all of a sudden you get "x + y" >takes y and appends it to x. That is just strange. That's not what the proposal says. It says "x = x + y" takes y and appends it to x, if x is a StringBuilder and y is a String. The append is only done so that this happens efficiently (by eliminating the need to create an unnecessary temporary String object). It's an optimization for an expression in a very common, specific pattern involving multiple operators which is known to be evaluated inefficiently if not treated as a special case. Compilers do this sort of large-scale optimization frequently for a variety of reasons. From the user's point of view, there is no difference in behavior. "x + y" by itself does what it has always done. >2. The whole point of not allowing operator overloading is to make >sure any given snippet of the form 'x + y' serves as an anchor of >sorts: You know nothing too weird is going on in those 3 characters. >If + can mean: Mathematical plus, -OR- string concatenation (utterly >unrelated), -OR- anything anybody may have cooked up by implementing >Appendable, then there's zero conservative anchoring left for the + >symbol. Ergo I assert that doing this is as bad as having full blown >operator overloading. Actually, it's worse - at least full blown >operator overloading has proper names for things ('+' is plus and not >append), and allows one to write proper libraries for it. I personally am not particularly against operator overloading as a general principle. I've used C++ for many years and never really had a problem with someone abusing it. I've never really understood certain parts of the Java community's shock and horror at the concept of having it in a language -- lots of languages have it, and it doesn't really seem to be one of the major problems with any of them. (C++, for instance, has WAY bigger problems than that!) Whether it gets abused or not mostly depends on the culture and training of the average person who uses that particular language, not the features they have available to them. Also, libraries which aren't useful and reasonably intuitive don't tend to become widespread in their use. Operator overloading is only one of many possible ways that an API could be designed either well or poorly. As always, the market decides. In any case, having limited use of operator overloading designed within the platform by the people who maintain it is presumably a lot less likely to lead to abuse than to turn the public at large loose on it, so the general arguments against operator overloading ("Everybody and his dog will define operators to have unintuitive meanings at every opportunity!") don't really seem to apply in this case. Also, having operator overloading based on system interfaces which have defined meanings (and which may well be designed in ways that make them awkward to use in cases where those meanings do not apply) seems far less prone to abuse than the C++ model of "any operator can be redefined by anybody at any time for any purpose, as long as you remember to include the appropriate header file." With regards to "things people cook up using Appendable", presumably those will be things for which appending strings is a meaningful operation, right? Otherwise, they shouldn't be implementing the Appendable interface in the first place (and it would be awkward to do so, since "append(String)" isn't the only method on it, and the others are harder to implement). Since that's what the interface is really defined for, why is it a bad thing for them to be able to use the same syntax for appending strings to something with that mandate as it would be for appending them to other things, like Strings? Note that I'm not really all that sure that I'll add the Appendable concept to the proposal, since I have other concerns about it (such as the fact that append(int) isn't allowed, so there would be a lot of calling of String.valueOf(?) on the arguments). I'll have to think a bit more on that issue. >*) string concat and numeric plus are unrelated to each other. In >fact, numeric plus ought to be commutative, which string concat isn't >(commutative = swapping arguments doesn't change result). It weakens >the information that a raw + sign is capable of telling you. There are >pros and cons to having a strict interpretation of a + sign, but given >that java does not allow operator overloading, the onus appears to be >on those in favour of weakening it to prove why this is acceptable. Operator + is already defined within the language to mean concatenation as well as addition. You may argue that this shouldn't be the case, and I may even agree with you, but the fact remains that it is so, and neither of us can change that fact at this point. Given that we do, in fact, have operator + for strings meaning concatenation, I think that it is logical for us to make sure that the full set of operations that have related semantics all work together in a fashion that makes sense, given that + means concatenation for strings. Otherwise, we have a language that's not just inconsistent in the one detail that + has multiple meanings -- we have a language that's arbitrary and capricious with regards to which apparently similar operations are allowed versus which ones aren't. That's harder for users to learn. "I'm supposed to use StringBuilder to build strings. Why can't I build them with nice syntax like I'm used to with expressions involving Strings? Why does making a small change (building a string in multiple statements versus a single statement) mean I have to use an entirely different syntax to get a similar level of efficiency?". Also, in this case, it leads to a lot of unnecessarily verbose code or unnecessarily inefficient code being written. Derek > --Reinier Zwitserloot > > > >On Mar 28, 2009, at 21:14, Mark Thornton wrote: > >> Derek Foster wrote: >>> >>> CONCATENATION: An expression of the form >>> >>> SB += S >>> >>> where SB is an RValue expression of type StringBuilder, and S is an >>> expression of type String, shall be considered to have meaning as >>> defined below. (Previously, this was a syntax error) >>> >>> SELF-CONCATENATION: >>> >>> An expression of the form >>> >>> SB = SB + S >>> >> Why not allow any Appendable in these cases? >> >> Mark Thornton >> > > From peter.levart at gmail.com Thu Apr 2 23:35:28 2009 From: peter.levart at gmail.com (Peter Levart) Date: Fri, 3 Apr 2009 08:35:28 +0200 Subject: Proposal: Sameness operators In-Reply-To: <49D54420.5090906@sun.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <4b4f45e00904020524p27741baeo40483e83d71dc768@mail.gmail.com> <275433EA-A420-42C8-891D-3B0C2629222A@zwitserloot.com> <49D54420.5090906@sun.com> Message-ID: On Fri, Apr 3, 2009 at 1:02 AM, Joe Darcy wrote: > > Yes, in JDK 7 I'd like to see > > 6797535 Add shared two argument static equals method to the platform > http://bugs.sun.com/view_bug.do?bug_id=6797535 > > addressed in the platform. I was thinking putting it in a place like a > new utility class java.util.Object. > > -Joe > > Maybe not java.util.Object but java.util.Objects. Using the same name as a java.lang class prevents IDEs to suggest the imports since java.lang classes are already in scope. You would have to manually type import statements each time you wanted to use this method. Nobody does this nowadays. It would be very inconvenient. Regards, Peter From Joe.Darcy at Sun.COM Thu Apr 2 23:47:37 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 02 Apr 2009 23:47:37 -0700 Subject: Proposal: Sameness operators In-Reply-To: References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <4b4f45e00904020524p27741baeo40483e83d71dc768@mail.gmail.com> <275433EA-A420-42C8-891D-3B0C2629222A@zwitserloot.com> <49D54420.5090906@sun.com> Message-ID: <49D5B109.2020007@sun.com> Peter Levart wrote: > > On Fri, Apr 3, 2009 at 1:02 AM, Joe Darcy > wrote: > > > Yes, in JDK 7 I'd like to see > > 6797535 Add shared two argument static equals method to the > platform > http://bugs.sun.com/view_bug.do?bug_id=6797535 > > addressed in the platform. I was thinking putting it in a place > like a > new utility class java.util.Object. > > -Joe > > > Maybe not java.util.Object but java.util.Objects. Using the same name > as a java.lang class prevents IDEs to suggest the imports since > java.lang classes are already in scope. Yes, I meant to type "java.util.Objects" -- having a class other than java.lang.Object named "Object" is just wrong! -Joe From vapor1 at teleport.com Fri Apr 3 00:04:18 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 3 Apr 2009 03:04:18 -0400 (EDT) Subject: Naked dot - accessing object fields through unqualified Message-ID: <19432589.1238742258930.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> Replies inline. -----Original Message----- >From: Reinier Zwitserloot >Sent: Mar 31, 2009 9:03 AM >To: Derek Foster >Cc: coin-dev at openjdk.java.net >Subject: Re: Naked dot - accessing object fields through unqualified "." [C1] > >'Self-assignment is forbidden' would not be backwards compatibile. >Yes, such code would most likely be a bug, but its still an issue. It >would have to be a warning, at best. Personally, I think it should be an error, since there seems to be no valid reason to do it, and it almost certainly indicates a bug. I think that compilers should default to being in a 'strict' mode where things like this that have been found to be bad ideas with virtually no upside are treated as illegal, even if that makes them not fully backwards compatible. For backwards compatibility, there could be a command-line switch to turn off strict mode if necessary for compiling old code. Some other things I'd like to see in this category: * Having an abstract class with a constructor that has 'public' or 'private' access. * Using C-style array declarations. (int x[] instead of int[] x) I could probably think of a few more. >However: > >Every single external java compiler I know of will warn you when you >self-assign. Eclipse does it. So does netbeans. So does IDEA. So does >pmd. So does findbugs. Mere warnings are not enough to stop people from doing this sort of thing, especially when the warning message is buried in 436 other warning messages about code which is less unambiguously broken than this is. (Note: I *HATE* it when people ignore compiler warnings like this, but I am speaking from experience when I say that it usually takes years to convince a company to clean up its act.) Unfortunately, I have worked for lots of companies that routinely ignore warnings. >If you internalize the self-assignment warning, where do you stop? >There are literally hundreds of 'duh, that must be a bug' warnings you >could generate. Not all of them are as obvious, or as non-contentious, >as 'self assignment'. So, where do you stop? Do we use the glacial >nature of the language changes process to set this up? I think that when a practice is almost always problematic, is easy to fix, and has no legitimate purpose (and/or has an easy workaround in the few cases that it is legitimate), it should be made an error (with the caveats above). I don't think that we should carry along every single design mistake in the 1.0 edition of the Java Language Standard with us until the end of time. The ability to achieve backwards compatibility is important (hence the ability to turn off strict mode I described above), but clarity of language design and preventing common errors is too. Otherwise, the amount of code which contains the error in question just keeps growing over time. > I say: No. The >community has done a fine job of addressing these issues by creating >code checkers. In my experience, the community, by and large, does not use code checkers. Relatively few companies do. Again, I wish it were otherwise, but the truth is that most companies assume that if something passes the checks done by the compiler, it's probably fine. Having tried to introduce them into companies a few times, I can report that most software engineers really don't want to be bothered with them (and are convinced that checkers won't find any bugs important enough to justify the time spent learning to use them and cleaning up lots of innocuous warnings just for the sake of the tool). Again, I thoroughly disagree with that philosophy, but that's what I have heard repeatedly in industry. Also, using a code checker is often a painful experience if you are forced to use a framework written by people who don't use them. The other issue is that every code checker checks for a different set of things. Just because your code passes your code checker's rules doesn't mean it will pass mine, or vice versa. The Sun Java compiler as of a specific version, at least, is the same for everybody. > So, I'd instead suggest: >Any improvements to java core in this area should focus on improving >the ability for external tools to integrate better. For example, a way >to extend @SuppressWarnings with additional keywords would be great. A >way to let javac auto-find (via the SPI system) 'warning/error' >plugins would be another fine idea. Having any kind of plugin system >for the official javac to give other tools a go at creating warnings >and errors on the AST that javac's parser is building would be good >already, using SPI to find these automatically is just one way of >doing it. I'm not sure APT is quite right for the job; I don't want to >litter annotations to the gist of '@ExtensivelyCheckMe' all over the >place. I'm certainly in favor of making life easier for code checkers. However, checkers that don't get used are no better than ones that don't exist. Javac (or jikes, etc.) gets used every time someone compiles a program. That means it's going to have far more influence on the correctness of the majority of Java code than any other tool. Derek > > > --Reinier Zwitserloot > > > >On Mar 29, 2009, at 04:42, Derek Foster wrote: > >> The major problem I have with this proposal is that it does not >> address the point of why I use a prefix on field names. As such, I >> would still continue to use a prefix even if this proposal were >> implemented. >> >> In short, I use a prefix to avoid typographical mistakes, like this >> one: >> >> void setFoo(Thing foob) { // Typo! >> this.foo = foo; >> } >> >> This will compile, and no warnings are produced, but it ends up >> assigning foo to itself, which is not what was intended. >> >> Your proposal has exactly the same problem: >> >> void setFoo(Thing foob) { // Typo! >> .foo = foo; >> } >> >> It therefore does not substitute for a field prefix, which WILL fix >> the problem: >> >> void setFoo(Thing foob) { // Typo! >> _foo = foo; // ERROR! Undefined variable 'foo'. >> } >> >> So unless you had some way to make use of the dot prefix mandatory >> and the only legal way to access fields (which I would like, but >> which would be an extremely backwards-incompatible change that will >> never happen in Java), I don't see that adding an optional dot >> prefix helps the situation except to reduce typing in constructor >> and setter methods slightly. >> >> (Note: I would love a "self-assignment is forbidden" change to Java. >> If I have time after my other proposals, I might write one up. >> (Anyone else want to volunteer? This one is easy!) I might be >> willing to forego prefixes and use the "this.foo = foo" approach, or >> even the ".foo = foo" approach, if I was sure it wouldn't cause me >> to fall into the self-assignment trap.) >> >> Derek >> >> > From vapor1 at teleport.com Fri Apr 3 00:21:24 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 3 Apr 2009 03:21:24 -0400 (EDT) Subject: Proposal: Sameness operators Message-ID: <12090747.1238743285109.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> -----Original Message----- >From: Tom Hawtin >Sent: Mar 31, 2009 7:09 AM >To: Derek Foster >Cc: coin-dev at openjdk.java.net >Subject: Re: Proposal: Sameness operators > >Derek Foster wrote: >> a $$ b "same as": a==null ? b==null : a.equals(b), or a == b for primitive types. > >$ and $$ are valid identifier in (existing) Java. Not a lot of people >know that. http://jroller.com/tackline/entry/things_i_didn_t_know I, however, do know it. In fact, I mentioned it in the "Breaking Changes" section of my proposal. However, use of generated code is rare in general, and fixing a code generator to comply with a new language version only has to be done once. I considered it a lesser risk than introducing syntax that might break non-generated programs, which are very common indeed. I am open to other operators being used instead of the ones I suggested. I considered >#, <#, ##, and !#, for instance, but I thought that too many people might want to use # for closure-related things. Mostly, I wanted readability and understandability. The idea is you can just replace an = (which means "object identity" aka "equals") with a $ (which means "object equality" aka "sameness") and the related operators tend to mean what you would expect them to. >> a !$ b "not same as": a==null ? b!=null : !a.equals(b), or a != b for primitive types. >> a >$ b "greater than or same": a.compareTo(b) >= 0, or a >= b for primitive types. >> a <$ b "less than or same": a.compareTo(b) <= 0, or a <= b for primitive types. > >That's going to be jolly confusing for BigDecimal users (but I guess >that is not a state change). Personally, I find if (a >$ b) { do stuff } if (a $$ b) { do stuff } a lot less confusing than: if (a.compareTo(b) >= 0) { do stuff } if (a == null ? b == null : a.equals(b)) { do stuff } so I would hope that these would eventually reduce the confusion, not add to it. Really, the confusion is already there in how or if classes like BigDecimal implement interfaces like Comparable. (Which maybe was your point.) Derek From mthornton at optrak.co.uk Fri Apr 3 00:33:34 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Fri, 03 Apr 2009 08:33:34 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <1238731172.49d589a4a3575@www.paradise.net.nz> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <1238711752.49d53dc8e0a4c@www.paradise.net.nz> <49D56FAB.8090405@sun.com> <1238731172.49d589a4a3575@www.paradise.net.nz> Message-ID: <49D5BBCE.2030102@optrak.co.uk> brucechapman at paradise.net.nz wrote: > OK, > > I was aware of that one because the last JUG meeting here was about visualising > code and was working with that corpus. > > The problem then is that the corpus is HUGE. Even the 20090202r version which > only has the latest release of each system (and is probably the appopriate one > for coin use) is 1.2Gb (my monthly broadband limit is 1Gb - I'd probably > sneakernet it from someone locally). > Ouch, however I'm sure there are quite a few of us with substantially more generous download allowances. Mark Thornton From forax at univ-mlv.fr Fri Apr 3 00:34:20 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 03 Apr 2009 09:34:20 +0200 Subject: Proposal: Sameness operators In-Reply-To: <49D5B109.2020007@sun.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <4b4f45e00904020524p27741baeo40483e83d71dc768@mail.gmail.com> <275433EA-A420-42C8-891D-3B0C2629222A@zwitserloot.com> <49D54420.5090906@sun.com> <49D5B109.2020007@sun.com> Message-ID: <49D5BBFC.7040705@univ-mlv.fr> Joseph D. Darcy a ?crit : > Peter Levart wrote: > >> On Fri, Apr 3, 2009 at 1:02 AM, Joe Darcy > > wrote: >> >> >> Yes, in JDK 7 I'd like to see >> >> 6797535 Add shared two argument static equals method to the >> platform >> http://bugs.sun.com/view_bug.do?bug_id=6797535 >> >> addressed in the platform. I was thinking putting it in a place >> like a >> new utility class java.util.Object. >> >> -Joe >> >> >> Maybe not java.util.Object but java.util.Objects. Using the same name >> as a java.lang class prevents IDEs to suggest the imports since >> java.lang classes are already in scope. >> > > Yes, I meant to type "java.util.Objects" -- having a class other than > java.lang.Object named "Object" is just wrong! > > -Joe > or fun, all programs that use import java.util.* will break. R?mi From vapor1 at teleport.com Fri Apr 3 00:45:56 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 3 Apr 2009 03:45:56 -0400 (EDT) Subject: PROPOSAL: Underscores in numbers Message-ID: <31694231.1238744756544.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> -----Original Message----- >From: Bruce Chapman >Sent: Mar 31, 2009 3:14 AM >To: Derek Foster >Cc: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: Underscores in numbers > >Derek, >thanks for writing this up, it saved me doing it. (and it would >complement my integer literal proposals nicely) You're welcome! Personally, I definitely hope that your type suffixes for bytes and shorts proposal goes through. Lack of that seems a weird omission in the language, and I am tired of casting to bytes. I am not as keen on the other proposal with its "0h52" notation, however. That seems to be mixing radix and type in a way that is not very consistent with how the rest of the language works. >A couple of comments: > >1. I don't really like most of your decimal examples because (apart from >the money one) although we talk about these as numbers, they are not >numbers really, just identifiers whose significant elements consist >solely of digits. As an explanation, prepending 00 to the front of any >of these would yield a different (or invalid) phone/credit card/SS >number, whereas prepending 00 to a number does not (but not in java >where it makes an octal or a compiler error :), similarly add two >together or subtracting them makes no sense. I think that both pure numbers (underscores used for order-of-magnitude grouping of digits) and formatted numbers (underscores used in standard groups) like these are both valid use cases for this feature. They are definitely different use cases, but it is nice that the feature can be used for both. >Real countable number examples that could be useful are populations, >national debt, Long.MAX_VALUE etc, as well as the hex and binary >examples you use later. I'm not averse to adding more examples. I tried to make each existing example show a different likely use of the feature. So I really only needed one example to show the use of underscores to group big numbers in three-digit chunks (as commas would be used, for Americans anyway). >I am not convinced of the utility of multiple consecutive underscore >separators, and I think the example that uses that is confusing and >asking for trouble. IMHO it would add to the value if you removed that >option, but you might have some good use case you are thinking about. >Similarly for underscore at either end seems strange. It might take more >effort to describe it such that these are illegal, but I don't think >anyone would complain at the absence of that form. I left them in because I couldn't see a good reason to exclude them, and it's possible that someone might want to use them for some form of formatting that I haven't thought of. Perhaps someone might want to space the digits out to make a number line up with the characters in a comment field that's above it, for instance: // AreaCode Exchange Number int x = 555______555___1212; int y = 555______857___5309; The question really is whether adding multiples causes actual problems. As far as I can see, it doesn't. If someone is abusing them to write unclear code, then it seems to me that that person is really the problem. I don't think the feature in and of itself particularly encourages abuse. It could be used in ways that make code clearer rather than harder to read. I don't really expect it to be used much, though. >Any reason why in the syntax you didn't just add underscore to the >various XXXXDigits forms (and maybe change the name a little) rather >than the more complex approach, then describe the erasure of the >underscore in the description of each form? Because that would have made things like "0x_" or "_._" be parseable as syntactically legal numbers, which would then become illegal once the underscores were removed. Getting the grammar right for the underscores proposal turned out to be much trickier than I had anticipated. (It probably took me two hours.) I initially did it wrong, and had to revise it once I realized that I couldn't ever allow an underscore to appear if it wasn't next to a digit. Derek >Bruce > >Derek Foster wrote: >> When I posted my Binary Literals proposal, I got feedback from several people stating that they would like to see a proposal regarding underscores in numbers, in the style of Ruby, since that would make numbers of all types (but especially binary ones) easier to read. Here is such a proposal. >> >> AUTHOR(S): Derek Foster >> >> OVERVIEW >> >> In Java, currently, numbers of various types currently are expressed in their pure form, as a long string of digits possibly interspersed with other punctuation (periods, an exponent specifier, etc.) needed to separate distinct sections of the number. While this is easy for a compiler to process, it is often difficult for a human being to visually parse. >> >> The ability of a human to visually separate separate items tops out somewhere near "seven plus or minus two" items. Research done by telephone companies suggests that for many practical purposes, the longest string of numbers an average human can successfully hold in memory at a time is around three or four. Also, it is difficult for the human eye to find common positions in numbers that have no break in their visual structure. >> >> As a result, most numbers that humans deal with in day-to-day life have separators included in them to break the long sequence of digits into manageable chunks that are easy to deal with as separate entities. This includes items such as (apologies to non-USA readers...): >> >> Phone numbers: 555-555-1212 >> Credit card numbers: 1234-5678-9012-3456 >> Social security numbers: 999-99-9999 >> Monetary amounts: $12,345,132.12 >> >> and a wide variety of other types of numbers. >> >> However, Java provides no way to add these kinds of visual separators into a number. Java expects the number to be essentially an unbroken string of digits. >> >> This proposal suggests that Java follow the lead of the Ruby programming language in allowing the underscore character to be inserted into numbers in most positions, for readability purposes. >> >> >> FEATURE SUMMARY: >> >> Java numeric literals will allow underscores to be placed in (nearly) arbitrary positions within the number, at the programmer's discretion, for readability purposes. These underscores shall be ignored by the compiler for the purposes of code generation. >> >> >> MAJOR ADVANTAGE: >> >> Programmers won't have to visually parse long strings of digits (a task humans are quite poor at). The internal digit-oriented structure of many numbers can be made more clear. >> >> >> MAJOR BENEFIT: >> >> Increased readability of code. >> >> >> MAJOR DISADVANTAGE: >> >> The number parsers in the Java compiler would have to be adjusted to parse and ignore the underscores. This is a small amount of effort, but nonzero. There might also be some small performance impact. >> >> If someone were to use this feature inappropriately, it could result in difficult to read code. >> >> >> ALTERNATIVES: >> >> Do without separators in numbers, or use some other character for them. >> >> >> EXAMPLES >> >> >> SIMPLE EXAMPLE: Show the simplest possible program utilizing the new feature. >> >> int phoneNumber = 555_555_1212; >> >> >> ADVANCED EXAMPLE: >> >> long creditCardNumber = 1234_5678_9012_3456L; >> long socialSecurityNumbers = 999_99_9999L; >> float monetaryAmount = 12_345_132.12; >> long hexBytes = 0xFF_EC_DE_5E; >> long hexWords = 0xFFEC_DE5E; >> long maxLong = 0x7fff_ffff_ffff_ffffL; >> long alsoMaxLong = 9_223_372_036_854_775_808L; >> double whyWouldYouEverDoThis = 0x1_.ffff_ffff_ffff_fp10_23; >> >> (Additionally, if binary literals are ever added to the Java language, the following might also be possible... >> byte nybbles = 0b0010_0101; >> long bytes = 0b11010010_01101001_10010100_10010010; >> int weirdBitfields = 0b000_10_101; >> ) >> >> Note that underscores can be placed around and between digits, but that underscores cannot be placed by themselves in positions where a string of digits would normally be expected: >> >> int x1 = _52; // This is an identifier, not a numeric literal. >> int x2 = 5_2; // OK. (decimal literal) >> int x2 = 52_; // OK. (decimal literal) >> int x3 = 5_______2; // OK. (decimal literal.) >> >> int x4 = 0_x52; // Illegal. Can't put underscores in the "0x" radix prefix. >> int x5 = 0x_52; // OK. (hexadecimal literal) >> int x6 = 0x5_2; // OK. (hexadecimal literal) >> int x6 = 0x52_; // OK. (hexadecimal literal) >> int x6 = 0x_; // Illegal. Not a valid hex number with the underscore removed. >> >> int x7 = 0_52; // OK. (octal literal) >> int x7 = 05_2; // OK. (octal literal) >> int x8 = 052_; // OK. (octal literal) >> >> >> DETAILS >> >> SPECIFICATION: >> >> DECIMALS: >> >> Section 3.10.1 ("Integer Literals") of the Java Language Specification 3rd edition shall be modified like so: >> >> Underscores: >> _ >> _ Underscores >> >> DecimalNumeral: >> 0 >> NonZeroDigit DigitsAndUnderscores_opt >> >> DigitsAndUnderscores: >> Underscores_opt Digit Underscores_opt >> DigitsAndUnderscores Digit Underscores_opt >> >> Digit: >> 0 >> NonZeroDigit >> >> NonZeroDigit: one of >> 1 2 3 4 5 6 7 8 9 >> >> HexNumeral: >> 0 x HexDigitsAndUnderscores >> 0 X HexDigitsAndUnderscores >> >> HexDigitsAndUnderscores: >> Underscores_opt HexDigit Underscores_opt >> Underscores_opt HexDigit HexDigitsAndUnderscores >> >> HexDigit: one of >> 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F >> >> OctalNumeral: >> 0 OctalDigitsAndUnderscores >> >> OctalDigitsAndUnderscores: >> Underscores_opt OctalDigit Underscores_opt >> Underscores_opt OctalDigit OctalDigitsAndUnderscores >> >> OctalDigit: one of >> 0 1 2 3 4 5 6 7 >> >> Section 3.10.2 ("Floating-Point Literals") would be modified as follows: >> >> >> FloatingPointLiteral: >> DecimalFloatingPointLiteral >> HexadecimalFloatingPointLiteral >> >> DecimalFloatingPointLiteral: >> Digit DigitsAndUnderscores_opt . DigitsAndUnderscores_opt ExponentPart_opt FloatTypeSuffix_opt >> . DigitsAndUnderscores ExponentPartopt FloatTypeSuffix_opt >> Digit DigitsAndUnderscores_opt ExponentPart FloatTypeSuffix_opt >> Digit DigitsAndUnderscores_opt ExponentPart_opt FloatTypeSuffix >> >> ExponentPart: >> ExponentIndicator SignedInteger >> >> ExponentIndicator: one of >> e E >> >> SignedInteger: >> Sign_opt DigitsAndUnderscores >> >> Sign: one of >> + - >> >> FloatTypeSuffix: one of >> f F d D >> >> HexadecimalFloatingPointLiteral: >> HexSignificand BinaryExponent FloatTypeSuffix_opt >> >> HexSignificand: >> HexNumeral >> HexNumeral . >> 0x HexDigitsAndUnderscores_opt . HexDigitsAndUnderscores >> 0X HexDigitsAndUnderscores_opt . HexDigitsAndUnderscores >> >> BinaryExponent: >> BinaryExponentIndicator SignedInteger >> >> BinaryExponentIndicator:one of >> p P >> >> >> COMPILATION: >> >> Numbers containing underscores are to be parsed and evaluated by the compiler exactly as if the underscores were not present. The above grammar ensures that removing underscores will not result in an unparseable number. >> >> A simple strategy for achieving this is that once a number has been parsed by the compiler lexer and determined to be syntactically valid according to the above grammar, then if the number contains any underscores, then all underscores in it may be removed (by something as simple as numberAsString.replaceAll("_","")) before passing the number on to the code that would normally have parsed the number prior to this proposal. >> >> More performant approaches are certainly possible. >> >> >> TESTING: How can the feature be tested? >> >> A variety of literals may be generated, of the cross product of each of the following radicies: >> >> hex, decimal, octal >> >> with each of the following types: >> >> byte, char, short, int, long, float, double >> >> such that for each possible numeric field in the result, that one or more underscores are inserted at the beginning, in the middle, and at the end of the digits. >> >> Note that the above grammar is specifically designed to disallow any underscores from appearing which are not either preceded by or followed by a digit. >> >> >> LIBRARY SUPPORT: >> >> Methods such as Integer.decode(String) and Long.decode(String) should probably be updated to ignore underscores in their inputs, since these methods attempt to parse according to Java conventions. >> >> I suggest that methods such as Integer.parseInt(), Float.parseFloat(), etc. should probably NOT be updated to ignore underscores, since these methods deal with numbers in their pure form, and are more focused and much more widely used. To alter them to ignore underscores would introduce ambiguity in (and have a performance impact on) various parsing code that uses them. >> >> >> REFLECTIVE APIS: >> >> No changes to reflective APIs are needed. >> >> >> OTHER CHANGES: >> >> No other changes are needed. >> >> >> MIGRATION: >> >> Underscores can be inserted into numbers within an existing code base as desired for readability. >> >> >> COMPATIBILITY >> >> BREAKING CHANGES: >> >> Since use of underscores within numbers was previously a syntax error, this should not break any existing programs. >> >> >> EXISTING PROGRAMS: >> >> This feature does not affect the format of class files. It is purely a notational convenience. Hence, interaction with existing class files would not be affected. >> >> REFERENCES >> >> EXISTING BUGS: >> >> A search of the Bug Database did not find any bug ID's related to this proposal. >> >> URL FOR PROTOTYPE (optional): >> >> None. >> >> >> >> > From vapor1 at teleport.com Fri Apr 3 00:57:06 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 3 Apr 2009 03:57:06 -0400 (EDT) Subject: PROPOSAL: Auto-assignment Parameters Message-ID: <31069284.1238745426303.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> -----Original Message----- >From: Reinier Zwitserloot >Sent: Mar 31, 2009 9:05 AM >To: Derek Foster >Cc: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: Auto-assignment Parameters > >Derek, if this proposal will save you a lot of typing, I think you're >doing it wrong. Thare are many tools that will auto-generate POJOs for >you, including whatever setter you prefer. Most IDEs have this in >their 'source' or 'refactor' menu, for example. It wasn't the typing of creating them in the first place that I had in mind, but what comes after that. I would explain more on that point, but it seems you have saved me the trouble: >What annoys me about these tools is that they are one-way operations. > From seeing the multiple pages of POJO auto-generated code (incl. >hashCode, equals, toString, and constructor, and in some cases, the >auto-generated builder as well), I cannot ascertain quickly if this is >'just' the usual auto-generated boilerplate, or if there's a fun >surprise in there someplace (like some field being excluded for equals/ >hashCode purposes, or a missing getter, or some such). This makes >POJOs spectacularly unmaintainable compared to the low impact they >should be having, in java. It's also somewhat difficult (but certainly >not impossible) to change things that were used to auto-generate code, >such as changing the type or name of a field later. You and I are in rabid agreement on that point. I don't like code generation tools that spew forth blocks of code that I then have to maintain. To me, the existence of such tools indicates a deficiency in the language. (If it's easy enough for a tool to generate boilerplate code like that, it should be easy for the language to make that boilerplate code unnecessary by generating it for me as I compile.) >That's why I want a 'data' modifier for class, which will completely >auto-generate everything. If the 'saves me typing' argument holds >water, imagine what this will do for you! We agree on this. I want a data modifier for a class also (or could we just use the 'struct' keyword like C++?). However, the auto-assignment parameters proposal has more general applicability to classes other than data classes as well, so I want those too. I might even use them both together in the same class. > I also don't want such a >feature to spin out of a control into an entirely new programming >definition syntax, so we'll just use java itself to fill in the gaps >and afford us flexibility: If the auto-gen isn't good enough for you, >then don't use it and write it the usual way. You get method-level >granularity for this process, but that's where it ends. Simple and yet >a great boon for code maintainability. I agree with this as well. I think it's perfectly reasonable for there to be shorthand syntax for common cases, with the ability to override it when something more complex is needed. If I just want to return three values from a method, I don't want to have to write a full-blown class complete with a constructor, getters, and setters. Just specifying the fields is enough. A data class will probably do fine. But I want to be able to replace that data class later with the real thing if necessary without having to update all of the uses of it in the code. Derek > > > > --Reinier Zwitserloot > > > >On Mar 28, 2009, at 22:31, Derek Foster wrote: > >> Just to add a few kudos and comments: >> >> I like the proposal a lot. Even in its current form, this would save >> me a lot of typing. Of the proposals so far put forth on Project >> Coin, this is the one I would probably end up using the most often. >> I use a lot of immutable class objects, and this >> >> Some suggestions and things to consider: >> >> 1) I think that having to repeat "this." all over the place is >> perhaps unnecessary. You could use something shorter, like a leading >> dot, or perhaps a leading equals sign: >> >> class Foo { >> final int bar; >> final String baz; >> Foo(int .bar, String .baz) {} >> void setBar(int .bar) {} >> void setBaz(String .baz) {} >> } >> >> 2) I think that allowing the syntax for all method parameters, not >> just constructor parameters, would be nice. >> >> 3) I think that allowing the syntax for return values from methods >> has some potential advantages as well. There are some potential >> advantages with >> Javadoc generation, as I describe below, which would make: >> >> String this.foo getFoo() {} >> >> advantageous in some circumstances even if it isn't much shorter than: >> >> String getFoo() { return this.foo; } >> >> 4) I think you should consider the impact on Javadoc more carefully. >> Particularly in cases where people use a prefix ("_", "m_", etc.) on >> their internal fields, which is very common. It looks as though >> those prefixes would end up being displayed in Javadoc as >> constructor parameter names, which would be less than ideal. >> >> Also, autogeneration of Javadoc for the this. parameters, based on >> Javadoc for the class members they are initialized from would be >> nice. Currently, these often have to be maintained in parallel, >> which can be a significant annoyance. >> >> I often see people write code equivalent to: >> >> class Foo { >> /** This is the name of a famous person which can't be null and >> blah blah blah. */ >> String _bar; >> >> /** >> * Construct a new instance. >> * @param bar This is the name of a famous person which can't be >> null and blah blah blah. >> */ >> Foo(String bar) { >> _bar = bar; >> } >> >> /** >> * Sets the value of bar. >> * @param bar This is the name of a famous person which can't be >> null and blah blah blah. >> */ >> void setBar(String bar) { >> _bar = bar; >> } >> >> /** >> * Gets the value of bar. >> * @return This is the name of a famous person which can't be >> null and blah blah blah. >> */ >> String getBar() { >> return _bar; >> } >> >> } >> >> which essentially reproduces the same JavaDoc comment four times >> (and means it must be maintained in quadruplicate if changes are >> made). It would be nice to replace this with something like: >> >> class Foo { >> /** This is the name of a famous person which can't be null and >> blah blah blah. */ >> String _bar; >> >> /** Construct a new instance. */ >> Foo(String this.bar) {} >> >> /** Sets the value of bar. */ >> void setBar(String this.bar) {} >> >> /** Gets the value of bar. */ >> String this.bar getBar() {} >> } >> >> with the same Javadoc being generated as the prior example. >> >> 5) Being able to omit the type in all of these cases would be a big >> plus. When I have a variable of a type like >> "List>", it would be >> awfully nice to be able to omit having to specify that detail >> redundantly in the constructor, settter, and getter. >> >> Derek >> >> >> >> >> -----Original Message----- >>> From: Mark Mahieu >>> Sent: Mar 26, 2009 2:21 PM >>> To: Marek Kozie? >>> Cc: coin-dev >>> Subject: Re: PROPOSAL: Auto-assignment Parameters >>> >>> 2009/3/26 Marek Kozie? >>> >>>> I see one problem here. >>>> class Some{ >>>> final String name; >>>> public Some(String this.name){} >>>> } >>>> >>>> perform .intern() is impossible now. >>> >>> >>> Correct, you'd have to write it the same way as you'd do now. I >>> actually >>> view that as a Good Thing though: there's a clear, visual distinction >>> between parameters which are just assigned directly to the fields, >>> and those >>> on which we perform some operation first. Only the latter would >>> appear in >>> the body of the constructor, without being cluttered by the former. >>> >>> >>>> But I like the proposition 'much'. >>>> Simple and clear. >>> >>> >>> Glad you like it! >>> >>> >>> Regards, >>> >>> Mark >>> >> >> > From vapor1 at teleport.com Fri Apr 3 01:09:56 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 3 Apr 2009 04:09:56 -0400 (EDT) Subject: PROPOSAL: @OverrideAll annotation Message-ID: <17542308.1238746196681.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> My major problem with this proposal is that it doesn't seem to be straightforward to generate the bodies of methods that have to return something. Particularly for code such as implementations of the Visitor pattern. Having un-overridden methods simply return null or zero is often not the right thing to do. It's OK for generating methods that just take parameters, I suppose. Still, having annotations generate code or otherwise affect the operation of a program is apparently a no-no per Sun's rules. If something like this is going to happen, I think it needs a new keyword or something rather than using an annotation. (Although, personally, I don't think it would be such a bad thing if code generation via annotation existed, but were limited only to certain annotations in a specific package duly designated by the language implementors. Annotations have one nice quality that other ways of extending the language don't: You can create new "keywords" at will with no risk of breaking someone's perfectly-working code. If they don't import the annotation, they won't need to be impacted by it. I sort of wish there was an alternative to annotations (@@Foo instead of @Foo?) which was explicitly for the purpose of telling the compiler to generate boilerplate code of various types. Decorators in Python sort of serve this purpose, for instance.) Derek -----Original Message----- >From: rssh at gradsoft.com.ua >Sent: Mar 31, 2009 10:02 AM >To: Gabriel Belingueres >Cc: coin-dev >Subject: Re: PROPOSAL: @OverrideAll annotation > >> Hi, >> >> I've written a new feature that might be comfortable to use for >> someone. All input is welcomed. >> > >It-is possible to do near same with annotation API (create a superclass > which will override all) > >But -- sometime we really need to say, that all methods 'mus be' >overriden. (For example - when implementing Proxy pattern). >In such case class-level annotation '@OverrideAll' which tell compiler >to check, that all methods must be overriden -- brilliant idea. > > > > > >> Regards, >> Gabriel >> >> PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 >> >> AUTHOR(S): Gabriel Belingueres >> >> OVERVIEW >> >> Add an @OverrideAll annotation to allow a class to override all >> inherited methods with a trivial implementation. The resulting class >> then could be used as the basis for a Null Object pattern (or even a >> basic Mock object.) >> >> >> FEATURE SUMMARY: >> >> The proposed @OverrideAll annotation will allow the class to override >> all methods (from its superclasses and implemented interfaces) with a >> trivial body, but the defined class can choose to implement specific >> methods, replacing those that would be produced automatically by the >> annotation. >> >> >> MAJOR ADVANTAGE: >> >> Less coding for implementing Null Objects, or simple tests. >> >> >> MAJOR BENEFIT: >> >> Let the compiler implement all uninteresting, non relevant behavior by >> automatically providing with a trivial implementation of the inherited >> methods. >> >> >> MAJOR DISADVANTAGE: >> >> Might be a cause of NullPointerException if not used judiciously. >> >> >> ALTERNATIVES: >> >> Implement all uninteresting methods by yourself by providing yourself >> a trivial implementation (though actually popular IDEs can do this >> automatically for you already.) >> >> EXAMPLES >> >> Given: >> >> class B {} >> >> public class A implements I1, I2 { >> >> public static final int VAR = 1; >> >> private B b; >> >> public static Integer getSome() { >> return VAR; >> } >> >> public A() { >> } >> >> public A(B b) { >> this.b=b; >> } >> >> public B getB() { >> return b; >> } >> >> public void setB(B b) { >> this.b=b; >> } >> >> protected void doProtected() { ... } >> >> private void doPrivate() { ... } >> >> A someNewA() { ... } >> >> public synchronized void someSynchronized() { >> } >> >> } >> >> then: >> >> @OverrideAll >> public class NullA extends A { >> } >> >> is equivalent to declare: >> >> public class NullA extends A { >> >> public NullA() {} >> >> public NullA(B b) { >> super(b); >> } >> >> public B getB() { >> return null; >> } >> >> public void setB(B b) { >> } >> >> protected void doProtected() { >> // empty >> } >> >> A someNewA() { >> return null; >> } >> >> public synchronized void someSynchronized() { >> // empty >> } >> >> } >> >> You may not want the default trivial implementation in some methods, >> then you override them as usual: >> >> @OverrideAll >> public class NullA extends A { >> >> @Override >> public B getB() { >> return new B(); >> } >> >> @Override >> public synchronized void someSynchronized() { >> System.out.println("overridden"); >> } >> >> } >> >> EXAMPLE 2 >> >> Implement a trivial Collection interface just to test that adding >> elements will increase the collection size: >> >> Currently: >> >> public class SomeCollection implements Collection { >> >> private int counter; >> >> @Override >> public boolean add(E arg0) { >> counter++; >> return true; >> } >> >> @Override >> public boolean addAll(Collection c) { >> counter += c.size(); >> return true; >> } >> >> @Override >> public void clear() { >> } >> >> @Override >> public boolean contains(Object arg0) { >> return false; >> } >> >> @Override >> public boolean containsAll(Collection arg0) { >> return false; >> } >> >> @Override >> public boolean isEmpty() { >> return false; >> } >> >> @Override >> public Iterator iterator() { >> return null; >> } >> >> @Override >> public boolean remove(Object arg0) { >> return false; >> } >> >> @Override >> public boolean removeAll(Collection arg0) { >> return false; >> } >> >> @Override >> public boolean retainAll(Collection arg0) { >> return false; >> } >> >> @Override >> public int size() { >> return counter; >> } >> >> @Override >> public Object[] toArray() { >> return null; >> } >> >> @Override >> public T[] toArray(T[] arg0) { >> return null; >> } >> >> } >> >> With the annotation: >> >> @OverrideAll >> public class SomeCollection implements Collection { >> >> private int counter; >> >> @Override >> public boolean add(E arg0) { >> counter++; >> return true; >> } >> >> @Override >> public boolean addAll(Collection c) { >> counter += c.size(); >> return true; >> } >> >> >> @Override >> public int size() { >> return counter; >> } >> >> } >> >> >> DETAILS >> >> >> SPECIFICATION: >> >> A preliminary specification follows: >> >> As this feature is proposed as an annotation for code generation, no >> changes to the current JLSv3 are needed. >> >> The annotation will generate "trivial" overridden implementations for >> all methods not specified in the class, for each superclass in the >> hierarchy (except Object) and implemented interface. >> >> - Static methods, private methods, final methods, constructors and >> methods from class Object should never be generated. >> - If some superclass (except Object) has already overridden some >> Object class methods, then do NOT generate an empty overridden method >> (to reuse current behavior.) (for example, if some superclass already >> override toString(), equals() or hashCode().) >> >> - OPTIONAL: add a parameter to the @OverrideAll annotation to indicate >> if @Deprecated methods should not be implemented. >> >> Trivial implementation for generated methods: >> >> - Methods returning void will have an empty body. (OPTIONAL: add a >> parameter to the @OverrideAll annotation to indicate that it should >> throw UnsupportedOperationException instead) >> - Methods returning a primitive type will have a body returning the >> same default value that would have for uninitialized instance >> variables. (JLS section 4.12.5.) >> - Methods returning a reference type will "return null;". (JLS section >> 4.12.5.) >> - The method will never return a covariant return type (because in >> case of implementing a Null object, it should be undistinguished from >> the common case) >> - Methods that throws checked exceptions can be modified to delete the >> throws clause. (ie. the trivial implementation should not throw >> checked exceptions) >> - Synchronized methods should retain that attribute. >> >> >> COMPILATION: >> >> Compilation should proceed as usual, except that the annotation >> processor would generate the code when it encounters an annotated >> class. >> >> No changes to the class file format are needed. >> >> >> TESTING >> >> Test cases should be done, including testing with classes implementing >> several interfaces, classes with generics, inner classes, etc. >> >> >> LIBRARY SUPPORT: >> >> No, except creating the new annotation. >> >> >> REFLECTIVE APIS: >> >> No changes foreseen. >> >> >> OTHER CHANGES: >> >> Output of javadoc tool. >> >> >> MIGRATION: >> >> Just add the annotation to class level, and erase your trivially >> implemented overridden methods. >> >> >> COMPATIBILITY >> >> BREAKING CHANGES: >> All existing programs remain valid. >> >> EXISTING PROGRAMS: >> The semantics of existing class files and legal source files are >> unchanged by this feature. >> >> >> REFERENCES >> >> EXISTING BUGS: >> >> None that I know about. >> >> URL FOR PROTOTYPE: >> >> None at this time. >> >> > > > From vapor1 at teleport.com Fri Apr 3 01:15:25 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 3 Apr 2009 04:15:25 -0400 (EDT) Subject: Proposal: Accepting a subclass as an element type in a for loop Message-ID: <9909880.1238746526010.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> I was leaning somewhat on the side of thinking this would be a nice feature (it is, at least, an elegant one), but I think that Reiner's arguments have convinced me otherwise. The example of the filtering method, in particular, shows that working around this is quite easy. Given that the need for this actually comes up pretty rarely in my experience (I have only ever wanted this once, that I can recall, and it was both easy and intuitive to work around in a manner somewhat similar to but less general than Reiner's suggestion), I think I have come to the conclusion that despite its elegance, this probably isn't worth adding to the language. Derek -----Original Message----- >From: Reinier Zwitserloot >Sent: Mar 31, 2009 11:16 AM >To: Jean-Louis Ardoint >Cc: coin-dev at openjdk.java.net >Subject: Re: Proposal: Accepting a subclass as an element type in a for loop > >Why is this worthy of a language change? It's very niche. > >You can solve your problem by writing 1 method, like so: > >for ( Rectangle r : MyUtilityClass.filterOnType(shapes, >Rectangle.class) ) { > drawRectangle(r); >} > > >with: > >public class MyUtilityClass { > public static List filterOnType(Iterable >in, Class outType) { > List list = new ArrayList(); > for ( A a : in ) > if ( outType.isInstance(a) ) list.add(outType.cast(a)); > return list; >} > > > >Even if you disregard for a moment that if you add this, I've got >about a gazillion other niche things that have about as many use cases >and are about as easy to solve with a library for coin,your proposal >has omitted a rather serious issue: > >What would you do if you have something like: > >List> foo = someMethodCall(); >for ( Set set : foo ) { > // You can't do this in java. >} > > > > --Reinier Zwitserloot > > > >On Mar 31, 2009, at 14:55, Jean-Louis Ardoint wrote: > >> I'm maybe a bit too late. Here's my proposal anyway. >> >> >> >> -- Jean-Louis Ardoint >> >> >> >> Accepting a subclass as an element type in a for loop >> >> >> >> AUTHOR(S): Jean-Louis Ardoint >> >> >> >> OVERVIEW >> >> >> >> FEATURE SUMMARY >> >> >> >> Add a filtering and downcast capability to the enhanced for statement >> (a.k.a for each). >> >> >> >> MAJOR ADVANTAGE >> >> >> >> It should reduce the number of lines of code and depth of nesting in >> loops. The resulting code would be more readable that what is done >> currently to achieve the same goal. The meaning of such a loop is >> quite >> obvious. >> >> >> >> MAJOR BENEFIT >> >> >> >> Better readability and expressiveness. >> >> >> >> MAJOR DISADVANTAGE >> >> >> >> More complexity in the compiler to generate a little bit more >> bytecode. >> >> >> >> ALTERNATIVE >> >> >> >> You can currently the same thing, yet it means adding an extra if >> statement and an intermediate variable to be cast. >> >> >> >> EXAMPLES >> >> >> >> Here is a small not very interesting example of such a enhanced for >> loop: >> >> >> >> Shape[] shapes = ...; >> >> for (Shape s : shapes) >> >> drawShape(s); >> >> >> >> If for a reason you would need to draw only the rectangles, you would >> need to write: >> >> >> >> for (Shape s : shapes) { >> >> if (s instanceof Rectangle) >> >> drawRectangle((Rectangle)s); >> >> } >> >> >> >> This is not very aesthetic. If only the for loop would directly >> accept a >> subclass as the element type and do the type checking and downcast, we >> could be able to write: >> >> >> >> for (Rectangle r : shapes) >> >> drawRectangle(r); >> >> >> >> Note that there is a subtlety w.r.t. the handling of nulls. See >> Compilation below for more details >> >> >> >> DETAILS >> >> >> >> SPECIFICATION: >> >> >> >> The grammar is unchanged. The equivalence between an enhanced for loop >> and a regular for loop has to be changed in JLS 14.14.2. >> >> COMPILATION: >> >> >> >> The way enhanced loop are translated into bytecode would change >> depending on whether the loop variable type is a subclass of the >> iterable or array element type. >> >> If the loop variable type is a subclass, then the loop is equivalent >> to: >> >> >> >> For an expression returning Iterable: >> >> Iterable cs... >> >> for (I #i = cs.iterator(); #i.hasNext(); ) { >> >> C #c = #i.next(); >> >> if (#c == null || #c instanceof D) { >> >> D d = (C)#c; >> >> ... >> >> } >> >> } >> >> >> >> For an array: >> >> >> >> C[] ca... >> >> for (int i = 0; i < ca.length; i++) { >> >> C #c = ca[i]; >> >> if (#c == null || #c instanceof D) { >> >> D d = (C)#c; >> >> ... >> >> } >> >> } >> >> >> >> Note that we need to test against null to keep the same behavior as >> the >> regular enhanced for loop. >> >> >> >> TESTING: >> >> >> >> This feature can be tested in the same way the enhanced for loop is >> tested. >> >> >> >> >> >> LIBRARY SUPPORT: >> >> >> >> There is no need for library support. >> >> >> >> >> >> REFLECTIVE APIS: >> >> >> >> No updates to the reflection APIs are needed. >> >> >> >> >> >> OTHER CHANGES: >> >> >> >> No other changes are needed. >> >> >> >> >> >> MIGRATION: >> >> >> >> Migration of existing enhanced for loop can be done if one desires so. >> >> >> >> COMPATIBILITY >> >> >> >> >> >> BREAKING CHANGES: >> >> >> >> This feature would not break any existing programs, since the new >> feature only permits more code to be parsed than before. >> >> >> >> >> >> EXISTING PROGRAMS: >> >> >> >> Class file format does not change, so existing programs can use class >> files compiled with the new feature without problems. >> >> >> >> >> >> >> >> >> >> >> >> >> >> > > From rssh at gradsoft.com.ua Fri Apr 3 01:19:42 2009 From: rssh at gradsoft.com.ua (rssh at gradsoft.com.ua) Date: Fri, 3 Apr 2009 11:19:42 +0300 (EEST) Subject: PROPOSAL: @OverrideAll annotation In-Reply-To: <17542308.1238746196681.JavaMail.root@mswamui-thinleaf.atl.sa.earthlin k.net> References: <17542308.1238746196681.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> Message-ID: > My major problem with this proposal is that it doesn't seem to be > straightforward to generate the bodies of methods that have to return > something. Particularly for code such as implementations of the Visitor > pattern. > > Having un-overridden methods simply return null or zero is often not the > right thing to do. > > It's OK for generating methods that just take parameters, I suppose. > May be this is not, what author of original proposal mean, but have class annotation @OverrideAll, which does not generate any code, just throw compile-time error when exists non-overridden member functions is helpfull in some situations and prevent from hard to debug errors. > Still, having annotations generate code or otherwise affect the operation > of a program is apparently a no-no per Sun's rules. If something like this > is going to happen, I think it needs a new keyword or something rather > than using an annotation. > > (Although, personally, I don't think it would be such a bad thing if code > generation via annotation existed, but were limited only to certain > annotations in a specific package duly designated by the language > implementors. Annotations have one nice quality that other ways of > extending the language don't: You can create new "keywords" at will with > no risk of breaking someone's perfectly-working code. If they don't import > the annotation, they won't need to be impacted by it. I sort of wish there > was an alternative to annotations (@@Foo instead of @Foo?) which was > explicitly for the purpose of telling the compiler to generate boilerplate > code of various types. Decorators in Python sort of serve this purpose, > for instance.) > > Derek > > -----Original Message----- >>From: rssh at gradsoft.com.ua >>Sent: Mar 31, 2009 10:02 AM >>To: Gabriel Belingueres >>Cc: coin-dev >>Subject: Re: PROPOSAL: @OverrideAll annotation >> >>> Hi, >>> >>> I've written a new feature that might be comfortable to use for >>> someone. All input is welcomed. >>> >> >>It-is possible to do near same with annotation API (create a superclass >> which will override all) >> >>But -- sometime we really need to say, that all methods 'mus be' >>overriden. (For example - when implementing Proxy pattern). >>In such case class-level annotation '@OverrideAll' which tell compiler >>to check, that all methods must be overriden -- brilliant idea. >> >> >> >> >> >>> Regards, >>> Gabriel >>> >>> PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 >>> >>> AUTHOR(S): Gabriel Belingueres >>> >>> OVERVIEW >>> >>> Add an @OverrideAll annotation to allow a class to override all >>> inherited methods with a trivial implementation. The resulting class >>> then could be used as the basis for a Null Object pattern (or even a >>> basic Mock object.) >>> >>> >>> FEATURE SUMMARY: >>> >>> The proposed @OverrideAll annotation will allow the class to override >>> all methods (from its superclasses and implemented interfaces) with a >>> trivial body, but the defined class can choose to implement specific >>> methods, replacing those that would be produced automatically by the >>> annotation. >>> >>> >>> MAJOR ADVANTAGE: >>> >>> Less coding for implementing Null Objects, or simple tests. >>> >>> >>> MAJOR BENEFIT: >>> >>> Let the compiler implement all uninteresting, non relevant behavior by >>> automatically providing with a trivial implementation of the inherited >>> methods. >>> >>> >>> MAJOR DISADVANTAGE: >>> >>> Might be a cause of NullPointerException if not used judiciously. >>> >>> >>> ALTERNATIVES: >>> >>> Implement all uninteresting methods by yourself by providing yourself >>> a trivial implementation (though actually popular IDEs can do this >>> automatically for you already.) >>> >>> EXAMPLES >>> >>> Given: >>> >>> class B {} >>> >>> public class A implements I1, I2 { >>> >>> public static final int VAR = 1; >>> >>> private B b; >>> >>> public static Integer getSome() { >>> return VAR; >>> } >>> >>> public A() { >>> } >>> >>> public A(B b) { >>> this.b=b; >>> } >>> >>> public B getB() { >>> return b; >>> } >>> >>> public void setB(B b) { >>> this.b=b; >>> } >>> >>> protected void doProtected() { ... } >>> >>> private void doPrivate() { ... } >>> >>> A someNewA() { ... } >>> >>> public synchronized void someSynchronized() { >>> } >>> >>> } >>> >>> then: >>> >>> @OverrideAll >>> public class NullA extends A { >>> } >>> >>> is equivalent to declare: >>> >>> public class NullA extends A { >>> >>> public NullA() {} >>> >>> public NullA(B b) { >>> super(b); >>> } >>> >>> public B getB() { >>> return null; >>> } >>> >>> public void setB(B b) { >>> } >>> >>> protected void doProtected() { >>> // empty >>> } >>> >>> A someNewA() { >>> return null; >>> } >>> >>> public synchronized void someSynchronized() { >>> // empty >>> } >>> >>> } >>> >>> You may not want the default trivial implementation in some methods, >>> then you override them as usual: >>> >>> @OverrideAll >>> public class NullA extends A { >>> >>> @Override >>> public B getB() { >>> return new B(); >>> } >>> >>> @Override >>> public synchronized void someSynchronized() { >>> System.out.println("overridden"); >>> } >>> >>> } >>> >>> EXAMPLE 2 >>> >>> Implement a trivial Collection interface just to test that adding >>> elements will increase the collection size: >>> >>> Currently: >>> >>> public class SomeCollection implements Collection { >>> >>> private int counter; >>> >>> @Override >>> public boolean add(E arg0) { >>> counter++; >>> return true; >>> } >>> >>> @Override >>> public boolean addAll(Collection c) { >>> counter += c.size(); >>> return true; >>> } >>> >>> @Override >>> public void clear() { >>> } >>> >>> @Override >>> public boolean contains(Object arg0) { >>> return false; >>> } >>> >>> @Override >>> public boolean containsAll(Collection arg0) { >>> return false; >>> } >>> >>> @Override >>> public boolean isEmpty() { >>> return false; >>> } >>> >>> @Override >>> public Iterator iterator() { >>> return null; >>> } >>> >>> @Override >>> public boolean remove(Object arg0) { >>> return false; >>> } >>> >>> @Override >>> public boolean removeAll(Collection arg0) { >>> return false; >>> } >>> >>> @Override >>> public boolean retainAll(Collection arg0) { >>> return false; >>> } >>> >>> @Override >>> public int size() { >>> return counter; >>> } >>> >>> @Override >>> public Object[] toArray() { >>> return null; >>> } >>> >>> @Override >>> public T[] toArray(T[] arg0) { >>> return null; >>> } >>> >>> } >>> >>> With the annotation: >>> >>> @OverrideAll >>> public class SomeCollection implements Collection { >>> >>> private int counter; >>> >>> @Override >>> public boolean add(E arg0) { >>> counter++; >>> return true; >>> } >>> >>> @Override >>> public boolean addAll(Collection c) { >>> counter += c.size(); >>> return true; >>> } >>> >>> >>> @Override >>> public int size() { >>> return counter; >>> } >>> >>> } >>> >>> >>> DETAILS >>> >>> >>> SPECIFICATION: >>> >>> A preliminary specification follows: >>> >>> As this feature is proposed as an annotation for code generation, no >>> changes to the current JLSv3 are needed. >>> >>> The annotation will generate "trivial" overridden implementations for >>> all methods not specified in the class, for each superclass in the >>> hierarchy (except Object) and implemented interface. >>> >>> - Static methods, private methods, final methods, constructors and >>> methods from class Object should never be generated. >>> - If some superclass (except Object) has already overridden some >>> Object class methods, then do NOT generate an empty overridden method >>> (to reuse current behavior.) (for example, if some superclass already >>> override toString(), equals() or hashCode().) >>> >>> - OPTIONAL: add a parameter to the @OverrideAll annotation to indicate >>> if @Deprecated methods should not be implemented. >>> >>> Trivial implementation for generated methods: >>> >>> - Methods returning void will have an empty body. (OPTIONAL: add a >>> parameter to the @OverrideAll annotation to indicate that it should >>> throw UnsupportedOperationException instead) >>> - Methods returning a primitive type will have a body returning the >>> same default value that would have for uninitialized instance >>> variables. (JLS section 4.12.5.) >>> - Methods returning a reference type will "return null;". (JLS section >>> 4.12.5.) >>> - The method will never return a covariant return type (because in >>> case of implementing a Null object, it should be undistinguished from >>> the common case) >>> - Methods that throws checked exceptions can be modified to delete the >>> throws clause. (ie. the trivial implementation should not throw >>> checked exceptions) >>> - Synchronized methods should retain that attribute. >>> >>> >>> COMPILATION: >>> >>> Compilation should proceed as usual, except that the annotation >>> processor would generate the code when it encounters an annotated >>> class. >>> >>> No changes to the class file format are needed. >>> >>> >>> TESTING >>> >>> Test cases should be done, including testing with classes implementing >>> several interfaces, classes with generics, inner classes, etc. >>> >>> >>> LIBRARY SUPPORT: >>> >>> No, except creating the new annotation. >>> >>> >>> REFLECTIVE APIS: >>> >>> No changes foreseen. >>> >>> >>> OTHER CHANGES: >>> >>> Output of javadoc tool. >>> >>> >>> MIGRATION: >>> >>> Just add the annotation to class level, and erase your trivially >>> implemented overridden methods. >>> >>> >>> COMPATIBILITY >>> >>> BREAKING CHANGES: >>> All existing programs remain valid. >>> >>> EXISTING PROGRAMS: >>> The semantics of existing class files and legal source files are >>> unchanged by this feature. >>> >>> >>> REFERENCES >>> >>> EXISTING BUGS: >>> >>> None that I know about. >>> >>> URL FOR PROTOTYPE: >>> >>> None at this time. >>> >>> >> >> >> > > From Joe.Darcy at Sun.COM Fri Apr 3 01:25:07 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Fri, 03 Apr 2009 01:25:07 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <6F835C91-A2F2-4050-BD03-DB1B462C2B4F@sun.com> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <6F835C91-A2F2-4050-BD03-DB1B462C2B4F@sun.com> Message-ID: <49D5C7E3.50801@sun.com> Hello. Some comments interspersed. John Rose wrote: > Here is a text form of the proposal, for the archives. The wiki form > should be equivalent at the moment, but as edits are made the wiki > form will be normative. > > Best wishes, > -- John > > AUTHOR(S): > > John Rose > > OVERVIEW > > Create source-code syntaxes for using new JVM features from JSR 292. > These are invokedynamic instructions, method handle invocation, > certain relaxed conversions, and exotic identifiers. [snip] > 1.3 Any call to a method in Dynamic accepts an optional type parameter > which specifies the return type of the call site's descriptor. The > type parameter may any type whatever, including void or a primitive > type. If it is omitted it defaults to the type java.dyn.Dynamic > itself. (See part 4 for conversion rules involving Dynamic.) > Reiterating a point Neal raised, if Dynamic is not related to Object, what does that mean when Dynamic is used as the format type argument to a type parameter? What do "? extends Dynamic" and "? super Dynamic" mean to the type system? > Dynamic x = Dynamic.myGetCurrentThing(); // type () -> Dynamic > Dynamic.myPutCurrentThing(x); // type (Dynamic) -> void > int y = Dynamic.myHashCode((Object)x); // type (Object) -> > int > boolean z = Dynamic.myEquals(x, y); // type (Dynamic, > int) -> boolean > > (Rationale: Although it is strange for non-references to appear in the > syntactic position of type arguments, this design is far simpler than > inventing a completely new syntax for specifying the return type of > the call site, as some early prototypes did.) > > 1.4 For the purposes of determining the descriptor of the > invokedynamic instruction, null arguments (unless casted to some other > type) are deemed to be of reference type java.lang.Void. This is a > pragmatic choice, compatible with the verifier and partially coherent > with the meaning of the type Void, since it happens to allow only null > reference values. Conversely, void method return values are reflected > as null values. The type Void will appear only to the bootstrap > method, and will serve notice that the call site contains a null, > rather than an explicitly typed reference. > > Dynamic.myPrintLine(null); // type (Void) -> Dynamic > Dynamic.foo((String)null, null); // type (String, Void) -> > void > > 1.5 No checked exceptions are produced by any call to Dynamic. > > try { Dynamic.foo(); } catch (Exception ee) { } // a compile- > time error > Actually there is a special rule that catching Exception is always okay per JLS 11.2.3; this program is legal and compiles fine: public class Test { public static void main(String... args){ try { ; } catch (Exception e) { ; } } } [snip] > 2.2 Any reference of type MethodHandle may be qualified with the > method name "invoke" and invoked on any number and type of arguments. > Only the method named "invoke" is treated this new way. All other > expressions involving MethodHandle are unchanged in meaning, including > selection of members other than "invoke", casting, and instanceof. > > MethodHandle mh = ...; > mh.invoke("foo", 42); // argument types (String, int) > MethodType mtype = mh.type(); // no new rules here; see JSR 292 > javadocs > mh.neverBeforeSeenName(); // no new rules; must raise an error > > In effect, java.dyn.MethodHandle appears to have an infinite number of > non-static methods named "invoke", of every possible signature. > > (In fact, JSR 292 specifies that each individual method handle has a > unique type signature, and may be invoked only under that specific > type. This type is checked on every method handle call. JSR 292 > guarantees runtime type safety by requiring that an exception be > thrown if a method handle caller and callee do not agree exactly on > the argument and return types. The details of this check are not part > of this specification, but rather of the MethodHandle API.) > So what are the notions of identity and equality for method handles? [snip] > 4.1 As specified above, the interface java.dyn.Dynamic has no > supertypes or members. As such, it is a bare reference type. (As an > arbitrary relation, the superclass of Dynamic[] is Object[].) We > Are there any other type building operations besides arrays we need to worry about? [snip] > 4.6 The expression syntaxes with predefined meaning for dynamic sub- > expressions are those which perform the conversions described above. > These are assignment "=" and casts. Dynamic expressions may also be > tested with instanceof. Also, Dynamic values may be declared, > assigned to variables, passed as method or constructor arguments, and > returned from methods. > > But, the Java operators "==" "!=" "+" "+=" on reference types are > clarified to apply only to reference types which are java.lang.Object > or one of its subtypes; they do not have a predefined meaning if > either operand is dynamic. The "synchronized" and "throw" statements > cannot be applied to dynamic expressions. > So if there is no predefined meaning, are those operations illegal? [snip] > REFLECTIVE APIS: > > The method java.lang.Class.getDeclaredMethod must be special-cased to > always succeed for MethodHandle.invoke and for Dynamic (any method > name), regardless of signature. The JSR 292 JVM has this logic > already, but it must be exposed out through the Class API. > > Only single-result reflection lookups need to be changed. Multiple- > method lookups should *not* produce implicitly defined methods. > > The javax.lang.model API (which is used internally by javac) does not > need specialization, because the implicitly defined methods of > MethodHandle and Dynamic do not ever need to mix with other more > normal methods. The static (compile-time) model of Dynamic may not > present any enclosed elemeents, while that of MethodHandle must not > present any methods named "invoke". > > Facilities which compute type relations (such as > javax.lang.model.util.Types) may need to be updated to take Dynamic > into account. Generally speaking, the new Dynamic conversions operate > in parallel to the implicit boxing conversions. That is, they add no > new subtype or supertype relations, but they provide a few more ways > for values to be implicitly converted or casted. > Yes, I would expect a few changes to the type-related APIs. They may also need to be changes to programs that assume Object is the root of the reference type hierarchy. I know I've written annotation processing code like that and Dynamic would need to be special cased in there. -Joe From vapor1 at teleport.com Fri Apr 3 01:26:41 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 3 Apr 2009 04:26:41 -0400 (EDT) Subject: PROPOSAL: 'final' without explicit type (update) Message-ID: <31420118.1238747201155.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> -----Original Message----- >From: Reinier Zwitserloot >Sent: Mar 31, 2009 11:28 AM >To: Tim Lebedkov >Cc: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: 'final' without explicit type (update) > >Tim: > >This isn't the first time I've read about inferring types, and this >isn't the first time I've seen 'final' used for it. > >It's -not- just to avoid a new keyword. It's quite specifically >because auto-typing should only be done for final variables. The >problem is this: > ... This message had a good explanation of why final is preferred, and an explanation of why not using an interface type is probably OK in this limited circumstance. Probably the best explanations of these issues I've seen. (I've just snipped it away. Read the Reiner's original post for the original description.) >FWIW, I'm -strongly- in favour of implicit typing for final local >method variables, and opposed to extending this for non-finals, not >just because its hard to come up with a syntax for it, due to there >being no readily available keywords or operators to do it with. := >comes to mind, but that's about it. I agree with this, on both points. (I'm perhaps not as "strongly" in favor as Reiner, but I do think that having implicit typing for local variables would be a net positive in readability, despite the lack of an explicit type in the code. I think that implicit typing would probably be a mistake for fields, however, even if they're final. (They're accessed in too many places.) With code that uses generics a lot, the overhead of having to mention long type names multiple times starts to become large. Improved type inference would help a lot. Derek From vapor1 at teleport.com Fri Apr 3 02:13:23 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 3 Apr 2009 05:13:23 -0400 (EDT) Subject: PROPOSAL: Binary Literals Message-ID: <31379447.1238750003379.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> -----Original Message----- >From: Mark Thornton >Sent: Mar 26, 2009 4:54 AM >To: Derek Foster >Cc: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: Binary Literals > >Derek Foster wrote: >> You are not considering the impact of constant folding on compiler optimizations. >> >> Not all constants are created equal. Constants whose values can be determined at compile time can be inlined by the compiler, and arithmetic expressions involving them can often therefore be simplified at compile time. This process is known as "constant folding". The resulting code need not reference the original variable to get the constant at all -- it can just use the inlined result of evaluating the expression. Additional compiler optimizations may then be performed on the basis of these folded constants. For instance, a compiler might decide to compile this code: >> >Perhaps you missed my suggestion that the range of operations permitted >in constant expressions be extended to include the bit munging >operations (and possibly others). We could perhaps have an annotation >that was only permitted on static methods in the java.* name space and >which required the compiler to execute the method at compile time if its >arguments were compile time constants. The compiler could alternatively >have a private list of such methods, the annotation conveniently tells >everyone else what is on the list. I did miss that suggestion, actually. Though now that you've mentioned it: It's not that I would mind that feature in the compiler ("that feature" being compile-time evaluation of common library methods which are passed parameters known at compile time). However, it doesn't sound terribly easy to implement. Especially when you consider the implications of having to do error handling on illegal function arguments at compile time, rather than at runtime. In fact, it sounds a whole lot more intrusive and a lot more work for the compiler team than just being able to parse a simple binary number. Besides that issue, however, and besides the also (substantial!) issue of the readability of (0b11010100 & 0b01001011) ^ (0b01101010 | 0b10010100) vs. (Byte.parseByte("0b11010100",2) & Byte.parseByte("0b01001011",2) ^ (Byte.parseByte("0b01101010",2) | Byte.parseByte("0b10010100",2)) there is also the fact that some Java platforms simply don't HAVE a Byte class. For instance, consider JavaCard: http://java.sun.com/javacard/ A JavaCard, if you weren't aware, is a literally credit-card-sized computer running a very stripped-down JVM that is just capable enough that it can do encryption calculations in order to ensure, for instance, that the card is connecting to an authorized and properly authenticated bank machine. There's no room in a machine that small for the vast majority of standard library classes, most of which would be useless anyway in a computer of those capabilities. For instance, there is no support for java.lang.String, java.lang.Integer, and so forth (since this computer has no need to process Strings, and only needs integers for the purpose of number-crunching math, not nullness checks). Programmers for JavaCard could easily use binary numbers in their encryption algorithms. That's a use case that is easily handled by my proposal. However, importing a library that depends on Byte.parseInt(java.lang.String, int) isn't going to be sufficient for them, because they have neither Byte nor String. When I worked on the massively parallel processor chip I described earlier, our Java didn't have Byte or String classes either. Even if it had had something like String, nobody probably would have used it. Text processing is just not the kind of thing you use a massively parallel number crunching chip to do. Also, when each processor on the chip has around 8Kbytes of ROM to store program code, you don't want to be wasting it on library routines, or calls to them, that you don't really need. Derek >Mark Thornton > From mthornton at optrak.co.uk Fri Apr 3 02:59:52 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Fri, 03 Apr 2009 10:59:52 +0100 Subject: PROPOSAL: Binary Literals In-Reply-To: <31379447.1238750003379.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> References: <31379447.1238750003379.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> Message-ID: <49D5DE18.3000606@optrak.co.uk> Derek Foster wrote: > > I did miss that suggestion, actually. Though now that you've mentioned it: > > It's not that I would mind that feature in the compiler ("that feature" > being compile-time evaluation of common library > methods which are passed parameters known at compile time). However, > it doesn't sound terribly easy to implement. Especially when you consider > the implications of having to do error handling on illegal function > arguments at compile time, rather than at runtime. In fact, it sounds > a whole lot more intrusive and a lot more work for the compiler team > than just being able to parse a simple binary number. > They already have to handle the exception resulting from integer division by zero, so I don't think this makes much difference to compile time expression evaluation. This is especially true if only methods in the java namespace were permitted (and these could be restricted to 'easy' methods). > there is also the fact that some Java platforms simply don't HAVE a Byte > class. For instance, consider JavaCard: > > http://java.sun.com/javacard/ > > A JavaCard, if you weren't aware, is a literally credit-card-sized computer > I was aware it existed but my Java experience hasn't gone any lower than JavaME. However when expressions are evaluated at compile time the resulting byte code contains no reference to the source of the computation -- only the result appears. Thus the fact that Byte isn't available in the target platform wouldn't matter. For example: class A { public static final String STREET="Mead Lane"; } class B { public static final String TOWN = "Hertford"; } class MyApp { public static final String ADDRESS = A.STREET + "," + B.TOWN; } The byte code for MyApp contains ADDRESS = "Mead Lane, Hertford" and no reference to classes A, or B. I don't like this behaviour, but it is what currently happens. I think it was intended to assist with implementation on restricted environments. Regards, Mark Thornton From reinier at zwitserloot.com Fri Apr 3 03:14:57 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Fri, 3 Apr 2009 12:14:57 +0200 Subject: Naked dot - accessing object fields through unqualified In-Reply-To: <19432589.1238742258930.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> References: <19432589.1238742258930.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> Message-ID: <763DE2D4-9ADE-40FF-A37A-D8963DCA2CD5@zwitserloot.com> You can think what you want, but that's not likely. Again, a source keyword would open up an opportunity to engage a bunch of strict checks, but you underestimate the amount of code that people have inherited from people that inherited it from people that inherited it, and each added their own little mess to the spaghetti. Them, and a bunch of contractors in between. It was thoroughly tested somewhere in 1999, and nobody even knows how it works, but every so often someone does need to wade into the mess and fix something. You can not force these people to deal with a gazillion 'these are likely bugs' errors. It needs to be opt-in. Your further suggestions are even further off the mark; why is an abstract class with a private constructor bad? It's a matter of style; most people who want utility classes make their constructors final, but some make their class abstract as well, because of the link between 'abstract' classes (cannot be instantiated) and utility classes (should not be instantiated). I believe a programming language should set style as much as possible, but java doesn't do that now, and changing it is a massive turn-around in java dogma that you or I just cannot take. C style array declarations - okay, fine. Yes. Guuuuhhhh, they are making working with the [ and ] symbols in a way that doesn't screw up the parser annoying, to say the least. Yet another argument for a 'source' keyword. If people don't want to listen to or setup their warnings, then more errors is just not going to help. Your suggestion is: Some companies are so boneheaded they won't listen to their IDE's warnings, so we'll just force it on them with a javac change? Nononono. That'll just result in them not updating their java, and that's one of those things sun (rightfully) wants to avoid like the plague without a solid reason to do it (like wiping the slate clean across the board, not just in this niche area). At any rate, there's no way to centralize errors/warnings in javac. Period. They are far too contentious. As I have said before, APT is a good start, but some more support for external warning/error plugins would help (including the ability to add more SuppressWarnings keywords). It would be nice if javac shipped out of the box with an extensive set, sure, but, again, opt-in. --Reinier Zwitserloot On Apr 3, 2009, at 09:04, Derek Foster wrote: > Replies inline. > > -----Original Message----- >> From: Reinier Zwitserloot >> Sent: Mar 31, 2009 9:03 AM >> To: Derek Foster >> Cc: coin-dev at openjdk.java.net >> Subject: Re: Naked dot - accessing object fields through >> unqualified "." [C1] >> >> 'Self-assignment is forbidden' would not be backwards compatibile. >> Yes, such code would most likely be a bug, but its still an issue. It >> would have to be a warning, at best. > > Personally, I think it should be an error, since there seems to be > no valid reason to do it, and it almost certainly indicates a bug. I > think that compilers should default to being in a 'strict' mode > where things like this that have been found to be bad ideas with > virtually no upside are treated as illegal, even if that makes them > not fully backwards compatible. For backwards compatibility, there > could be a command-line switch to turn off strict mode if necessary > for compiling old code. > > Some other things I'd like to see in this category: > > * Having an abstract class with a constructor that has 'public' or > 'private' access. > > * Using C-style array declarations. (int x[] instead of int[] x) > > I could probably think of a few more. > >> However: >> >> Every single external java compiler I know of will warn you when you >> self-assign. Eclipse does it. So does netbeans. So does IDEA. So does >> pmd. So does findbugs. > > Mere warnings are not enough to stop people from doing this sort of > thing, especially when the warning message is buried in 436 other > warning messages about code which is less unambiguously broken than > this is. (Note: I *HATE* it when people ignore compiler warnings > like this, but I am speaking from experience when I say that it > usually takes years to convince a company to clean up its act.) > Unfortunately, I have worked for lots of companies that routinely > ignore warnings. > >> If you internalize the self-assignment warning, where do you stop? >> There are literally hundreds of 'duh, that must be a bug' warnings >> you >> could generate. Not all of them are as obvious, or as non- >> contentious, >> as 'self assignment'. So, where do you stop? Do we use the glacial >> nature of the language changes process to set this up? > > I think that when a practice is almost always problematic, is easy > to fix, and has no legitimate purpose (and/or has an easy workaround > in the few cases that it is legitimate), it should be made an error > (with the caveats above). I don't think that we should carry along > every single design mistake in the 1.0 edition of the Java Language > Standard with us until the end of time. The ability to achieve > backwards compatibility is important (hence the ability to turn off > strict mode I described above), but clarity of language design and > preventing common errors is too. Otherwise, the amount of code which > contains the error in question just keeps growing over time. > >> I say: No. The >> community has done a fine job of addressing these issues by creating >> code checkers. > > In my experience, the community, by and large, does not use code > checkers. Relatively few companies do. Again, I wish it were > otherwise, but the truth is that most companies assume that if > something passes the checks done by the compiler, it's probably > fine. Having tried to introduce them into companies a few times, I > can report that most software engineers really don't want to be > bothered with them (and are convinced that checkers won't find any > bugs important enough to justify the time spent learning to use them > and cleaning up lots of innocuous warnings just for the sake of the > tool). Again, I thoroughly disagree with that philosophy, but that's > what I have heard repeatedly in industry. > > Also, using a code checker is often a painful experience if you are > forced to use a framework written by people who don't use them. > > The other issue is that every code checker checks for a different > set of things. Just because your code passes your code checker's > rules doesn't mean it will pass mine, or vice versa. The Sun Java > compiler as of a specific version, at least, is the same for > everybody. > >> So, I'd instead suggest: >> Any improvements to java core in this area should focus on improving >> the ability for external tools to integrate better. For example, a >> way >> to extend @SuppressWarnings with additional keywords would be >> great. A >> way to let javac auto-find (via the SPI system) 'warning/error' >> plugins would be another fine idea. Having any kind of plugin system >> for the official javac to give other tools a go at creating warnings >> and errors on the AST that javac's parser is building would be good >> already, using SPI to find these automatically is just one way of >> doing it. I'm not sure APT is quite right for the job; I don't want >> to >> litter annotations to the gist of '@ExtensivelyCheckMe' all over the >> place. > > I'm certainly in favor of making life easier for code checkers. > However, checkers that don't get used are no better than ones that > don't exist. Javac (or jikes, etc.) gets used every time someone > compiles a program. That means it's going to have far more influence > on the correctness of the majority of Java code than any other tool. > > Derek > >> >> >> --Reinier Zwitserloot >> >> >> >> On Mar 29, 2009, at 04:42, Derek Foster wrote: >> >>> The major problem I have with this proposal is that it does not >>> address the point of why I use a prefix on field names. As such, I >>> would still continue to use a prefix even if this proposal were >>> implemented. >>> >>> In short, I use a prefix to avoid typographical mistakes, like this >>> one: >>> >>> void setFoo(Thing foob) { // Typo! >>> this.foo = foo; >>> } >>> >>> This will compile, and no warnings are produced, but it ends up >>> assigning foo to itself, which is not what was intended. >>> >>> Your proposal has exactly the same problem: >>> >>> void setFoo(Thing foob) { // Typo! >>> .foo = foo; >>> } >>> >>> It therefore does not substitute for a field prefix, which WILL fix >>> the problem: >>> >>> void setFoo(Thing foob) { // Typo! >>> _foo = foo; // ERROR! Undefined variable 'foo'. >>> } >>> >>> So unless you had some way to make use of the dot prefix mandatory >>> and the only legal way to access fields (which I would like, but >>> which would be an extremely backwards-incompatible change that will >>> never happen in Java), I don't see that adding an optional dot >>> prefix helps the situation except to reduce typing in constructor >>> and setter methods slightly. >>> >>> (Note: I would love a "self-assignment is forbidden" change to Java. >>> If I have time after my other proposals, I might write one up. >>> (Anyone else want to volunteer? This one is easy!) I might be >>> willing to forego prefixes and use the "this.foo = foo" approach, or >>> even the ".foo = foo" approach, if I was sure it wouldn't cause me >>> to fall into the self-assignment trap.) >>> >>> Derek >>> >>> >> > From Thomas.Hawtin at Sun.COM Fri Apr 3 03:24:24 2009 From: Thomas.Hawtin at Sun.COM (Tom Hawtin) Date: Fri, 03 Apr 2009 11:24:24 +0100 Subject: Proposal: Sameness operators In-Reply-To: <49D5B109.2020007@sun.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <4b4f45e00904020524p27741baeo40483e83d71dc768@mail.gmail.com> <275433EA-A420-42C8-891D-3B0C2629222A@zwitserloot.com> <49D54420.5090906@sun.com> <49D5B109.2020007@sun.com> Message-ID: <49D5E3D8.8020901@sun.com> Joseph D. Darcy wrote: > Yes, I meant to type "java.util.Objects" -- having a class other than > java.lang.Object named "Object" is just wrong! But having an interface named "Object" is just CORBA! Tom From reinier at zwitserloot.com Fri Apr 3 03:27:40 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Fri, 3 Apr 2009 12:27:40 +0200 Subject: PROPOSAL: @OverrideAll annotation In-Reply-To: <17542308.1238746196681.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> References: <17542308.1238746196681.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> Message-ID: <61773C12-3611-452A-B0A1-8B873F0E47E1@zwitserloot.com> What Derek said - this is not a good idea. rssh: The proposal specifically states that each non-overridden method is to be generated with an empty body, or if that isn't possible due to a return type, the default return for that type (0/false/0.0/'\0'/ null). --Reinier Zwitserloot On Apr 3, 2009, at 10:09, Derek Foster wrote: > My major problem with this proposal is that it doesn't seem to be > straightforward to generate the bodies of methods that have to > return something. Particularly for code such as implementations of > the Visitor pattern. > > Having un-overridden methods simply return null or zero is often not > the right thing to do. > > It's OK for generating methods that just take parameters, I suppose. > > Still, having annotations generate code or otherwise affect the > operation of a program is apparently a no-no per Sun's rules. If > something like this is going to happen, I think it needs a new > keyword or something rather than using an annotation. > > (Although, personally, I don't think it would be such a bad thing if > code generation via annotation existed, but were limited only to > certain annotations in a specific package duly designated by the > language implementors. Annotations have one nice quality that other > ways of extending the language don't: You can create new "keywords" > at will with no risk of breaking someone's perfectly-working code. > If they don't import the annotation, they won't need to be impacted > by it. I sort of wish there was an alternative to annotations (@@Foo > instead of @Foo?) which was explicitly for the purpose of telling > the compiler to generate boilerplate code of various types. > Decorators in Python sort of serve this purpose, for instance.) > > Derek > > -----Original Message----- >> From: rssh at gradsoft.com.ua >> Sent: Mar 31, 2009 10:02 AM >> To: Gabriel Belingueres >> Cc: coin-dev >> Subject: Re: PROPOSAL: @OverrideAll annotation >> >>> Hi, >>> >>> I've written a new feature that might be comfortable to use for >>> someone. All input is welcomed. >>> >> >> It-is possible to do near same with annotation API (create a >> superclass >> which will override all) >> >> But -- sometime we really need to say, that all methods 'mus be' >> overriden. (For example - when implementing Proxy pattern). >> In such case class-level annotation '@OverrideAll' which tell >> compiler >> to check, that all methods must be overriden -- brilliant idea. >> >> >> >> >> >>> Regards, >>> Gabriel >>> >>> PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 >>> >>> AUTHOR(S): Gabriel Belingueres >>> >>> OVERVIEW >>> >>> Add an @OverrideAll annotation to allow a class to override all >>> inherited methods with a trivial implementation. The resulting class >>> then could be used as the basis for a Null Object pattern (or even a >>> basic Mock object.) >>> >>> >>> FEATURE SUMMARY: >>> >>> The proposed @OverrideAll annotation will allow the class to >>> override >>> all methods (from its superclasses and implemented interfaces) >>> with a >>> trivial body, but the defined class can choose to implement specific >>> methods, replacing those that would be produced automatically by the >>> annotation. >>> >>> >>> MAJOR ADVANTAGE: >>> >>> Less coding for implementing Null Objects, or simple tests. >>> >>> >>> MAJOR BENEFIT: >>> >>> Let the compiler implement all uninteresting, non relevant >>> behavior by >>> automatically providing with a trivial implementation of the >>> inherited >>> methods. >>> >>> >>> MAJOR DISADVANTAGE: >>> >>> Might be a cause of NullPointerException if not used judiciously. >>> >>> >>> ALTERNATIVES: >>> >>> Implement all uninteresting methods by yourself by providing >>> yourself >>> a trivial implementation (though actually popular IDEs can do this >>> automatically for you already.) >>> >>> EXAMPLES >>> >>> Given: >>> >>> class B {} >>> >>> public class A implements I1, I2 { >>> >>> public static final int VAR = 1; >>> >>> private B b; >>> >>> public static Integer getSome() { >>> return VAR; >>> } >>> >>> public A() { >>> } >>> >>> public A(B b) { >>> this.b=b; >>> } >>> >>> public B getB() { >>> return b; >>> } >>> >>> public void setB(B b) { >>> this.b=b; >>> } >>> >>> protected void doProtected() { ... } >>> >>> private void doPrivate() { ... } >>> >>> A someNewA() { ... } >>> >>> public synchronized void someSynchronized() { >>> } >>> >>> } >>> >>> then: >>> >>> @OverrideAll >>> public class NullA extends A { >>> } >>> >>> is equivalent to declare: >>> >>> public class NullA extends A { >>> >>> public NullA() {} >>> >>> public NullA(B b) { >>> super(b); >>> } >>> >>> public B getB() { >>> return null; >>> } >>> >>> public void setB(B b) { >>> } >>> >>> protected void doProtected() { >>> // empty >>> } >>> >>> A someNewA() { >>> return null; >>> } >>> >>> public synchronized void someSynchronized() { >>> // empty >>> } >>> >>> } >>> >>> You may not want the default trivial implementation in some methods, >>> then you override them as usual: >>> >>> @OverrideAll >>> public class NullA extends A { >>> >>> @Override >>> public B getB() { >>> return new B(); >>> } >>> >>> @Override >>> public synchronized void someSynchronized() { >>> System.out.println("overridden"); >>> } >>> >>> } >>> >>> EXAMPLE 2 >>> >>> Implement a trivial Collection interface just to test that adding >>> elements will increase the collection size: >>> >>> Currently: >>> >>> public class SomeCollection implements Collection { >>> >>> private int counter; >>> >>> @Override >>> public boolean add(E arg0) { >>> counter++; >>> return true; >>> } >>> >>> @Override >>> public boolean addAll(Collection c) { >>> counter += c.size(); >>> return true; >>> } >>> >>> @Override >>> public void clear() { >>> } >>> >>> @Override >>> public boolean contains(Object arg0) { >>> return false; >>> } >>> >>> @Override >>> public boolean containsAll(Collection arg0) { >>> return false; >>> } >>> >>> @Override >>> public boolean isEmpty() { >>> return false; >>> } >>> >>> @Override >>> public Iterator iterator() { >>> return null; >>> } >>> >>> @Override >>> public boolean remove(Object arg0) { >>> return false; >>> } >>> >>> @Override >>> public boolean removeAll(Collection arg0) { >>> return false; >>> } >>> >>> @Override >>> public boolean retainAll(Collection arg0) { >>> return false; >>> } >>> >>> @Override >>> public int size() { >>> return counter; >>> } >>> >>> @Override >>> public Object[] toArray() { >>> return null; >>> } >>> >>> @Override >>> public T[] toArray(T[] arg0) { >>> return null; >>> } >>> >>> } >>> >>> With the annotation: >>> >>> @OverrideAll >>> public class SomeCollection implements Collection { >>> >>> private int counter; >>> >>> @Override >>> public boolean add(E arg0) { >>> counter++; >>> return true; >>> } >>> >>> @Override >>> public boolean addAll(Collection c) { >>> counter += c.size(); >>> return true; >>> } >>> >>> >>> @Override >>> public int size() { >>> return counter; >>> } >>> >>> } >>> >>> >>> DETAILS >>> >>> >>> SPECIFICATION: >>> >>> A preliminary specification follows: >>> >>> As this feature is proposed as an annotation for code generation, no >>> changes to the current JLSv3 are needed. >>> >>> The annotation will generate "trivial" overridden implementations >>> for >>> all methods not specified in the class, for each superclass in the >>> hierarchy (except Object) and implemented interface. >>> >>> - Static methods, private methods, final methods, constructors and >>> methods from class Object should never be generated. >>> - If some superclass (except Object) has already overridden some >>> Object class methods, then do NOT generate an empty overridden >>> method >>> (to reuse current behavior.) (for example, if some superclass >>> already >>> override toString(), equals() or hashCode().) >>> >>> - OPTIONAL: add a parameter to the @OverrideAll annotation to >>> indicate >>> if @Deprecated methods should not be implemented. >>> >>> Trivial implementation for generated methods: >>> >>> - Methods returning void will have an empty body. (OPTIONAL: add a >>> parameter to the @OverrideAll annotation to indicate that it should >>> throw UnsupportedOperationException instead) >>> - Methods returning a primitive type will have a body returning the >>> same default value that would have for uninitialized instance >>> variables. (JLS section 4.12.5.) >>> - Methods returning a reference type will "return null;". (JLS >>> section >>> 4.12.5.) >>> - The method will never return a covariant return type (because in >>> case of implementing a Null object, it should be undistinguished >>> from >>> the common case) >>> - Methods that throws checked exceptions can be modified to delete >>> the >>> throws clause. (ie. the trivial implementation should not throw >>> checked exceptions) >>> - Synchronized methods should retain that attribute. >>> >>> >>> COMPILATION: >>> >>> Compilation should proceed as usual, except that the annotation >>> processor would generate the code when it encounters an annotated >>> class. >>> >>> No changes to the class file format are needed. >>> >>> >>> TESTING >>> >>> Test cases should be done, including testing with classes >>> implementing >>> several interfaces, classes with generics, inner classes, etc. >>> >>> >>> LIBRARY SUPPORT: >>> >>> No, except creating the new annotation. >>> >>> >>> REFLECTIVE APIS: >>> >>> No changes foreseen. >>> >>> >>> OTHER CHANGES: >>> >>> Output of javadoc tool. >>> >>> >>> MIGRATION: >>> >>> Just add the annotation to class level, and erase your trivially >>> implemented overridden methods. >>> >>> >>> COMPATIBILITY >>> >>> BREAKING CHANGES: >>> All existing programs remain valid. >>> >>> EXISTING PROGRAMS: >>> The semantics of existing class files and legal source files are >>> unchanged by this feature. >>> >>> >>> REFERENCES >>> >>> EXISTING BUGS: >>> >>> None that I know about. >>> >>> URL FOR PROTOTYPE: >>> >>> None at this time. >>> >>> >> >> >> > > From reinier at zwitserloot.com Fri Apr 3 03:34:47 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Fri, 3 Apr 2009 12:34:47 +0200 Subject: PROPOSAL: Binary Literals In-Reply-To: <31379447.1238750003379.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> References: <31379447.1238750003379.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> Message-ID: <483055E7-EAC0-4FF0-9B11-2F828F90B917@zwitserloot.com> public static byte b(String in) { return Byte.parseByte(in, 2); } then: (0b11010100 & 0b01001011) ^ (0b01101010 | 0b10010100) vs: import static ByteUtils.b; (b("11010100") & b("01001011")) ^ (b("01101010") | b("10010100")) I can live with that. --Reinier Zwitserloot On Apr 3, 2009, at 11:13, Derek Foster wrote: > > > -----Original Message----- >> From: Mark Thornton >> Sent: Mar 26, 2009 4:54 AM >> To: Derek Foster >> Cc: coin-dev at openjdk.java.net >> Subject: Re: PROPOSAL: Binary Literals >> >> Derek Foster wrote: >>> You are not considering the impact of constant folding on compiler >>> optimizations. >>> >>> Not all constants are created equal. Constants whose values can be >>> determined at compile time can be inlined by the compiler, and >>> arithmetic expressions involving them can often therefore be >>> simplified at compile time. This process is known as "constant >>> folding". The resulting code need not reference the original >>> variable to get the constant at all -- it can just use the inlined >>> result of evaluating the expression. Additional compiler >>> optimizations may then be performed on the basis of these folded >>> constants. For instance, a compiler might decide to compile this >>> code: >>> >> Perhaps you missed my suggestion that the range of operations >> permitted >> in constant expressions be extended to include the bit munging >> operations (and possibly others). We could perhaps have an annotation >> that was only permitted on static methods in the java.* name space >> and >> which required the compiler to execute the method at compile time >> if its >> arguments were compile time constants. The compiler could >> alternatively >> have a private list of such methods, the annotation conveniently >> tells >> everyone else what is on the list. > > > I did miss that suggestion, actually. Though now that you've > mentioned it: > > It's not that I would mind that feature in the compiler ("that > feature" > being compile-time evaluation of common library > methods which are passed parameters known at compile time). However, > it doesn't sound terribly easy to implement. Especially when you > consider > the implications of having to do error handling on illegal function > arguments at compile time, rather than at runtime. In fact, it sounds > a whole lot more intrusive and a lot more work for the compiler team > than just being able to parse a simple binary number. > > Besides that issue, however, and besides the also (substantial!) issue > of the readability of > > (0b11010100 & 0b01001011) ^ (0b01101010 | 0b10010100) > > vs. > > (Byte.parseByte("0b11010100",2) & Byte.parseByte("0b01001011",2) ^ > (Byte.parseByte("0b01101010",2) | Byte.parseByte("0b10010100",2)) > > there is also the fact that some Java platforms simply don't HAVE a > Byte > class. For instance, consider JavaCard: > > http://java.sun.com/javacard/ > > A JavaCard, if you weren't aware, is a literally credit-card-sized > computer > running a very stripped-down JVM that is just capable enough that it > can do encryption calculations in order to ensure, for instance, that > the card is connecting to an authorized and properly authenticated > bank > machine. There's no room in a machine that small for the vast majority > of standard library classes, most of which would be useless anyway in > a computer of those capabilities. For instance, there is no support > for java.lang.String, java.lang.Integer, and so forth (since this > computer has no need to process Strings, and only needs integers > for the purpose of number-crunching math, not nullness checks). > > Programmers for JavaCard could easily use binary numbers in their > encryption algorithms. That's a use case that is easily handled by > my proposal. However, importing a library that depends on > Byte.parseInt(java.lang.String, int) isn't going to be sufficient > for them, because they have neither Byte nor String. > > When I worked on the massively parallel processor chip I described > earlier, our Java didn't have Byte or String classes either. Even > if it had had something like String, nobody probably would have > used it. Text processing is just not the kind of thing you use a > massively parallel number crunching chip to do. Also, when each > processor on the chip has around 8Kbytes of ROM to store program code, > you don't want to be wasting it on library routines, or calls > to them, that you don't really need. > > Derek > > > > > > > > >> Mark Thornton >> > > From mthornton at optrak.co.uk Fri Apr 3 03:48:37 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Fri, 03 Apr 2009 11:48:37 +0100 Subject: Annotation processors Message-ID: <49D5E985.8010408@optrak.co.uk> These have come up several times on this list. I suspect many people have only a vague idea of what they can do. Is there any good documentation or introductory material available? Mark Thornton From pdoubleya at gmail.com Fri Apr 3 04:05:38 2009 From: pdoubleya at gmail.com (Patrick Wright) Date: Fri, 3 Apr 2009 13:05:38 +0200 Subject: Annotation processors In-Reply-To: <49D5E985.8010408@optrak.co.uk> References: <49D5E985.8010408@optrak.co.uk> Message-ID: <64efa1ba0904030405w4d68cec9xbee57f8a9969ec25@mail.gmail.com> Here are some links I found on searching for this yesterday http://today.java.net/pub/a/today/2008/04/10/source-code-analysis-using-java-6-compiler-apis.html http://blogs.sun.com/sundararajan/entry/javac_tree_api_-_check http://scg.unibe.ch/archive/projects/Erni08b.pdf http://java.sun.com/javase/6/docs/technotes/guides/javac/index.html http://smallwiki.unibe.ch/adriankuhn/javacompiler/ HTH Patrick From mthornton at optrak.co.uk Fri Apr 3 04:21:02 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Fri, 03 Apr 2009 12:21:02 +0100 Subject: Annotation processors In-Reply-To: <64efa1ba0904030405w4d68cec9xbee57f8a9969ec25@mail.gmail.com> References: <49D5E985.8010408@optrak.co.uk> <64efa1ba0904030405w4d68cec9xbee57f8a9969ec25@mail.gmail.com> Message-ID: <49D5F11E.9030806@optrak.co.uk> Thanks Patrick Wright wrote: > http://scg.unibe.ch/archive/projects/Erni08b.pdf > I like the section: "How to abuse JSR269 for AST rewriting". I wonder if I can use that to extend the compile time evaluation of constant expressions. Regards, Mark From belingueres at gmail.com Fri Apr 3 08:23:59 2009 From: belingueres at gmail.com (Gabriel Belingueres) Date: Fri, 3 Apr 2009 12:23:59 -0300 Subject: PROPOSAL: @OverrideAll annotation In-Reply-To: <61773C12-3611-452A-B0A1-8B873F0E47E1@zwitserloot.com> References: <17542308.1238746196681.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> <61773C12-3611-452A-B0A1-8B873F0E47E1@zwitserloot.com> Message-ID: Hi, Thanks for taking the time for reading this. @Derek: My current approach for implementing this feature is to use the reflection API to get the Methods and generate from there the source file. (I'm not very experienced with the annotation API so this may not be the shortest path to do it, but for a first try I think it's OK.) However my mayor problem here is how to generate the concrete class, for example let's say we have: class A { public void method1() {}; public void method2() {}; } @OverrideAll class B extends A { public void method1() { ... } } the easiest way I'm thinking I can generate the code is to create a superclass class A_overrideAll which extends A with all methods overridden, and then make B extends A_overrideAll. However, AFAIK I can't modify the original source file (where class B is declared) so how can now make it a subclass of A_overrideAll? I choose an annotation instead of introducing a new keyword because it was less intrusive than the other, that is, with a new keyword I would need to modify the JLS, which is unnecessary because no language rule changes. If further analysis reveal that a new keyword would be better than an annotation, then it's fine with me. @rssh: no compile time error should be thrown, instead, at runtime the execution of a method should have a default behavior. In terms of the language, the most basic behavior is do nothing/return default values, but in general, the idea was to create a Null Object, meaning that the client code could call methods that do nothing instead of checking for != null. (Hopefully you could avoid some NPEs with this idiom.) Other idiom that apply for @OverrideAll are the AWT/Swing Listeners and Adapters. There are lots of XXXListener interfaces with an associated XXXAdapter abstract class that are used with a (sometimes anonymous) class just to listen to particular events offered in the listener interface. With the @OverrideAll annotation, you could avoid the declaration of the abstract adapter class. Regards, Gabriel 2009/4/3 Reinier Zwitserloot : > What Derek said - this is not a good idea. > > rssh: The proposal specifically states that each non-overridden method > is to be generated with an empty body, or if that isn't possible due > to a return type, the default return for that type (0/false/0.0/'\0'/ > null). > > > > ?--Reinier Zwitserloot > > > > On Apr 3, 2009, at 10:09, Derek Foster wrote: > >> My major problem with this proposal is that it doesn't seem to be >> straightforward to generate the bodies of methods that have to >> return something. Particularly for code such as implementations of >> the Visitor pattern. >> >> Having un-overridden methods simply return null or zero is often not >> the right thing to do. >> >> It's OK for generating methods that just take parameters, I suppose. >> >> Still, having annotations generate code or otherwise affect the >> operation of a program is apparently a no-no per Sun's rules. If >> something like this is going to happen, I think it needs a new >> keyword or something rather than using an annotation. >> >> (Although, personally, I don't think it would be such a bad thing if >> code generation via annotation existed, but were limited only to >> certain annotations in a specific package duly designated by the >> language implementors. Annotations have one nice quality that other >> ways of extending the language don't: You can create new "keywords" >> at will with no risk of breaking someone's perfectly-working code. >> If they don't import the annotation, they won't need to be impacted >> by it. I sort of wish there was an alternative to annotations (@@Foo >> instead of @Foo?) which was explicitly for the purpose of telling >> the compiler to generate boilerplate code of various types. >> Decorators in Python sort of serve this purpose, for instance.) >> >> Derek >> >> -----Original Message----- >>> From: rssh at gradsoft.com.ua >>> Sent: Mar 31, 2009 10:02 AM >>> To: Gabriel Belingueres >>> Cc: coin-dev >>> Subject: Re: PROPOSAL: @OverrideAll annotation >>> >>>> Hi, >>>> >>>> I've written a new feature that might be comfortable to use for >>>> someone. All input is welcomed. >>>> >>> >>> It-is possible to do near same with annotation API (create a >>> superclass >>> which will override all) >>> >>> But -- sometime we really need to say, that all methods 'mus be' >>> overriden. ?(For example - when implementing Proxy pattern). >>> In such case class-level annotation '@OverrideAll' ?which tell >>> compiler >>> to check, that all methods must be overriden -- brilliant idea. >>> >>> >>> >>> >>> >>>> Regards, >>>> Gabriel >>>> >>>> PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 >>>> >>>> AUTHOR(S): Gabriel Belingueres >>>> >>>> OVERVIEW >>>> >>>> Add an @OverrideAll annotation to allow a class to override all >>>> inherited methods with a trivial implementation. The resulting class >>>> then could be used as the basis for a Null Object pattern (or even a >>>> basic Mock object.) >>>> >>>> >>>> FEATURE SUMMARY: >>>> >>>> The proposed @OverrideAll annotation will allow the class to >>>> override >>>> all methods (from its superclasses and implemented interfaces) >>>> with a >>>> trivial body, but the defined class can choose to implement specific >>>> methods, replacing those that would be produced automatically by the >>>> annotation. >>>> >>>> >>>> MAJOR ADVANTAGE: >>>> >>>> Less coding for implementing Null Objects, or simple tests. >>>> >>>> >>>> MAJOR BENEFIT: >>>> >>>> Let the compiler implement all uninteresting, non relevant >>>> behavior by >>>> automatically providing with a trivial implementation of the >>>> inherited >>>> methods. >>>> >>>> >>>> MAJOR DISADVANTAGE: >>>> >>>> Might be a cause of NullPointerException if not used judiciously. >>>> >>>> >>>> ALTERNATIVES: >>>> >>>> Implement all uninteresting methods by yourself by providing >>>> yourself >>>> a trivial implementation (though actually popular IDEs can do this >>>> automatically for you already.) >>>> >>>> EXAMPLES >>>> >>>> Given: >>>> >>>> class B {} >>>> >>>> public class A implements I1, I2 { >>>> >>>> ?public static final int VAR = 1; >>>> >>>> ?private B b; >>>> >>>> ?public static Integer getSome() { >>>> ? ?return VAR; >>>> ?} >>>> >>>> ?public A() { >>>> ?} >>>> >>>> ?public A(B b) { >>>> ? ?this.b=b; >>>> ?} >>>> >>>> ?public B getB() { >>>> ? ?return b; >>>> ?} >>>> >>>> ?public void setB(B b) { >>>> ? ?this.b=b; >>>> ?} >>>> >>>> ?protected void doProtected() { ... } >>>> >>>> ?private void doPrivate() { ... } >>>> >>>> ?A someNewA() { ... } >>>> >>>> ?public synchronized void someSynchronized() { >>>> ?} >>>> >>>> } >>>> >>>> then: >>>> >>>> @OverrideAll >>>> public class NullA extends A { >>>> } >>>> >>>> is equivalent to declare: >>>> >>>> public class NullA extends A { >>>> >>>> ?public NullA() {} >>>> >>>> ?public NullA(B b) { >>>> ? ?super(b); >>>> ?} >>>> >>>> ?public B getB() { >>>> ? ?return null; >>>> ?} >>>> >>>> ?public void setB(B b) { >>>> ?} >>>> >>>> ?protected void doProtected() { >>>> ? // empty >>>> ?} >>>> >>>> ?A someNewA() { >>>> ? return null; >>>> ?} >>>> >>>> ?public synchronized void someSynchronized() { >>>> ? ?// empty >>>> ?} >>>> >>>> } >>>> >>>> You may not want the default trivial implementation in some methods, >>>> then you override them as usual: >>>> >>>> @OverrideAll >>>> public class NullA extends A { >>>> >>>> ?@Override >>>> ?public B getB() { >>>> ? ?return new B(); >>>> ?} >>>> >>>> ?@Override >>>> ?public synchronized void someSynchronized() { >>>> ? ?System.out.println("overridden"); >>>> ?} >>>> >>>> } >>>> >>>> EXAMPLE 2 >>>> >>>> Implement a trivial Collection interface just to test that adding >>>> elements will increase the collection size: >>>> >>>> Currently: >>>> >>>> public class SomeCollection implements Collection { >>>> >>>> ?private int counter; >>>> >>>> ?@Override >>>> ?public boolean add(E arg0) { >>>> ? ?counter++; >>>> ? ?return true; >>>> ?} >>>> >>>> ?@Override >>>> ?public boolean addAll(Collection c) { >>>> ? ?counter += c.size(); >>>> ? ?return true; >>>> ?} >>>> >>>> ?@Override >>>> ?public void clear() { >>>> ?} >>>> >>>> ?@Override >>>> ?public boolean contains(Object arg0) { >>>> ? ?return false; >>>> ?} >>>> >>>> ?@Override >>>> ?public boolean containsAll(Collection arg0) { >>>> ? ?return false; >>>> ?} >>>> >>>> ?@Override >>>> ?public boolean isEmpty() { >>>> ? ?return false; >>>> ?} >>>> >>>> ?@Override >>>> ?public Iterator iterator() { >>>> ? ?return null; >>>> ?} >>>> >>>> ?@Override >>>> ?public boolean remove(Object arg0) { >>>> ? ?return false; >>>> ?} >>>> >>>> ?@Override >>>> ?public boolean removeAll(Collection arg0) { >>>> ? ?return false; >>>> ?} >>>> >>>> ?@Override >>>> ?public boolean retainAll(Collection arg0) { >>>> ? ?return false; >>>> ?} >>>> >>>> ?@Override >>>> ?public int size() { >>>> ? ?return counter; >>>> ?} >>>> >>>> ?@Override >>>> ?public Object[] toArray() { >>>> ? ?return null; >>>> ?} >>>> >>>> ?@Override >>>> ?public T[] toArray(T[] arg0) { >>>> ? ?return null; >>>> ?} >>>> >>>> } >>>> >>>> With the annotation: >>>> >>>> @OverrideAll >>>> public class SomeCollection implements Collection { >>>> >>>> ?private int counter; >>>> >>>> ?@Override >>>> ?public boolean add(E arg0) { >>>> ? ?counter++; >>>> ? ?return true; >>>> ?} >>>> >>>> ?@Override >>>> ?public boolean addAll(Collection c) { >>>> ? ?counter += c.size(); >>>> ? ?return true; >>>> ?} >>>> >>>> >>>> ?@Override >>>> ?public int size() { >>>> ? ?return counter; >>>> ?} >>>> >>>> } >>>> >>>> >>>> DETAILS >>>> >>>> >>>> SPECIFICATION: >>>> >>>> A preliminary specification follows: >>>> >>>> As this feature is proposed as an annotation for code generation, no >>>> changes to the current JLSv3 are needed. >>>> >>>> The annotation will generate "trivial" overridden implementations >>>> for >>>> all methods not specified in the class, for each superclass in the >>>> hierarchy (except Object) and implemented interface. >>>> >>>> - Static methods, private methods, final methods, constructors and >>>> methods from class Object should never be generated. >>>> - If some superclass (except Object) has already overridden some >>>> Object class methods, then do NOT generate an empty overridden >>>> method >>>> (to reuse current behavior.) (for example, if some superclass >>>> already >>>> override toString(), equals() or hashCode().) >>>> >>>> - OPTIONAL: add a parameter to the @OverrideAll annotation to >>>> indicate >>>> if @Deprecated methods should not be implemented. >>>> >>>> Trivial implementation for generated methods: >>>> >>>> - Methods returning void will have an empty body. (OPTIONAL: add a >>>> parameter to the @OverrideAll annotation to indicate that it should >>>> throw UnsupportedOperationException instead) >>>> - Methods returning a primitive type will have a body returning the >>>> same default value that would have for uninitialized instance >>>> variables. (JLS section 4.12.5.) >>>> - Methods returning a reference type will "return null;". (JLS >>>> section >>>> 4.12.5.) >>>> - The method will never return a covariant return type (because in >>>> case of implementing a Null object, it should be undistinguished >>>> from >>>> the common case) >>>> - Methods that throws checked exceptions can be modified to delete >>>> the >>>> throws clause. (ie. the trivial implementation should not throw >>>> checked exceptions) >>>> - Synchronized methods should retain that attribute. >>>> >>>> >>>> COMPILATION: >>>> >>>> Compilation should proceed as usual, except that the annotation >>>> processor would generate the code when it encounters an annotated >>>> class. >>>> >>>> No changes to the class file format are needed. >>>> >>>> >>>> TESTING >>>> >>>> Test cases should be done, including testing with classes >>>> implementing >>>> several interfaces, classes with generics, inner classes, etc. >>>> >>>> >>>> LIBRARY SUPPORT: >>>> >>>> No, except creating the new annotation. >>>> >>>> >>>> REFLECTIVE APIS: >>>> >>>> No changes foreseen. >>>> >>>> >>>> OTHER CHANGES: >>>> >>>> Output of javadoc tool. >>>> >>>> >>>> MIGRATION: >>>> >>>> Just add the annotation to class level, and erase your trivially >>>> implemented overridden methods. >>>> >>>> >>>> COMPATIBILITY >>>> >>>> BREAKING CHANGES: >>>> All existing programs remain valid. >>>> >>>> EXISTING PROGRAMS: >>>> The semantics of existing class files and legal source files are >>>> unchanged by this feature. >>>> >>>> >>>> REFERENCES >>>> >>>> EXISTING BUGS: >>>> >>>> None that I know about. >>>> >>>> URL FOR PROTOTYPE: >>>> >>>> None at this time. >>>> >>>> >>> >>> >>> >> >> > > > From belingueres at gmail.com Fri Apr 3 08:58:18 2009 From: belingueres at gmail.com (Gabriel Belingueres) Date: Fri, 3 Apr 2009 12:58:18 -0300 Subject: PROPOSAL: 'final' without explicit type (update) In-Reply-To: <31420118.1238747201155.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> References: <31420118.1238747201155.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> Message-ID: I agree that must be valid just for final, local variables. Regards, Gabriel 2009/4/3 Derek Foster : > > > -----Original Message----- >>From: Reinier Zwitserloot >>Sent: Mar 31, 2009 11:28 AM >>To: Tim Lebedkov >>Cc: coin-dev at openjdk.java.net >>Subject: Re: PROPOSAL: 'final' without explicit type (update) >> >>Tim: >> >>This isn't the first time I've read about inferring types, and this >>isn't the first time I've seen 'final' used for it. >> >>It's -not- just to avoid a new keyword. It's quite specifically >>because auto-typing should only be done for final variables. The >>problem is this: >> ... > > This message had a good explanation of why final is preferred, and an explanation of why not using an interface type is probably OK in this limited circumstance. Probably the best explanations of these issues I've seen. (I've just snipped it away. Read the Reiner's original post for the original description.) > >>FWIW, I'm -strongly- in favour of implicit typing for final local >>method variables, and opposed to extending this for non-finals, not >>just because its hard to come up with a syntax for it, due to there >>being no readily available keywords or operators to do it with. := >>comes to mind, but that's about it. > > I agree with this, on both points. (I'm perhaps not as "strongly" in favor as Reiner, but I do think that having implicit typing for local variables would be a net positive in readability, despite the lack of an explicit type in the code. I think that implicit typing would probably be a mistake for fields, however, even if they're final. (They're accessed in too many places.) With code that uses generics a lot, the overhead of having to mention long type names multiple times starts to become large. Improved type inference would help a lot. > > Derek > > > From Joe.Darcy at Sun.COM Fri Apr 3 10:07:37 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Fri, 03 Apr 2009 10:07:37 -0700 Subject: Annotation processors In-Reply-To: <49D5E985.8010408@optrak.co.uk> References: <49D5E985.8010408@optrak.co.uk> Message-ID: <49D64259.1020801@sun.com> Mark Thornton wrote: > These have come up several times on this list. I suspect many people > have only a vague idea of what they can do. Is there any good > documentation or introductory material available? > > Mark Thornton > > The annotation processing in javac provides immutable data structures modeling the types in question. However, much of the power of providing mutable source files can be had by either using an annotation processor to generate subclasses of a class or the *superclass* of a class. Those capabilities are mandated for JSR 269 annotation processing frameworks, as implemented in javac and Eclipse. For example, @MakeMeAPropertyInMySuperclass annotations could be used to automatically generate at build time the desired property structure that could be inherited. It is technically possible (a small matter of programming ;-) to run @MakeMeAPropertyInMySuperclass(name="foo",type=Type.class) class Foo extends ToBeGenerated {} into something like class ToBeGenerated { private Type foo; Type getFoo() { return foo; } Type setFoo(Type type) { this.type = type; return this.type; } } Bruce Chapman has written interesting annotation processors as part of his rapt and hickory projects: https://rapt.dev.java.net/ https://hickory.dev.java.net/ -Joe From howard.lovatt at iee.org Sat Apr 4 21:59:07 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Sun, 5 Apr 2009 14:59:07 +1000 Subject: Opportunity Cost and Proposal Selection Message-ID: <3dd3f56a0904042159r741706fdq9e081f4043850950@mail.gmail.com> Hi All, I would like to thanks Sun and particularly Joe for running this process, despite the fact that I think many of my favourites will not make 'the list' :( I think it is a very health process. -- Howard. From markmahieu at googlemail.com Sun Apr 5 04:40:55 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Sun, 5 Apr 2009 12:40:55 +0100 Subject: Proposal: Elvis and Other Null-Safe Operators In-Reply-To: <49C27E68.7020709@gmail.com> References: <49C201C5.3090200@gmail.com> <15e8b9d20903190713i67595fe1hac45db43e4dc522c@mail.gmail.com> <49C27E68.7020709@gmail.com> Message-ID: <84A9B0E6-9454-4A74-AFF1-BE92D6694D05@googlemail.com> Hi Stephen, Revisiting an email from a couple of weeks ago... On 19 Mar 2009, at 17:18, Stephen Colebourne wrote: > Neal Gafter wrote: >> On Thu, Mar 19, 2009 at 1:26 AM, Jacek Kolodziejczyk >> wrote: >> >>> In my opinion the most obtrusive part in the current state of >>> proposals >>> is assumption that the invocation on null object should always >>> return null. >>> If I understand it correctly the following would break at runtime, >>> because null cannot be assigned to boolean: >>> >>> List list = null; >>> boolean b = list?.isEmpty(); >>> >> >> That would be a compile-time error because of the incompatibility >> between null and boolean. >> > The intention is that you can write a combination to handle this with > the submitted Coin proposal: > > List list = null; > boolean b = list?.isEmpty() ?: true; > > Stephen > I don't understand how that combination is supposed to work, given this part of the proposal: "A null-safe method invocation expression e1?.name(args) ... the type of the result is the same as the type of e1.name(args). It is an error if this is not a reference type." Doesn't that mean that the compiler should reject the expression 'list?.isEmpty()' ? Mark From neal at gafter.com Sun Apr 5 07:11:33 2009 From: neal at gafter.com (Neal Gafter) Date: Sun, 5 Apr 2009 07:11:33 -0700 Subject: Proposal: Elvis and Other Null-Safe Operators In-Reply-To: <84A9B0E6-9454-4A74-AFF1-BE92D6694D05@googlemail.com> References: <49C201C5.3090200@gmail.com> <15e8b9d20903190713i67595fe1hac45db43e4dc522c@mail.gmail.com> <49C27E68.7020709@gmail.com> <84A9B0E6-9454-4A74-AFF1-BE92D6694D05@googlemail.com> Message-ID: <15e8b9d20904050711o124b388etca7847f8a456a45c@mail.gmail.com> On Sun, Apr 5, 2009 at 4:40 AM, Mark Mahieu wrote: >> List list = null; >> boolean b = list?.isEmpty() ?: true; >> >> Stephen >> > > I don't understand how that combination is supposed to work, given > this part of the proposal: > > "A null-safe method invocation expression e1?.name(args) ... the type > of the result is the same as the type of e1.name(args). ?It is an > error if this is not a reference type." > > Doesn't that mean that the compiler should reject the expression > 'list?.isEmpty()' ? Given the spec as written, yes. However, it could be changed so that the result is the same as the result of the rewriting in the "compilation" section of the spec. In that case its result would be Boolean. However, that is likely to result in more runtime null errors, not fewer, if people do things like if (list?.isEmpty()) ... -Neal From markmahieu at googlemail.com Sun Apr 5 10:19:52 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Sun, 5 Apr 2009 18:19:52 +0100 Subject: Proposal: Elvis and Other Null-Safe Operators In-Reply-To: <15e8b9d20904050711o124b388etca7847f8a456a45c@mail.gmail.com> References: <49C201C5.3090200@gmail.com> <15e8b9d20903190713i67595fe1hac45db43e4dc522c@mail.gmail.com> <49C27E68.7020709@gmail.com> <84A9B0E6-9454-4A74-AFF1-BE92D6694D05@googlemail.com> <15e8b9d20904050711o124b388etca7847f8a456a45c@mail.gmail.com> Message-ID: 2009/4/5 Neal Gafter > On Sun, Apr 5, 2009 at 4:40 AM, Mark Mahieu > wrote: > > Doesn't that mean that the compiler should reject the expression > > 'list?.isEmpty()' ? > > Given the spec as written, yes. However, it could be changed so that > the result is the same as the result of the rewriting in the > "compilation" section of the spec. In that case its result would be > Boolean. However, that is likely to result in more runtime null > errors, not fewer, if people do things like > > if (list?.isEmpty()) ... > > -Neal > Thanks, Neal. I've started putting a rough implementation of this proposal together, just to aid my own understanding. Are you or Stephen (or anyone else) intending to produce a prototype, or would it be useful if I polish up what I've been doing? Mark From neal at gafter.com Sun Apr 5 10:52:55 2009 From: neal at gafter.com (Neal Gafter) Date: Sun, 5 Apr 2009 10:52:55 -0700 Subject: Proposal: Elvis and Other Null-Safe Operators In-Reply-To: References: <49C201C5.3090200@gmail.com> <15e8b9d20903190713i67595fe1hac45db43e4dc522c@mail.gmail.com> <49C27E68.7020709@gmail.com> <84A9B0E6-9454-4A74-AFF1-BE92D6694D05@googlemail.com> <15e8b9d20904050711o124b388etca7847f8a456a45c@mail.gmail.com> Message-ID: <15e8b9d20904051052q530820e5m9fcb3441c8cb59d3@mail.gmail.com> On Sun, Apr 5, 2009 at 10:19 AM, Mark Mahieu wrote: > I've started putting a rough implementation of this proposal together, just > to aid my own understanding. ?Are you or Stephen (or anyone else) intending > to produce a prototype, or would it be useful if I polish up what I've been > doing? I'm not planning to prototype this. From jodastephen at gmail.com Sun Apr 5 05:11:57 2009 From: jodastephen at gmail.com (Stephen Colebourne) Date: Sun, 05 Apr 2009 13:11:57 +0100 Subject: Proposal: Elvis and Other Null-Safe Operators In-Reply-To: <84A9B0E6-9454-4A74-AFF1-BE92D6694D05@googlemail.com> References: <49C201C5.3090200@gmail.com> <15e8b9d20903190713i67595fe1hac45db43e4dc522c@mail.gmail.com> <49C27E68.7020709@gmail.com> <84A9B0E6-9454-4A74-AFF1-BE92D6694D05@googlemail.com> Message-ID: <49D8A00D.7040909@gmail.com> Mark Mahieu wrote: >> >> List list = null; >> boolean b = list?.isEmpty() ?: true; >> >> Stephen >> > > I don't understand how that combination is supposed to work, given > this part of the proposal: > > "A null-safe method invocation expression e1?.name(args) ... the type > of the result is the same as the type of e1.name(args). It is an > error if this is not a reference type." > > Doesn't that mean that the compiler should reject the expression > 'list?.isEmpty()' ? I hope Neal can comment as he wrote up the details of the proposal. I did ask him about this when I first read it, and he replied that primitives were handled in the "boxedValue ?: primitive" case. At the time, I assumed that meant that the "list?.isEmpty() ?: false" was also handled, but on re-reading today, you may be right. I'd like the "list?.isEmpty() ?: false" to be handled though. Stephen From stephen at joda.org Sun Apr 5 11:07:51 2009 From: stephen at joda.org (Stephen C) Date: Sun, 05 Apr 2009 19:07:51 +0100 Subject: Proposal: Elvis and Other Null-Safe Operators In-Reply-To: References: <49C201C5.3090200@gmail.com> <15e8b9d20903190713i67595fe1hac45db43e4dc522c@mail.gmail.com> <49C27E68.7020709@gmail.com> <84A9B0E6-9454-4A74-AFF1-BE92D6694D05@googlemail.com> <15e8b9d20904050711o124b388etca7847f8a456a45c@mail.gmail.com> Message-ID: <49D8F377.4080308@joda.org> Mark Mahieu wrote: > I've started putting a rough implementation of this proposal together, > just to aid my own understanding. Are you or Stephen (or anyone else) > intending to produce a prototype, or would it be useful if I polish up > what I've been doing? I haven't got time to do so, thus it would be great if you do some polishing. Stephen From markmahieu at googlemail.com Sun Apr 5 23:05:24 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Mon, 6 Apr 2009 07:05:24 +0100 Subject: Proposal: Elvis and Other Null-Safe Operators In-Reply-To: <49D8F377.4080308@joda.org> References: <49C201C5.3090200@gmail.com> <15e8b9d20903190713i67595fe1hac45db43e4dc522c@mail.gmail.com> <49C27E68.7020709@gmail.com> <84A9B0E6-9454-4A74-AFF1-BE92D6694D05@googlemail.com> <15e8b9d20904050711o124b388etca7847f8a456a45c@mail.gmail.com> <49D8F377.4080308@joda.org> Message-ID: 2009/4/5 Stephen C > Mark Mahieu wrote: > > I've started putting a rough implementation of this proposal together, > > just to aid my own understanding. Are you or Stephen (or anyone else) > > intending to produce a prototype, or would it be useful if I polish up > > what I've been doing? > I haven't got time to do so, thus it would be great if you do some > polishing. > Stephen > OK, will do. Mark From alexandre.makarenko at free.fr Mon Apr 6 14:25:23 2009 From: alexandre.makarenko at free.fr (alex) Date: Mon, 6 Apr 2009 23:25:23 +0200 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: Message-ID: <200904062325.23836.alexandre.makarenko@free.fr> Hi Tim, a little bit late comment... what if Map> anagrams(); compiled as Map> anagrams = new HashMap>(); ? In more general way for a class C C c( constructor-args ); would be equivalent to C c = new C( constructor-args ); @lex ps: C++ trick ;-) On Saturday 28 March 2009 09:35:46 Tim Lebedkov wrote: > Type inference for variable definition/initialization using the 'auto' > keyword. > > AUTHOR(S): Tim Lebedkov > > OVERVIEW > > Provide a two sentence or shorter description of these five aspects of > the feature: > > FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. > > This proposal addresses the addition of type inference for > variable definitions to the Java programming language using the 'auto' > keyword instead of specific type name. > > For example, consider the following assignment statement: > > Map> anagrams = new HashMap>(); > > This is rather lengthy, so it can be replaced with this: > > auto anagrams = new HashMap>(); > > and anagrams is automatically typed as HashMap> > > MAJOR ADVANTAGE: What makes the proposal a favorable change? > > Generics have had a tremendously positive impact on type safety in the > Java programming language. They have made it possible to provide > static guarantees about the type of instances used by other classes, > preventing entire classes of runtime errors from occurring. However, > generics have added complexity to Java, making the code far more > verbose and occasionally difficult to read. Although solving this > problem is well outside the scope of this proposal, a limited form of > type inference would remove unnecessary redundancy from the language. > Even without generics it seems unnecessary to duplicate type names for > simple variable definitions/assignments like: > > Integer a = new Integer(1023); > > MAJOR BENEFIT: Why is the platform better if the proposal is adopted? > > Less code and no duplication has a positive impact on many things: > - faster typing/faster code changes > - easier code changing without IDE assistance > - code versioning diffs are more clear > > MAJOR DISADVANTAGE: There is always a cost. > > - it could be harder to read the code. > - auto will be a keyword and may break some old code > > ALTERNATIVES: Can the benefits and advantages be had some way without > a language change? > > no > > EXAMPLES > > SIMPLE EXAMPLE: Show the simplest possible program utilizing the new > feature. > > 1. simple assignment > > Map> a = new HashMap>(); > > becomes > > auto a = new HashMap>(); > > 2. auto in for > > List list = ... > for (auto s: list) > ... > > 3. auto for a final variable > > final ArrayList list = new ArrayList(); > > becomes > > final auto list = new ArrayList(); > > 4. class field definition > > class A { > String a = ""; > } > > becomes > > class A { > auto a = ""; > } > > ADVANCED EXAMPLE: Show advanced usage(s) of the feature. > > auto i = 5 + 3; // same as "int i = 5 + 3" > auto i = 5 + 3L; // same as "long i = 5 + 3L" > for (auto entry : (new HashMap>).entrySet()) { } > > DETAILS > > SPECIFICATION: Describe how the proposal affects the grammar, type > system, and meaning of expressions and statements in the Java > Programming Language as well as any other known impacts. > > Informally, the specification adds syntax to replace the type definition > in variable definitions with assignments by 'auto'. The type of the > variable is automatically determined. > > COMPILATION: How would the feature be compiled to class files? Show > how the simple and advanced examples would be compiled. Compilation > can be expressed as at least one of a desugaring to existing source > constructs and a translation down to bytecode. If a new bytecode is > used or the semantics of an existing bytecode are changed, describe > those changes, including how they impact verification. Also discuss > any new class file attributes that are introduced. Note that there are > many downstream tools that consume class files and that they may to be > updated to support the proposal! > > The resulting bytecode would be identical to bytecode generated by the > same code with the types inferred. > > TESTING: How can the feature be tested? > > The proposed construct can be tested by writing a number of statements > that construct instances using > inferred types. These instances can then be assigned to variables and > fields of specific types, and passed to > methods that expect specific types. These tests should compile and run > as expected: > auto set = new SortedSet(); > set.add("A"); > set.add("B"); > set.add("C"); > // verify that set contains "A", "B", "C". > > LIBRARY SUPPORT: Are any supporting libraries needed for the feature? > > No library support is required, although libraries can be rewritten to > take advantage of the new feature. > > REFLECTIVE APIS: Do any of the various and sundry reflection APIs need > to be updated? This list of reflective APIs includes but is not > limited to core reflection (java.lang.Class and java.lang.reflect.*), > javax.lang.model.*, the doclet API, and JPDA. > > No reflective APIs need to be changed. > > OTHER CHANGES: Do any other parts of the platform need be updated too? > Possibilities include but are not limited to JNI, serialization, and > output of the javadoc tool. > > No other parts of the platform need to be updated. > > MIGRATION: Sketch how a code base could be converted, manually or > automatically, to use the new feature. > > Libraries can be rewritten to take advantage of this feature, but it > is not imperative that they do so. > > COMPATIBILITY > > This change is backwards incompatible on the source code level. > > BREAKING CHANGES: Are any previously valid programs now invalid? If > so, list one. > > All programs that use auto as a name for an identifier would become > invalid. > > EXISTING PROGRAMS: How do source and class files of earlier platform > versions interact with the feature? Can any new overloadings occur? > Can any new overriding occur? > > The feature is completely transparent to the class files. Class files > do not contain > any information about the variables declared using 'auto'. > > REFERENCES > > [1] Thanks to Jeremy Manson (his proposal served as a template for this > one) > http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html > [2] Jaako Jarvi and Bjarne Stroustrup. Decltype and auto (revision 3). > Paper N1607, > JTC1-SC22/WG21, February 17 2004. Online: http://www.open-std.org/jtc1/ > sc22/wg21/docs/papers/2004/n1607.pdf; same as ANSI NCITS/J16 04-0047. > [3] James Gosling, Bill Joy, Guy Steele, and Gilad Bracha. The Java > Language Specification, 3rd Edition. > Addison Wesley, 2004. > > > EXISTING BUGS: Please include a list of any existing Sun bug ids > related to this proposal. > 6242254, 4983159, 6368076 > > URL FOR PROTOTYPE (optional): > none From mthornton at optrak.co.uk Mon Apr 6 14:31:32 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Mon, 06 Apr 2009 22:31:32 +0100 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <200904062325.23836.alexandre.makarenko@free.fr> References: <200904062325.23836.alexandre.makarenko@free.fr> Message-ID: <49DA74B4.5080304@optrak.co.uk> alex wrote: > Hi Tim, > a little bit late comment... > > what if > > Map> anagrams(); > > compiled as > > Map> anagrams = new HashMap>(); > > Why HashMap and not some other implementation of Map? That approach only works if the LHS specifies a concrete type and not an interface or abstract class. Mark Thornton From rssh at gradsoft.com.ua Mon Apr 6 17:33:12 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Tue, 7 Apr 2009 03:33:12 +0300 (EEST) Subject: scripts and results (was Helping to find the usefulness of a proposal) Message-ID: <60287e9e1530b3e1ae49976316e8dc57.squirrel@wmail.gradsoft.ua> Good day, Few days ago Stephan give idea about writing simple script, which count amount of possible-optimizations of existing code. So, I wrote few checks for some of such entries. They count low bound of number of code patterns, which can be optimized with some of coin proposal and situated on distinct source lines. I'm afraid that information, which come from count of such code patterns can give incorrect direction: when we have such patterns in code, it's means that problem is not so big and we can easy live with one. Big language problems solved (or not) in non-trivial way, when we have no common (may be ugly) workaround. For example. in Java we rare will see BigDecimal.add() because it is not easy to work with BigDecimals, instead people work with double and have troubles with floating points rounding issues (see http://www.ddj.com/java/184405721)). Yet one example - choosing another language for implementing db-intensive parts of projects. Ok, you warned; data still can be interesting: Checked patterns was: string in switch instanceof switch byte literals multi catch loop by iterator, with call remove inside loop (if you want include other checks, you can add one at etc/checkers_coin.def or ask me [but without any warranty]) Exists one proposal, which I can't find on Joe blog: is change of variable subtype inside 'if instance' statement I. e. patterns look: if (x instanceof something) { something sx = (something)x; } And proposal tell type 'x' as 'something' inside dominate if block. Are anybody remember such proposal or it's was my fantasy ? Some results: For jetty6_11: (web server) byte literal : 52 elvis : 43 instanceof switch : 8 loop with remove : 0 multi catch : 22 string in switch : 19 Files:187 For gwt-user (google ajax library) byte literal : 2 elvis : 30 instanceof switch : 6 loop with remove : 5 multi catch : 9 string in switch : 10 Files:920 For openjdk-jdk part: (system library) byte literal : 1245 elvis : 725 instanceof switch : 252 loop with remove : 61 multi catch : 349 string in switch : 380 Files:7375 If you want to play with checks - most easy way is get special modified source distributive of JavaChecker, which I published as 2.5.0p0 and run it, i.e. (assuming you on Unix console) retrive distributive: wget http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerSourceInstaller-2.5.0p0.jar run installer: java -jar JavaCheckerSourceInstaller-2.5.0p0.jar (install one from UI) cd vi build-check-external.xml, look at few last tasks at end vi check-external.properties add own task and run one, as example: ant -f build-check-external.xml check-coin-openjdk Note, that speed of JavaChecker is far from ideal: openJDK-jdk processed near 50 minutes, so be patient ;) Hope, this information can be useful, as one (and not main) of sources. Regards ! From reinier at zwitserloot.com Mon Apr 6 17:37:18 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 7 Apr 2009 02:37:18 +0200 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <49DA74B4.5080304@optrak.co.uk> References: <200904062325.23836.alexandre.makarenko@free.fr> <49DA74B4.5080304@optrak.co.uk> Message-ID: <30B1D532-AA2B-4D1E-A8AC-700D54C05CA5@zwitserloot.com> Also, > Map> anagrams(); Actually looks like a method declaration (in fact, it is indistinguishable from it!), so the syntax needs work. --Reinier Zwitserloot Like it? Tip it! http://tipit.to On Apr 6, 2009, at 23:31, Mark Thornton wrote: > alex wrote: >> Hi Tim, >> a little bit late comment... >> >> what if >> >> Map> anagrams(); >> >> compiled as >> >> Map> anagrams = new HashMap> List>(); >> >> > Why HashMap and not some other implementation of Map? That approach > only > works if the LHS specifies a concrete type and not an interface or > abstract class. > > Mark Thornton > > From brucechapman at paradise.net.nz Tue Apr 7 01:22:27 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Tue, 07 Apr 2009 20:22:27 +1200 Subject: scripts and results (was Helping to find the usefulness of a proposal) In-Reply-To: <60287e9e1530b3e1ae49976316e8dc57.squirrel@wmail.gradsoft.ua> References: <60287e9e1530b3e1ae49976316e8dc57.squirrel@wmail.gradsoft.ua> Message-ID: <49DB0D43.1050605@paradise.net.nz> Ruslan, Thanks for doing that. Bruce P.S. One answer below Ruslan Shevchenko wrote: > Good day, > > Few days ago Stephan give idea about writing simple script, which > count amount of possible-optimizations of existing code. > > - SNIP - > > Exists one proposal, which I can't find on Joe blog: is change of variable > subtype inside 'if instance' statement > I. e. patterns look: > if (x instanceof something) > { > something sx = (something)x; > } > And proposal tell type 'x' as 'something' inside dominate if block. > Are anybody remember such proposal or it's was my fantasy ? > > > > This is part of the functionality of the switch instanceof proposal, the desugaring probably has something that looks like that in it, and I mentioned it in one of my comments regarding that proposal. Bruce From tim.lebedkov at googlemail.com Tue Apr 7 09:52:29 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Tue, 7 Apr 2009 18:52:29 +0200 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <200904062325.23836.alexandre.makarenko@free.fr> References: <200904062325.23836.alexandre.makarenko@free.fr> Message-ID: Hello Alex, yes, C++ has a lot of interesting syntax. It is one of Java "parents" and very similar/compatible to Java. IMHO it is always worth a look at how something is implemented there. By the way, C++0x will have both features: "auto" and "definition=initialization". This is probably because you can write something like: auto birthday = user.getBirthday(); // no constructor call and no type name here Regards --Tim On Mon, Apr 6, 2009 at 11:25 PM, alex wrote: > Hi Tim, > a little bit late comment... > > what if > > Map> anagrams(); > > compiled as > > Map> anagrams = new HashMap>(); > > ? > > > > In more general way for a class C > > C c( constructor-args ); > > would be equivalent to > > C c = new C( constructor-args ); > > @lex > > ps: C++ trick ;-) > > > On Saturday 28 March 2009 09:35:46 Tim Lebedkov wrote: >> Type inference for variable definition/initialization using the 'auto' >> keyword. >> >> AUTHOR(S): Tim Lebedkov >> >> OVERVIEW >> >> Provide a two sentence or shorter description of these five aspects of >> the feature: >> >> FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. >> >> This proposal addresses the addition of type inference for >> variable definitions to the Java programming language using the 'auto' >> keyword instead of specific type name. >> >> For example, consider the following assignment statement: >> >> Map> anagrams = new HashMap>(); >> >> This is rather lengthy, so it can be replaced with this: >> >> auto anagrams = new HashMap>(); >> >> and anagrams is automatically typed as HashMap> >> >> MAJOR ADVANTAGE: What makes the proposal a favorable change? >> >> Generics have had a tremendously positive impact on type safety in the >> Java programming language. They ?have made it possible to provide >> static guarantees about the type of instances used by other classes, >> preventing entire classes of runtime errors from occurring. However, >> generics have added complexity to Java, making the code far more >> verbose and occasionally difficult to read. Although solving this >> problem is well outside the scope of this proposal, a limited form of >> type inference would remove unnecessary redundancy from the language. >> Even without generics it seems unnecessary to duplicate type names for >> simple variable definitions/assignments like: >> >> Integer a = new Integer(1023); >> >> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? >> >> Less code and no duplication has a positive impact on many things: >> - faster typing/faster code changes >> - easier code changing without IDE assistance >> - code versioning diffs are more clear >> >> MAJOR DISADVANTAGE: There is always a cost. >> >> - it could be harder to read the code. >> - auto will be a keyword and may break some old code >> >> ALTERNATIVES: Can the benefits and advantages be had some way without >> a language change? >> >> no >> >> EXAMPLES >> >> SIMPLE EXAMPLE: Show the simplest possible program utilizing the new >> feature. >> >> 1. simple assignment >> >> Map> a = new HashMap>(); >> >> becomes >> >> auto a = new HashMap>(); >> >> 2. auto in for >> >> List list = ... >> for (auto s: list) >> ? ? ... >> >> 3. auto for a final variable >> >> final ArrayList list = new ArrayList(); >> >> becomes >> >> final auto list = new ArrayList(); >> >> 4. class field definition >> >> class A { >> ? ? String a = ""; >> } >> >> becomes >> >> class A { >> ? ? auto a = ""; >> } >> >> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >> >> auto i = 5 + 3; ?// same as "int i = 5 + 3" >> auto i = 5 + 3L; ?// same as "long i = 5 + 3L" >> for (auto entry : (new HashMap>).entrySet()) { } >> >> DETAILS >> >> SPECIFICATION: Describe how the proposal affects the grammar, type >> system, and meaning of expressions and statements in the Java >> Programming Language as well as any other known impacts. >> >> Informally, the specification adds syntax to replace the type definition >> in variable definitions with assignments by 'auto'. The type of the >> variable is automatically determined. >> >> COMPILATION: How would the feature be compiled to class files? Show >> how the simple and advanced examples would be compiled. Compilation >> can be expressed as at least one of a desugaring to existing source >> constructs and a translation down to bytecode. If a new bytecode is >> used or the semantics of an existing bytecode are changed, describe >> those changes, including how they impact verification. Also discuss >> any new class file attributes that are introduced. Note that there are >> many downstream tools that consume class files and that they may to be >> updated to support the proposal! >> >> The resulting bytecode would be identical to bytecode generated by the >> same code with the types inferred. >> >> TESTING: How can the feature be tested? >> >> The proposed construct can be tested by writing a number of statements >> that construct instances using >> inferred types. These instances can then be assigned to variables and >> fields of specific types, and passed to >> methods that expect specific types. These tests should compile and run >> as expected: >> auto set = new SortedSet(); >> set.add("A"); >> set.add("B"); >> set.add("C"); >> // verify that set contains "A", "B", "C". >> >> LIBRARY SUPPORT: Are any supporting libraries needed for the feature? >> >> No library support is required, although libraries can be rewritten to >> take advantage of the new feature. >> >> REFLECTIVE APIS: Do any of the various and sundry reflection APIs need >> to be updated? This list of reflective APIs includes but is not >> limited to core reflection (java.lang.Class and java.lang.reflect.*), >> javax.lang.model.*, the doclet API, and JPDA. >> >> No reflective APIs need to be changed. >> >> OTHER CHANGES: Do any other parts of the platform need be updated too? >> Possibilities include but are not limited to JNI, serialization, and >> output of the javadoc tool. >> >> No other parts of the platform need to be updated. >> >> MIGRATION: Sketch how a code base could be converted, manually or >> automatically, to use the new feature. >> >> Libraries can be rewritten to take advantage of this feature, but it >> is not imperative that they do so. >> >> COMPATIBILITY >> >> This change is backwards incompatible on the source code level. >> >> BREAKING CHANGES: Are any previously valid programs now invalid? If >> so, list one. >> >> All programs that use auto as a name for an identifier would become >> invalid. >> >> EXISTING PROGRAMS: How do source and class files of earlier platform >> versions interact with the feature? Can any new overloadings occur? >> Can any new overriding occur? >> >> The feature is completely transparent to the class files. Class files >> do not contain >> any information about the variables declared using 'auto'. >> >> REFERENCES >> >> [1] Thanks to Jeremy Manson (his proposal served as a template for this >> one) >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html >> [2] Jaako Jarvi and Bjarne Stroustrup. Decltype and auto (revision 3). >> Paper N1607, >> JTC1-SC22/WG21, February 17 2004. Online: http://www.open-std.org/jtc1/ >> sc22/wg21/docs/papers/2004/n1607.pdf; same as ANSI NCITS/J16 04-0047. >> [3] James Gosling, Bill Joy, Guy Steele, and Gilad Bracha. The Java >> Language Specification, 3rd Edition. >> Addison Wesley, 2004. >> >> >> EXISTING BUGS: Please include a list of any existing Sun bug ids >> related to this proposal. >> 6242254, 4983159, 6368076 >> >> URL FOR PROTOTYPE (optional): >> none > > From alexandre.makarenko at free.fr Tue Apr 7 11:57:15 2009 From: alexandre.makarenko at free.fr (alexandre.makarenko at free.fr) Date: Tue, 7 Apr 2009 20:57:15 +0200 (CEST) Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <49DA74B4.5080304@optrak.co.uk> Message-ID: <32658616.5264011239130635849.JavaMail.root@spooler2-g27.priv.proxad.net> exactly ;-) ----- Original Message ----- From: "Mark Thornton" To: "alex" Cc: "Tim Lebedkov" , coin-dev at openjdk.java.net Sent: Monday, April 6, 2009 11:31:32 PM GMT +01:00 Amsterdam / Berlin / Bern / Rome / Stockholm / Vienna Subject: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. alex wrote: > Hi Tim, > a little bit late comment... > > what if > > Map> anagrams(); > > compiled as > > Map> anagrams = new HashMap>(); > > Why HashMap and not some other implementation of Map? That approach only works if the LHS specifies a concrete type and not an interface or abstract class. Mark Thornton From alexandre.makarenko at free.fr Tue Apr 7 12:00:49 2009 From: alexandre.makarenko at free.fr (alexandre.makarenko at free.fr) Date: Tue, 7 Apr 2009 21:00:49 +0200 (CEST) Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <30B1D532-AA2B-4D1E-A8AC-700D54C05CA5@zwitserloot.com> Message-ID: <20015364.5264851239130849035.JavaMail.root@spooler2-g27.priv.proxad.net> method ? it lacks the method body (or abstract or native modifier) alex ----- Original Message ----- From: "Reinier Zwitserloot" To: coin-dev at openjdk.java.net Sent: Tuesday, April 7, 2009 2:37:18 AM GMT +01:00 Amsterdam / Berlin / Bern / Rome / Stockholm / Vienna Subject: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. Also, > Map> anagrams(); Actually looks like a method declaration (in fact, it is indistinguishable from it!), so the syntax needs work. --Reinier Zwitserloot Like it? Tip it! http://tipit.to On Apr 6, 2009, at 23:31, Mark Thornton wrote: > alex wrote: >> Hi Tim, >> a little bit late comment... >> >> what if >> >> Map> anagrams(); >> >> compiled as >> >> Map> anagrams = new HashMap> List>(); >> >> > Why HashMap and not some other implementation of Map? That approach > only > works if the LHS specifies a concrete type and not an interface or > abstract class. > > Mark Thornton > > From alexandre.makarenko at free.fr Tue Apr 7 12:02:36 2009 From: alexandre.makarenko at free.fr (alexandre.makarenko at free.fr) Date: Tue, 7 Apr 2009 21:02:36 +0200 (CEST) Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: Message-ID: <28935064.5265151239130956325.JavaMail.root@spooler2-g27.priv.proxad.net> sounds great ! ----- Original Message ----- From: "Tim Lebedkov" To: "alex" Cc: coin-dev at openjdk.java.net Sent: Tuesday, April 7, 2009 6:52:29 PM GMT +01:00 Amsterdam / Berlin / Bern / Rome / Stockholm / Vienna Subject: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. Hello Alex, yes, C++ has a lot of interesting syntax. It is one of Java "parents" and very similar/compatible to Java. IMHO it is always worth a look at how something is implemented there. By the way, C++0x will have both features: "auto" and "definition=initialization". This is probably because you can write something like: auto birthday = user.getBirthday(); // no constructor call and no type name here Regards --Tim On Mon, Apr 6, 2009 at 11:25 PM, alex wrote: > Hi Tim, > a little bit late comment... > > what if > > Map> anagrams(); > > compiled as > > Map> anagrams = new HashMap>(); > > ? > > > > In more general way for a class C > > C c( constructor-args ); > > would be equivalent to > > C c = new C( constructor-args ); > > @lex > > ps: C++ trick ;-) > > > On Saturday 28 March 2009 09:35:46 Tim Lebedkov wrote: >> Type inference for variable definition/initialization using the 'auto' >> keyword. >> >> AUTHOR(S): Tim Lebedkov >> >> OVERVIEW >> >> Provide a two sentence or shorter description of these five aspects of >> the feature: >> >> FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. >> >> This proposal addresses the addition of type inference for >> variable definitions to the Java programming language using the 'auto' >> keyword instead of specific type name. >> >> For example, consider the following assignment statement: >> >> Map> anagrams = new HashMap>(); >> >> This is rather lengthy, so it can be replaced with this: >> >> auto anagrams = new HashMap>(); >> >> and anagrams is automatically typed as HashMap> >> >> MAJOR ADVANTAGE: What makes the proposal a favorable change? >> >> Generics have had a tremendously positive impact on type safety in the >> Java programming language. They ?have made it possible to provide >> static guarantees about the type of instances used by other classes, >> preventing entire classes of runtime errors from occurring. However, >> generics have added complexity to Java, making the code far more >> verbose and occasionally difficult to read. Although solving this >> problem is well outside the scope of this proposal, a limited form of >> type inference would remove unnecessary redundancy from the language. >> Even without generics it seems unnecessary to duplicate type names for >> simple variable definitions/assignments like: >> >> Integer a = new Integer(1023); >> >> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? >> >> Less code and no duplication has a positive impact on many things: >> - faster typing/faster code changes >> - easier code changing without IDE assistance >> - code versioning diffs are more clear >> >> MAJOR DISADVANTAGE: There is always a cost. >> >> - it could be harder to read the code. >> - auto will be a keyword and may break some old code >> >> ALTERNATIVES: Can the benefits and advantages be had some way without >> a language change? >> >> no >> >> EXAMPLES >> >> SIMPLE EXAMPLE: Show the simplest possible program utilizing the new >> feature. >> >> 1. simple assignment >> >> Map> a = new HashMap>(); >> >> becomes >> >> auto a = new HashMap>(); >> >> 2. auto in for >> >> List list = ... >> for (auto s: list) >> ? ? ... >> >> 3. auto for a final variable >> >> final ArrayList list = new ArrayList(); >> >> becomes >> >> final auto list = new ArrayList(); >> >> 4. class field definition >> >> class A { >> ? ? String a = ""; >> } >> >> becomes >> >> class A { >> ? ? auto a = ""; >> } >> >> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >> >> auto i = 5 + 3; ?// same as "int i = 5 + 3" >> auto i = 5 + 3L; ?// same as "long i = 5 + 3L" >> for (auto entry : (new HashMap>).entrySet()) { } >> >> DETAILS >> >> SPECIFICATION: Describe how the proposal affects the grammar, type >> system, and meaning of expressions and statements in the Java >> Programming Language as well as any other known impacts. >> >> Informally, the specification adds syntax to replace the type definition >> in variable definitions with assignments by 'auto'. The type of the >> variable is automatically determined. >> >> COMPILATION: How would the feature be compiled to class files? Show >> how the simple and advanced examples would be compiled. Compilation >> can be expressed as at least one of a desugaring to existing source >> constructs and a translation down to bytecode. If a new bytecode is >> used or the semantics of an existing bytecode are changed, describe >> those changes, including how they impact verification. Also discuss >> any new class file attributes that are introduced. Note that there are >> many downstream tools that consume class files and that they may to be >> updated to support the proposal! >> >> The resulting bytecode would be identical to bytecode generated by the >> same code with the types inferred. >> >> TESTING: How can the feature be tested? >> >> The proposed construct can be tested by writing a number of statements >> that construct instances using >> inferred types. These instances can then be assigned to variables and >> fields of specific types, and passed to >> methods that expect specific types. These tests should compile and run >> as expected: >> auto set = new SortedSet(); >> set.add("A"); >> set.add("B"); >> set.add("C"); >> // verify that set contains "A", "B", "C". >> >> LIBRARY SUPPORT: Are any supporting libraries needed for the feature? >> >> No library support is required, although libraries can be rewritten to >> take advantage of the new feature. >> >> REFLECTIVE APIS: Do any of the various and sundry reflection APIs need >> to be updated? This list of reflective APIs includes but is not >> limited to core reflection (java.lang.Class and java.lang.reflect.*), >> javax.lang.model.*, the doclet API, and JPDA. >> >> No reflective APIs need to be changed. >> >> OTHER CHANGES: Do any other parts of the platform need be updated too? >> Possibilities include but are not limited to JNI, serialization, and >> output of the javadoc tool. >> >> No other parts of the platform need to be updated. >> >> MIGRATION: Sketch how a code base could be converted, manually or >> automatically, to use the new feature. >> >> Libraries can be rewritten to take advantage of this feature, but it >> is not imperative that they do so. >> >> COMPATIBILITY >> >> This change is backwards incompatible on the source code level. >> >> BREAKING CHANGES: Are any previously valid programs now invalid? If >> so, list one. >> >> All programs that use auto as a name for an identifier would become >> invalid. >> >> EXISTING PROGRAMS: How do source and class files of earlier platform >> versions interact with the feature? Can any new overloadings occur? >> Can any new overriding occur? >> >> The feature is completely transparent to the class files. Class files >> do not contain >> any information about the variables declared using 'auto'. >> >> REFERENCES >> >> [1] Thanks to Jeremy Manson (his proposal served as a template for this >> one) >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html >> [2] Jaako Jarvi and Bjarne Stroustrup. Decltype and auto (revision 3). >> Paper N1607, >> JTC1-SC22/WG21, February 17 2004. Online: http://www.open-std.org/jtc1/ >> sc22/wg21/docs/papers/2004/n1607.pdf; same as ANSI NCITS/J16 04-0047. >> [3] James Gosling, Bill Joy, Guy Steele, and Gilad Bracha. The Java >> Language Specification, 3rd Edition. >> Addison Wesley, 2004. >> >> >> EXISTING BUGS: Please include a list of any existing Sun bug ids >> related to this proposal. >> 6242254, 4983159, 6368076 >> >> URL FOR PROTOTYPE (optional): >> none > > From reinier at zwitserloot.com Tue Apr 7 13:45:26 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 7 Apr 2009 22:45:26 +0200 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <20015364.5264851239130849035.JavaMail.root@spooler2-g27.priv.proxad.net> References: <20015364.5264851239130849035.JavaMail.root@spooler2-g27.priv.proxad.net> Message-ID: <514D5836-B9FA-438C-AD05-04E9B6C916AF@zwitserloot.com> Yes, so? The parser cannot distinguish between the two, so the only solution would be to amend the semantic translation of parser tokens as such: Any method declaration that is abstract but lacks the abstract or native modifier is actually a field declaration with an auto- initialization scheme. I'm extremely prejudiced against such hackery at the parser level. What if later we want to give the 'abstract' keyword meaning when it is used on fields? All existing tools would also have to do some potentially serious rewriting and refactoring in order to accomodate such a change. --Reinier Zwitserloot Like it? Tip it! http://tipit.to On Apr 7, 2009, at 21:00, alexandre.makarenko at free.fr wrote: > method ? > > it lacks the method body (or abstract or native modifier) > > alex > > > ----- Original Message ----- > From: "Reinier Zwitserloot" > To: coin-dev at openjdk.java.net > Sent: Tuesday, April 7, 2009 2:37:18 AM GMT +01:00 Amsterdam / > Berlin / Bern / Rome / Stockholm / Vienna > Subject: Re: Proposal: Type inference for variable definition/ > initialization using the 'auto' keyword. > > Also, > >> Map> anagrams(); > > Actually looks like a method declaration (in fact, it is > indistinguishable from it!), so the syntax needs work. > > --Reinier Zwitserloot > Like it? Tip it! > http://tipit.to > > > > On Apr 6, 2009, at 23:31, Mark Thornton wrote: > >> alex wrote: >>> Hi Tim, >>> a little bit late comment... >>> >>> what if >>> >>> Map> anagrams(); >>> >>> compiled as >>> >>> Map> anagrams = new HashMap>> List>(); >>> >>> >> Why HashMap and not some other implementation of Map? That approach >> only >> works if the LHS specifies a concrete type and not an interface or >> abstract class. >> >> Mark Thornton >> >> > > From markmahieu at googlemail.com Thu Apr 9 12:25:47 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Thu, 9 Apr 2009 20:25:47 +0100 Subject: Prototype: Elvis and Other Null-Safe Operators Message-ID: <8CD6752E-879D-41BA-BB11-D5AE9F35C3F9@googlemail.com> I've made available a prototype of Stephen Colebourne's Elvis proposal (based on Neal Gafter's spec), if anyone who wants to play around with it: http://slm888.com/javac/elvis.html The usual caveats apply : expect bugs, misinterpretations of the proposal etc. I'll be happy to look into any bug reports, especially if they're accompanied by a simple test case ;) Mark From Joe.Darcy at Sun.COM Thu Apr 9 14:41:12 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 09 Apr 2009 14:41:12 -0700 Subject: Prototype: Elvis and Other Null-Safe Operators In-Reply-To: <8CD6752E-879D-41BA-BB11-D5AE9F35C3F9@googlemail.com> References: <8CD6752E-879D-41BA-BB11-D5AE9F35C3F9@googlemail.com> Message-ID: <49DE6B78.2040900@sun.com> Thanks for sending in the prototype! Which javac was the starting point? -Joe On 04/09/09 12:25 PM, Mark Mahieu wrote: > I've made available a prototype of Stephen Colebourne's Elvis > proposal (based on Neal Gafter's spec), if anyone who wants to play > around with it: > > http://slm888.com/javac/elvis.html > > The usual caveats apply : expect bugs, misinterpretations of the > proposal etc. I'll be happy to look into any bug reports, especially > if they're accompanied by a simple test case ;) > > Mark > > From markmahieu at googlemail.com Thu Apr 9 14:50:04 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Thu, 9 Apr 2009 22:50:04 +0100 Subject: Prototype: Elvis and Other Null-Safe Operators In-Reply-To: <49DE6B78.2040900@sun.com> References: <8CD6752E-879D-41BA-BB11-D5AE9F35C3F9@googlemail.com> <49DE6B78.2040900@sun.com> Message-ID: Hi Joe, The starting point was a clone of the JDK 7 "tl" forest, as of a few days ago. Mark 2009/4/9 Joe Darcy > Thanks for sending in the prototype! > > Which javac was the starting point? > > -Joe > > > On 04/09/09 12:25 PM, Mark Mahieu wrote: > >> I've made available a prototype of Stephen Colebourne's Elvis proposal >> (based on Neal Gafter's spec), if anyone who wants to play around with it: >> >> http://slm888.com/javac/elvis.html >> >> The usual caveats apply : expect bugs, misinterpretations of the proposal >> etc. I'll be happy to look into any bug reports, especially if they're >> accompanied by a simple test case ;) >> >> Mark >> >> >> > > From markmahieu at googlemail.com Mon Apr 13 05:01:53 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Mon, 13 Apr 2009 13:01:53 +0100 Subject: Some notes on Elvis and Other Null-Safe Operators Message-ID: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> Below are a few observations I compiled while building and testing the prototype for Elvis and friends, in case they're of interest. They are in note form and fairly random order, so please shout if anything isn't clear. Mark -------- Elvis operator can be approximated as a library method: static T elvis(T t1, T t2) { return t1 != null ? t1 : t2; } In a core-libs round table recording (at http://mail.openjdk.java.net/ pipermail/core-libs-dev/2009-April/001406.html) the possibility of adding core library methods for common null-handling tasks is mentioned, such as throwing a standard exception if a supplied argument is null (presumably similar to methods in com.google.common.base.Preconditions). Is it reasonable to implement the Elvis operator as a language change but other null-handling facilities as library changes? Cannot use null-safe method invocation as a statement: stringBuilder?.append(?some text?); // compiler error which is legal in Groovy and Fan, even for methods with void (or Void) result, eg. given: Map map = ... some legal Groovy code: map?.get(someKey)?.run(); and the equivalent with this proposal: Runnable r = map?.get(someKey); if (r != null) r.run(); However, this is accepted: map?.get(someKey).run(); yet is almost certainly an error. Should there at least be a warning in this case? Groovy will also allow the following: someObject?.someField = someValue which does nothing at runtime if someObject is null. Fan and this proposal both reject it. As discussed on coin-dev, this isn't legal as containsKey() returns a primitive type: if (!map?.containsKey(key) ?: false) ... // compiler error Would it be clear to someone reading the code that these two statements are equivalent? if (map?.get(key) == null) ... if (map == null || map.get(key) == null) ... Given: 101: Map map = .. 102: Bar bar = map?.get(someFoo); 103: ... 204: bar.execute(); where the programmer has forgotten to protect the bar.execute() call (or was unaware of the need, perhaps in a different method), the NPE will point at line 204, even if the root cause was 'map' being null. Without use of ?. It would point at line 102 or 204 depending on which variable was null. Groovy has supported Elvis since v1.5 (Dec 2007), other operators for longer. Few Google Code Search results for the former, plenty for the latter (but a large percentage cannot be adapted to use equivalents from this proposal because the method call results in a primitive type, or is used as a statement). Fan has only had Elvis etc since a July 2008 build (1.0.29). C# has had Elvis-equivalent '??' operator since v2.0. From Chris.Allen at nationalcity.com Mon Apr 13 09:26:18 2009 From: Chris.Allen at nationalcity.com (Allen, Chris) Date: Mon, 13 Apr 2009 12:26:18 -0400 Subject: Automatic Resource Management Message-ID: <7108D662C5ED344CBAD8CAFEEC94244115F59488@ohclemsx1023.corp.ntl-city.net> I've looked at Automatic Resource Management proposal, and written this email and then sat on it for several days, and it seems that the current proposal, adding a Disposable interface, is arbitrarily restrictive and that by using an attribute combined with a signature matching we could get better bang for our buck. We already use annotations to describe classes such as persistable or deprecated, why not as a resource? I've read the objections on this list to using an annotation, and the interface proposal does list common resources such as Streams and SQL constructs, but while the interface would probably be the preferred way to add this if we were designing the language from scratch, we already have a huge collection of code out there where a typical resource pattern is already used - but where close() is not the disposal method. People have pointed out locks for instance, but were told that locks were beyond the scope of this small change. Why? We're looking to make a small change to Java that will make source code easier to read, write and maintain while making the new constructs easy to recognize. The try() syntax that's been proposed seems to meet that criteria, although I would argue against multiple resources being opened in one try statement (that's not easy to read) and propose this two-step processes to find the method called to dispose the target of the try: 1. If the instance's class or one of it parent classes or interfaces has an attribute of @Disposable the method named in the attributes "value" value is the name of the method to call. The default value for "value" is "close". So: @Disposable("close") public abstract java.io.InputStream { ... or @Disposable public abstract java.io.InputStream { ... Would call close() to dispose of an InputStream. where as @Disposable("unlock") public interface java.util.concurrent.locks.Lock { ... Would call unlock() to dispose of a Lock. 2. If the instance's class and all of it's parent classes and interfaces has no @Disposable attribute, and a instance method matching this signature 'public void close()' exists, regardless of exception thrown, it can also be used as a resource. So: public void MyClass { public void close() throws MyOwnException; } Could still be used even without the @Disposable attribute even if it's compiled in some jar file that I don't have the source for. I understand the parallelism that we'd like to achieve with the interface decisions made with Iterator. There a very small change was introduced in by the addition of an interface, and voila for-each loops. But we're talking a much broader range of classes here, including various 3rd party binaries that have classes that are resources. With Iterator there was a very small set of classes affected - mainly Collection and arrays, but resources could be database connections, text files, locks, threads, servers, memory, scripting engine or any number of other things. Besides, the Disposable interface ends up basically being a marker interface. Since no one is going to go around throwing Exception from the Disposable interface, you're always going to have to narrow the list of thrown exceptions to something like java.sql.ResultSet so that you can deal with SQLException instead. I can't think of a situation where you're going to be using a Disposable objects directly (other than perhaps some resource manager). So Disposable degrades into a marker interface, and when I think marker interface, I squirm a bit. Here's how the annotation might be described. @Documented @Retention(RetentionPolicy.CLASS) @Target({ElementType.TYPE}) public @interface java.lang.Disposable { String value() default "close"; } The compiler simply picks the correct dispose method (or methods if parent classes define additional dispose methods) at compile time so this has no effect on runtime speed. Remember, the whole idea is to change: A a = new A(); try { B b = new B(); try { a.doSomethingTo(b); } finally { b.dispose(); } } finally { a.dispose(); } into an easier to read, easier to understand, easier to write: try (A a = new A()) { try (B b = new B()) { a.doSomethingTo(b); } } Why should it be limited to classes that have a close() method and have to have a Disposable interface, too? As an aside, one of the ideas that needs to be promoted in any of these proposals, is the idea that the exception thrown during the main life of the resource receives priority over any exception thrown by the dispose method(s). This is a fantastic idea, but sounds fishy at first glance. By responsibly closing your resource even during some catastrophic event you can actually erase what the catastrophic event was and waste many hours of debugging. This idea needs to be made clear: the proposal doesn't not hide the dispose exception, just doesn't favor it when competing with the primary exception. We already have a lot of JDK code out there and a good portion of it does not use close() as it's dispose method. Adding the Dispose interface to so many classes seems to break the "small change rule". An annotation combined with a backup method signature match, covers many more resources than the interface proposal and is more compatible with the various types of resources already in use. P.S. Apologies to any people who's toes I've stepped on, some of the ideas I've stated here have been stated by others, too. -Chris Allen ------------------------------------------------------------------------------------------- ***National City made the following annotations ------------------------------------------------------------------------------------------- This communication is a confidential and proprietary business communication. It is intended solely for the use of the designated recipient(s). If this communication is received in error, please contact the sender and delete this communication. =========================================================================================== From jjb at google.com Mon Apr 13 09:38:30 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 13 Apr 2009 09:38:30 -0700 Subject: Automatic Resource Management In-Reply-To: <7108D662C5ED344CBAD8CAFEEC94244115F59488@ohclemsx1023.corp.ntl-city.net> References: <7108D662C5ED344CBAD8CAFEEC94244115F59488@ohclemsx1023.corp.ntl-city.net> Message-ID: <17b2302a0904130938y76bc6719g25eb5b6aa413a57e@mail.gmail.com> Allen, Hi. Thanks for taking the time to read the proposal. On Mon, Apr 13, 2009 at 9:26 AM, Allen, Chris wrote: > I've looked at Automatic Resource Management proposal, and written this > email and then sat on it for several days, and it seems that the current > proposal, adding a Disposable interface, is arbitrarily restrictive and > that by using an attribute combined with a signature matching we could > get better bang for our buck. We discussed this extensively (you can find it in the archive) and Sun made it clear that this violates the "prime directive" concerning the use of annotations: they are not permitted to change program semantics. I floated a related proposal involving the use of "finally" as a modifier (again, you can find it in the archive), but it necessarily involved changes to the class file format, the tool chain, etc. The consensus was that this was too big a change for Coin, and probably to big a change for the added benefit. Moreover, the added flexibility came with added potential for trouble (how do you ensure that there is a unique disposal method on a given type, or deal with the situation where there's more than one?). > > > As an aside, one of the ideas that needs to be promoted in any of these > proposals, is the idea that the exception thrown during the main life of > the resource receives priority over any exception thrown by the dispose > method(s). This is a fantastic idea, but sounds fishy at first glance. > By responsibly closing your resource even during some catastrophic event > you can actually erase what the catastrophic event was and waste many > hours of debugging. This idea needs to be made clear: the proposal > doesn't not hide the dispose exception, just doesn't favor it when > competing with the primary exception. I'm hard at work on a revision, and hope to have it out later today. I will make sure to make this clear. > > > We already have a lot of JDK code out there and a good portion of it > does not use close() as it's dispose method. That's true, and this facility won't cover everything right away. But it will cover enough types to pay for itself and it will cover more over time. And in the worst case, you can cover arbitrary types by writing adapters. Regards, Josh From angelo.borsotti at gmail.com Mon Apr 13 14:21:10 2009 From: angelo.borsotti at gmail.com (Angelo Borsotti) Date: Mon, 13 Apr 2009 23:21:10 +0200 Subject: Proposal for a small language change Message-ID: <541298b90904131421ocf2aa4buc0bda308f4480367@mail.gmail.com> Author: Angelo Borsotti, former Senior Director Software Technology, Alcatel-Lucent Optics Overview Feature Summary: fast and accurate measurement of execution time Major Advantage: optimization of algorithms by measuring execution times of small snippets of code executed many times Major Benefit: greatly increases observability of programs Major Disadvantage: very little cost Alternatives: there are no alternatives Examples: Simple example: long c0 = System.cycles(); i++; long c = System.cycles() - c0; Advanced example: long cycles = 0; for (int i = 0; i < bound; i++){ ... long c0 = System.cycles(); some statements cycles += System.cycles()- c0; } Details Specification Add a new method System.cycles(). Compilation The method must be compiled inline, translating it into a single instruction, present in most architectures, that reads the cycle counter register (e.g. the TSC in x86 architectures). To measure execution time, System.nanoTime() is currently provided. This, however, is by far too inaccurate to measure the execution time of code which lies inside methods, possibly inside loops. The accuracy that it provides is comparable to the time needed to execute thousands of java statements, which is too low. Moreover, the time spent to execute the nanoTime() method itself makes this tool too much invasive. Execution times become often much higher when nanoTime() is added, to the point to provide useless results. Note that when a piece of code lies inside loops, measuring its execution time means adding many small durations. This means that the invasivity and the accuracy of the tool to measure time is extremely important. Note that also a native method would be too much invasive. The only way to provide a means to measure execution times that introduces an acceptable noise (i.e. an error that is sufficiently lower than the times measured) is to compile the call inline into a machine instruction. Profilers are orders of magnitude coarser than what is needed. Testing A simple test case in which a very simple example (as the one above) is used, that computes the number of cycles needed to perform a simple operation. The result should then be compared agains an estimate. Library suppor None needed Reflective APIs No change Other changes None Migration None Compatibility Completely downward compatible References Bug ID: 6685613 From Joe.Darcy at Sun.COM Mon Apr 13 14:28:49 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Mon, 13 Apr 2009 14:28:49 -0700 Subject: Proposal for a small language change In-Reply-To: <541298b90904131421ocf2aa4buc0bda308f4480367@mail.gmail.com> References: <541298b90904131421ocf2aa4buc0bda308f4480367@mail.gmail.com> Message-ID: <49E3AE91.7010303@sun.com> The Project Coin call for proposals phase is over; no new proposals are being accepted. Microbenching is a tricky area, but not one requiring language support! -Joe PS Somewhat related might be JSR 284: Resource Consumption Management API http://www.jcp.org/en/jsr/detail?id=284 Angelo Borsotti wrote: > Author: Angelo Borsotti, former Senior Director Software Technology, > Alcatel-Lucent Optics > > Overview > Feature Summary: fast and accurate measurement of execution time > Major Advantage: optimization of algorithms by measuring execution > times of small snippets of code executed many times > Major Benefit: greatly increases observability of programs > Major Disadvantage: very little cost > Alternatives: there are no alternatives > > Examples: > > Simple example: > long c0 = System.cycles(); > i++; > long c = System.cycles() - c0; > Advanced example: > long cycles = 0; > for (int i = 0; i < bound; i++){ > ... > long c0 = System.cycles(); > some statements > cycles += System.cycles()- c0; > } > > Details > Specification > Add a new method System.cycles(). > Compilation > The method must be compiled inline, translating it into a single > instruction, > present in most architectures, that reads the cycle counter > register (e.g. the > TSC in x86 architectures). > To measure execution time, System.nanoTime() is currently > provided. This, however, > is by far too inaccurate to measure the execution time of code > which lies inside > methods, possibly inside loops. The accuracy that it provides is > comparable to the > time needed to execute thousands of java statements, which is too low. > Moreover, the time spent to execute the nanoTime() method itself > makes this tool > too much invasive. Execution times become often much higher when > nanoTime() is > added, to the point to provide useless results. > Note that when a piece of code lies inside loops, measuring its execution > time means adding many small durations. This means that the invasivity > and the accuracy of the tool to measure time is extremely important. > Note that also a native method would be too much invasive. The > only way to provide > a means to measure execution times that introduces an acceptable > noise (i.e. an > error that is sufficiently lower than the times measured) is to > compile the call > inline into a machine instruction. Profilers are orders of > magnitude coarser than > what is needed. > Testing > A simple test case in which a very simple example (as the one > above) is used, > that computes the number of cycles needed to perform a simple > operation. The > result should then be compared agains an estimate. > Library suppor > None needed > Reflective APIs > No change > Other changes > None > Migration > None > > Compatibility > Completely downward compatible > > References > Bug ID: 6685613 > > From Ulf.Zibis at gmx.de Mon Apr 13 14:43:08 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Mon, 13 Apr 2009 23:43:08 +0200 Subject: Proposal for a small language change In-Reply-To: <541298b90904131421ocf2aa4buc0bda308f4480367@mail.gmail.com> References: <541298b90904131421ocf2aa4buc0bda308f4480367@mail.gmail.com> Message-ID: <49E3B1EC.7060309@gmx.de> +1 -Ulf Am 13.04.2009 23:21, Angelo Borsotti schrieb: > Author: Angelo Borsotti, former Senior Director Software Technology, > Alcatel-Lucent Optics > > Overview > Feature Summary: fast and accurate measurement of execution time > Major Advantage: optimization of algorithms by measuring execution > times of small snippets of code executed many times > Major Benefit: greatly increases observability of programs > Major Disadvantage: very little cost > Alternatives: there are no alternatives > > Examples: > > Simple example: > long c0 = System.cycles(); > i++; > long c = System.cycles() - c0; > Advanced example: > long cycles = 0; > for (int i = 0; i < bound; i++){ > ... > long c0 = System.cycles(); > some statements > cycles += System.cycles()- c0; > } > > Details > Specification > Add a new method System.cycles(). > Compilation > The method must be compiled inline, translating it into a single > instruction, > present in most architectures, that reads the cycle counter > register (e.g. the > TSC in x86 architectures). > To measure execution time, System.nanoTime() is currently > provided. This, however, > is by far too inaccurate to measure the execution time of code > which lies inside > methods, possibly inside loops. The accuracy that it provides is > comparable to the > time needed to execute thousands of java statements, which is too low. > Moreover, the time spent to execute the nanoTime() method itself > makes this tool > too much invasive. Execution times become often much higher when > nanoTime() is > added, to the point to provide useless results. > Note that when a piece of code lies inside loops, measuring its execution > time means adding many small durations. This means that the invasivity > and the accuracy of the tool to measure time is extremely important. > Note that also a native method would be too much invasive. The > only way to provide > a means to measure execution times that introduces an acceptable > noise (i.e. an > error that is sufficiently lower than the times measured) is to > compile the call > inline into a machine instruction. Profilers are orders of > magnitude coarser than > what is needed. > Testing > A simple test case in which a very simple example (as the one > above) is used, > that computes the number of cycles needed to perform a simple > operation. The > result should then be compared agains an estimate. > Library suppor > None needed > Reflective APIs > No change > Other changes > None > Migration > None > > Compatibility > Completely downward compatible > > References > Bug ID: 6685613 > > > From mthornton at optrak.co.uk Mon Apr 13 14:44:22 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Mon, 13 Apr 2009 22:44:22 +0100 Subject: Proposal for a small language change In-Reply-To: <541298b90904131421ocf2aa4buc0bda308f4480367@mail.gmail.com> References: <541298b90904131421ocf2aa4buc0bda308f4480367@mail.gmail.com> Message-ID: <49E3B236.2050406@optrak.co.uk> Angelo Borsotti wrote: > Author: Angelo Borsotti, former Senior Director Software Technology, > Alcatel-Lucent Optics > > Overview > Feature Summary: fast and accurate measurement of execution time > Major Advantage: optimization of algorithms by measuring execution > times of small snippets of code executed many times > Major Benefit: greatly increases observability of programs > Major Disadvantage: very little cost > Alternatives: there are no alternatives > > Examples: > > Simple example: > long c0 = System.cycles(); > i++; > long c = System.cycles() - c0; > Advanced example: > long cycles = 0; > for (int i = 0; i < bound; i++){ > ... > long c0 = System.cycles(); > some statements > cycles += System.cycles()- c0; > } > > As Joe has said the proposal period is over and this proposal doesn't need a language change. The existing System.nanoTime() method could be implemented using CPU cycle counters. However there are significant problems on multi-core or multi-processor systems and where power management is in use. Some systems don't keep the cycle counters synchronized across CPUs, so if a thread is migrated from one CPU to another the computed elapsed cycle time is not reliable. Some interesting information on timing can be found here: http://blogs.sun.com/dholmes/entry/inside_the_hotspot_vm_clocks Mark Thornton From reinier at zwitserloot.com Mon Apr 13 14:58:22 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 13 Apr 2009 23:58:22 +0200 Subject: Proposal for a small language change In-Reply-To: <49E3B1EC.7060309@gmx.de> References: <541298b90904131421ocf2aa4buc0bda308f4480367@mail.gmail.com> <49E3B1EC.7060309@gmx.de> Message-ID: Bad Idea: What you're talking about is microbenchmarking. Trying to do it, is almost always a good indicator that you're Doing It Wrong. Java doesn't microbenchmark well for several reasons. If you really must benchmark some code, here's how you MUST do it; the following scheme is a neccessary but not sufficient guarantee that you might just be getting relevant timing numbers: Set up something that can be looped over many times. Then, time the time it takes to run the entire loop. Make sure the data that is calculated is used someplace; for example, if you're calculating lists, add the sizes of the lists to a number, then, at the end, print the number (do the printing after the timing, of course - it takes ages!) - otherwise the hotspot compiler will just excise the entire code! Time it for many different loop invocations, and draw a chart. loop count on the x-axis, time taken (in total, not per iteration) on the y- axis. Keep doing this until you get a graph that looks a little like this: for the first X iterations, the line is roughly linear, with a slope of m. Then, there's a sudden spike, and after the spike, the line becomes linear again, with a different slope of n. n is significantly smaller than m (the line is closer to the horizontal). Once you've reached this chart, you've got your answer: The spike is the hotspot compiler kicking in. The m slope gives you the time for the loop pre-hotspot and is mostly irrelevant. The n slope gives you the post-hotspot and is more relevant. This is better than blind microbenchmarking but I'm leaving out many, many important details about how to do microbenchmarking appropriately in java. A 'cycle' method really isn't going to help much - the timing you need to do is many orders of magnitude larger than what System.nanoTime() can reliably measure, so existing tools are fine. Secondly, and more importantly: That's not where timing is _supposed_ to be done in the first place. That's where JVMTI comes in - that's where you need to be doing this. Download a profiler (netbeans has a nice one!) and work with that. A JVM debug can generate cycle instructions if that really would be helpful, just like debug JVMs can print the assembler code generated when hotspotting for the local architecture. If the profiler team needs something to improve their ability to profile, that should certainly be considered, but I seriously doubt they'll be needing a cycle() JVM bytecode to do their job. --Reinier Zwitserloot On Apr 13, 2009, at 23:43, Ulf Zibis wrote: > +1 > > -Ulf > > > Am 13.04.2009 23:21, Angelo Borsotti schrieb: >> Author: Angelo Borsotti, former Senior Director Software Technology, >> Alcatel-Lucent Optics >> >> Overview >> Feature Summary: fast and accurate measurement of execution time >> Major Advantage: optimization of algorithms by measuring execution >> times of small snippets of code executed many times >> Major Benefit: greatly increases observability of programs >> Major Disadvantage: very little cost >> Alternatives: there are no alternatives >> >> Examples: >> >> Simple example: >> long c0 = System.cycles(); >> i++; >> long c = System.cycles() - c0; >> Advanced example: >> long cycles = 0; >> for (int i = 0; i < bound; i++){ >> ... >> long c0 = System.cycles(); >> some statements >> cycles += System.cycles()- c0; >> } >> >> Details >> Specification >> Add a new method System.cycles(). >> Compilation >> The method must be compiled inline, translating it into a single >> instruction, >> present in most architectures, that reads the cycle counter >> register (e.g. the >> TSC in x86 architectures). >> To measure execution time, System.nanoTime() is currently >> provided. This, however, >> is by far too inaccurate to measure the execution time of code >> which lies inside >> methods, possibly inside loops. The accuracy that it provides is >> comparable to the >> time needed to execute thousands of java statements, which is >> too low. >> Moreover, the time spent to execute the nanoTime() method itself >> makes this tool >> too much invasive. Execution times become often much higher when >> nanoTime() is >> added, to the point to provide useless results. >> Note that when a piece of code lies inside loops, measuring its >> execution >> time means adding many small durations. This means that the >> invasivity >> and the accuracy of the tool to measure time is extremely >> important. >> Note that also a native method would be too much invasive. The >> only way to provide >> a means to measure execution times that introduces an acceptable >> noise (i.e. an >> error that is sufficiently lower than the times measured) is to >> compile the call >> inline into a machine instruction. Profilers are orders of >> magnitude coarser than >> what is needed. >> Testing >> A simple test case in which a very simple example (as the one >> above) is used, >> that computes the number of cycles needed to perform a simple >> operation. The >> result should then be compared agains an estimate. >> Library suppor >> None needed >> Reflective APIs >> No change >> Other changes >> None >> Migration >> None >> >> Compatibility >> Completely downward compatible >> >> References >> Bug ID: 6685613 >> >> >> > > From reinier at zwitserloot.com Mon Apr 13 15:21:44 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 14 Apr 2009 00:21:44 +0200 Subject: Automatic Resource Management In-Reply-To: <7108D662C5ED344CBAD8CAFEEC94244115F59488@ohclemsx1023.corp.ntl-city.net> References: <7108D662C5ED344CBAD8CAFEEC94244115F59488@ohclemsx1023.corp.ntl-city.net> Message-ID: <1A55DAD4-F03E-4E06-8C52-C9939006A70A@zwitserloot.com> Allen, you haven't answered any of the questions about using an annotation, even if we forget for a moment that annotations aren't supposed to be used for this in the first place: 1. Do @Disposable annotations inherit (if not, the proposal really stinks, so I'll assume it does, which leads to): 2. What if 1 object has multiple @Disposable annotations? Call them all? That's rather a lot of exceptions that could occur - do we stop calling them all once one of them throws an exception, or keep going? 3. What if the close() method doesn't actually exist? Whose job is it to generate a compiler error? 4. Should @Disposable be sorted out at runtime, or at compiletime? In other words, if I have a variable typed 'Foobar', named 'foobar', and I try() on this, should I just call all the close methods that I can find when chasing down the Disposable annotations of Foobar, or should I ask for foobar's actual type (foobar.getClass()) and work with that instead? If we go with the compile-time option, then won't this cause some fairly serious confusion and possible resource leakage? These are all serious issues, and while you could pick a solution for them all, and document this extensively, your average java programming just doesn't read all of the JLS - in other words, language changes should be as self-sensible as possible. Josh's proposal may not work for every existing class, but it has clear and obvious answers for ALL of those issues. In case people are wondering what they are, here they briefly follow: 1. interfaces inherit already (if your superclass implements X, so do you - you can't undo this), so the answer is obvious: Yes. 2. There's only one method, so even if the Disposable interface is implemented many times over, it makes absolutely no difference: close() willbe called, and that's the only method. 3. It's already an error to not implement an abstract method, so that's easy. 4. This situation cannot occur; either the compile-time type is a Disposable, and thus the close() method is called, or it isn't, and the try() form is not even legal. You could cast your object to a Disposable, and this would work, but then the method to call is also obvious (close), as is the error when the object isn't actually disposable at all (ClassCastException). None of these things even need to be specified in Josh's ARM proposal, because these are the rules that already apply to implementing interfaces. I hope this mail summarizes the major issues (aside from the notion that annotations should not affect compilation like this) with using an annotation. Before initiating too much discussion on these problems, please review the (many, many) emails that have already been spent on the topic, lest we just rehash the same arguments over and over. A telling point: NOBODY submitted an official annotation based ARM proposal for coin (at least none that had a snowball's chance of being accepted - i.e. having enough detail to update javac and covering every open issue like the ones stated above). --Reinier Zwitserloot On Apr 13, 2009, at 18:26, Allen, Chris wrote: > I've looked at Automatic Resource Management proposal, and written > this > email and then sat on it for several days, and it seems that the > current > proposal, adding a Disposable interface, is arbitrarily restrictive > and > that by using an attribute combined with a signature matching we could > get better bang for our buck. > > We already use annotations to describe classes such as persistable or > deprecated, why not as a resource? I've read the objections on this > list to using an annotation, and the interface proposal does list > common > resources such as Streams and SQL constructs, but while the interface > would probably be the preferred way to add this if we were designing > the > language from scratch, we already have a huge collection of code out > there where a typical resource pattern is already used - but where > close() is not the disposal method. People have pointed out locks for > instance, but were told that locks were beyond the scope of this small > change. > > Why? > > We're looking to make a small change to Java that will make source > code > easier to read, write and maintain while making the new constructs > easy > to recognize. > > The try() syntax that's been proposed seems to meet that criteria, > although I would argue against multiple resources being opened in one > try statement (that's not easy to read) and propose this two-step > processes to find the method called to dispose the target of the try: > > 1. If the instance's class or one of it parent classes or interfaces > has > an attribute of @Disposable the method named in the attributes "value" > value is the name of the method to call. The default value for > "value" > is "close". > > So: > > @Disposable("close") > public abstract java.io.InputStream { ... > > or > > @Disposable > public abstract java.io.InputStream { ... > > Would call close() to dispose of an InputStream. > > where as > > @Disposable("unlock") > public interface java.util.concurrent.locks.Lock { ... > > Would call unlock() to dispose of a Lock. > > 2. If the instance's class and all of it's parent classes and > interfaces > has no @Disposable attribute, and a instance method matching this > signature 'public void close()' exists, regardless of exception > thrown, > it can also be used as a resource. > > So: > > public void MyClass { > > public void close() throws MyOwnException; > > } > > Could still be used even without the @Disposable attribute even if > it's > compiled in some jar file that I don't have the source for. > > I understand the parallelism that we'd like to achieve with the > interface decisions made with Iterator. There a very small change was > introduced in by the addition of an interface, and voila for-each > loops. > But we're talking a much broader range of classes here, including > various 3rd party binaries that have classes that are resources. With > Iterator there was a very small set of classes affected - mainly > Collection and arrays, but resources could be database connections, > text > files, locks, threads, servers, memory, scripting engine or any number > of other things. > > Besides, the Disposable interface ends up basically being a marker > interface. Since no one is going to go around throwing Exception from > the Disposable interface, you're always going to have to narrow the > list > of thrown exceptions to something like java.sql.ResultSet so that you > can deal with SQLException instead. I can't think of a situation > where > you're going to be using a Disposable objects directly (other than > perhaps some resource manager). So Disposable degrades into a marker > interface, and when I think marker interface, I squirm a bit. > > Here's how the annotation might be described. > > @Documented > @Retention(RetentionPolicy.CLASS) > @Target({ElementType.TYPE}) > public @interface java.lang.Disposable { > String value() default "close"; > } > > The compiler simply picks the correct dispose method (or methods if > parent classes define additional dispose methods) at compile time so > this has no effect on runtime speed. Remember, the whole idea is to > change: > > A a = new A(); > try { > B b = new B(); > try { > a.doSomethingTo(b); > } > finally { > b.dispose(); > } > } > finally { > a.dispose(); > } > > into an easier to read, easier to understand, easier to write: > > try (A a = new A()) { > try (B b = new B()) { > a.doSomethingTo(b); > } > } > > Why should it be limited to classes that have a close() method and > have > to have a Disposable interface, too? > > As an aside, one of the ideas that needs to be promoted in any of > these > proposals, is the idea that the exception thrown during the main > life of > the resource receives priority over any exception thrown by the > dispose > method(s). This is a fantastic idea, but sounds fishy at first > glance. > By responsibly closing your resource even during some catastrophic > event > you can actually erase what the catastrophic event was and waste many > hours of debugging. This idea needs to be made clear: the proposal > doesn't not hide the dispose exception, just doesn't favor it when > competing with the primary exception. > > We already have a lot of JDK code out there and a good portion of it > does not use close() as it's dispose method. Adding the Dispose > interface to so many classes seems to break the "small change > rule". An > annotation combined with a backup method signature match, covers many > more resources than the interface proposal and is more compatible with > the various types of resources already in use. > > P.S. Apologies to any people who's toes I've stepped on, some of the > ideas I've stated here have been stated by others, too. > > -Chris Allen > > ------------------------------------------------------------------------------------------- > ***National City made the following annotations > ------------------------------------------------------------------------------------------- > This communication is a confidential and proprietary business > communication. > It is intended solely for the use of the designated recipient(s). > If this > communication is received in error, please contact the sender and > delete > this communication. > = > = > = > = > = > = > = > = > = > = > = > = > = > = > = > = > = > = > = > = > = > ====================================================================== > From reinier at zwitserloot.com Mon Apr 13 16:54:54 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 14 Apr 2009 01:54:54 +0200 Subject: Automatic Resource Management In-Reply-To: <200904140134.22467.peter.levart@gmail.com> References: <7108D662C5ED344CBAD8CAFEEC94244115F59488@ohclemsx1023.corp.ntl-city.net> <1A55DAD4-F03E-4E06-8C52-C9939006A70A@zwitserloot.com> <200904140134.22467.peter.levart@gmail.com> Message-ID: If the notion that 1 interface, with the associated forced 'close()' method, is considered too great of a problem, then your proposal is certainly the only viable alternative IMO. You can even play with the syntax to open multiple resources (but personally I'm somewhat opposed to letting any kind of ARM block open multiple resources in one statement; what's the problem with nesting a few of them?). The problem I have with your proposal is twofold. One is simple, one is fairly esoteric: 1. Disposable/close() fits almost all use-cases, and the foreach syntax has shown that not covering every single existent base is not going to be a problem; the java world will adapt and come around to it. Especially because the libraries that can't work with this scheme don't seem too important to the java community at this point (more on that later). 2. The esoteric one: For semantics' sake, I would consider the closing statement to be better located at the end of the guarded block - but how do we figure this out, syntax wise? You could use the 'finally' keyword, which makes some sense, but the finally keyword already has meanings which are not quite compatible with the meaning of ARM-style final code: exceptions in the main body have precedence in ARM blocks, but they lose out in the usual try/finally. This makes finally a bad keyword, and in fact gets in the way of the entire concept: It LOOKS like you're just using a slightly different version of try/finally syntax, but that's not really what's going on. That makes your proposal somewhat ambiguous without knowing the JLS specifics. It's not nearly as bad as some of the other proposals, so not a showstopper, but certainly a nit. Having said that, there might be a way out of this, by integrating both proposals. 1. Remove the ability to put multiple resources in one statement; what's the problem with nesting trywith blocks again? 2. Use the ; to switch to the alternate form of resource management: try ( a ; b ) {} no longer requires that is an expression of type 'Disposable' (or a variable declaration of a Disposable), and instead, b is run at the end analogous to your proposal. Then, for all objects that know how to dispose of themselves, you just go try ( object ) { stuff }, but when they don't, you can work around it with try ( object ; closeIt ) { stuff }. NOTE: I'm not actually in favour of this, because, at the risk of taking a contentious position, I don't rate the libraries that can't deal with Disposable very highly. SWT was absolutely excellent when it was released, and the java community owes it a great thank you for lighting the fire of competition under awt/swing's behind, but between new swing versions and javaFX, SWT's time has gone, eclipse needs to migrate over, and SWT needs to slowly but surely go away now. Locks are handled just as well, IMO, with the existing try/finally structure, primarily because lock.unlock() generally doesn't throw exceptions, which is a big reason for using ARM in the first place. --Reinier Zwitserloot On Apr 14, 2009, at 01:34, Peter Levart wrote: > Hello Reinier, > > What do you think of the idea of explicit resource cleanup (as > opposed to > using interface) that I have described a few days ago (in > http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001383.html) > . > > The way I see it is best described by the following parallelism: > > Cleaning up resources correctly with existing try-catch-finally > construct as > opposed to using Joshua's ARM is like iterating over elements of the > array > using while loop as opposed to using foreach. > > int i = 0; > while (i < array.length) > { > Type a = array[i] ; > ... > i++; > } > > vs. > > foreach (Type a : array) > { > ... > } > > > ... but using existing try-catch-finally vs. Semi-Automatic- > Resource-Cleanup > (described in my previous mail) is like using while vs. for > > int i = 0; > while (i < array.length) > { > Type a = array[i] ; > ... > i++; > } > > vs. > > for (int i = 0; i < array.length; i++) > { > Type a = array[i]; > ... > } > > > ...there's not much less typing, everything is still explicit. But > the idiom > is "captured" in a predefined construct leaving less chance for an > average > programmer to do it wrong. > > Using 'for' instead of 'foreach' leaves you more flexibility if you > need it. > For example: > > for (int i = offset; i < array.length && i < offset + length; i+ > +) ... etc. > > The question is: Do we want to be more flexible (and type a little > more) when > capturing the resource cleanup idiom? > > Regards, Peter > From Joe.Darcy at Sun.COM Mon Apr 13 18:55:08 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Mon, 13 Apr 2009 18:55:08 -0700 Subject: Helping to find the usefulness of a proposal In-Reply-To: References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <28bca0ff0904020528l51d803f2t5a6dc29a8f6a67dc@mail.gmail.com> <31AB3E69-CCE7-4134-95C9-4DB5BF6C9281@zwitserloot.com> <49D516A6.6000404@sun.com> Message-ID: <49E3ECFC.6000002@sun.com> On 04/02/09 04:30 PM, rssh at gradsoft.com.ua wrote: [snip] >>> Note, that I does not propose use polls as one and only one criteria. I >>> just tell that see result of such poll will be interest. >>> >>> // btw - from other side, all this activity is overkill, I can suggest, >>> // that accepted proposals would be exactly same, which was listed in >>> // project-coin description (before coin was started) >>> // http://blogs.sun.com/darcy/entry/project_coin >>> // +ARM +jsr292 and ... it's already 6, which is more than 5 :) >>> >>> >> Your own sentence disproves your point since ARM was not listed among >> the five proposal areas under consideration before Project Coin started. >> >> > > I mean not 'would be exactly same, which was listed in project-coin > description (before coin was started)[url]', but 'would be > exactly same, which was listed in project-coin description (before coin > was started)[url] +ARM +jsr292', > sorry for ambiguity. > > ARM floating around (and widly discussed) from late 2007 or early 2008. > And all we know, that if BGGA will not available, than at least ARM must > be included. I don't know that. > I. e. I can't say that ARM is 'external' and new or not to > be generally known be included in Java 7 before project coin start. > > I have no pretension about judgement process, It's only about information > flow: i. e. Sun have all proposals before and call for new > proposals with process of selecting 5 from set of newly received and 5 > apriory well-known items, for which we know, that they are necessory, it's > near the same, that throw away all non-apriory proposals. > > > I. e. I guess, that when people asked to submit new proposals, they expect > that exists demand for new proposals, not demand for choosing from five > well-known items. When appointment of all new proposals to be thrown away, > with role be backgroung for well-known items, people, which invested some > time in such activity, usually frustrated. It's why I think, that call for > new proposals, whithout real possibility to implement something new (not > well-known before) was an error. If we have slot, for example, in summary > for 10 proposals to implement (5 well know and 5 new) - then all ok, it's > fair game. > Amongst other factors, the maximum number of proposals that can get in is a function of how many people work on implementations. Very few of the proposals had any accompanying prototype. For example, I'm sympathetic to the idea of having literals for bit strings and the like; those are much more likely to end up as part of the platform if people outside of Sun take the lead on the implementation. However, even with help from the broader community, there is still an upper-bound on how many small language changes can get in because of various kinds of coordination activities that do not scale and the non-implementation aspects of the work (specification and testing). Many of the submitted proposals were not really proposals in terms of a thoughtful analysis of what it would take to add a feature to the platform; rather they were "requests for enhancement" in Sun bug database terminology where much of the hard work of thinking through implications and interactions was left undone. Existing discussion of such issues from Sun's bug database were often ignored even though they can be found by a simple web search query. And a specification is much more than the grammatical changes involved! >>> I. e. doing project coin with external auditory was a 'Sun system >>> error', >>> I guess; if they want some feedback from community, correct way was at >>> first implement own stuff, than ask community for something new ;) >>> >>> >> The call of proposal phase of Project Coin is an effort both to solicit >> feedback from the external community and also to invite the external >> community to participate more directly in evolving the language. That >> opportunity to participate also implies participating in the large >> amount of work required to go from "I have this great idea!" to "I have >> this great idea and here is a carefully considered review of all the >> implications of the idea, along with a prototype." The blogs I wrote >> last year and the proposal form itself are part of an effort to explain >> and expose what this language work entails so more people can get >> involved. >> >> > > > It would be great, to participate in language evolution in future. > For now I does not see general aviable process for future participation: > call closed, all new proposal throwed away. > I would counter the list received few serious actual proposals, which is directly tied to why few proposals (so far) have been selected for further consideration. I reviewed all open language specification RFEs last year. A restatement of an existing RFE in Sun's bug database as a Project Coin proposal without any further analysis has approximately zero value. Last year I published a list of five proposal ideas to seed the discussion. Opinions will differ of course (different parts of the elephant), but I think few of the submitted proposals were as compelling as the problems being addressed by those initial five proposals, which again relates to why those proposal areas have not been displaced by subsequent ones. > Finish. Fire bug reports is useless - they will live in bugzilla for years. > > One possible solution: is make 'coin project' regular, for example once a > year. (May be with > entry barrier as 'required implementation in some form') > Another - propose some process (may be long) for author, how to push his > proposal (whith implementation) > into language after JDK7 (or receive official position, that this change > is rejected) > > > >> Unfortunately, many of the submitted proposals did not do a credible job >> of analyzing the true effect the proposal would have, which has a rather >> strong relation to why many were not chosen for further consideration. >> For example, let's take the "'This' type" proposal: >> >> > ... > > > Problem with inaccurate proposals - it's well known problem, the same with > publications, wildly used technique is peer review. (Honesly, overall > quality of proposals was better that I was expected). > Yes, the list is for peer review and many proposals found a vigorous discussion there! In retrospect, I think it would have been helpful to publish, say, the completed strings in switch proposal form sooner after the proposal form was published. That form for a very simple language change indicates the degree of thoroughnesses I would have liked to have seen from all the proposals: http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000001.html > Good entry barrier can be requirement to proposal to be implemented in > some form. > > P.S. Project coin involved me to think about Java more close than before. > So, despite my criticism, you achieve goal to raise interest to > participate in process of Java language evolution ;) > That is something at least ;-) -Joe From peter.levart at gmail.com Tue Apr 14 00:04:23 2009 From: peter.levart at gmail.com (Peter Levart) Date: Tue, 14 Apr 2009 09:04:23 +0200 Subject: Automatic Resource Management In-Reply-To: References: <7108D662C5ED344CBAD8CAFEEC94244115F59488@ohclemsx1023.corp.ntl-city.net> <1A55DAD4-F03E-4E06-8C52-C9939006A70A@zwitserloot.com> <200904140134.22467.peter.levart@gmail.com> Message-ID: On Tue, Apr 14, 2009 at 1:54 AM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > Having said that, there might be a way out of this, by integrating both > proposals. > > 1. Remove the ability to put multiple resources in one statement; what's > the problem with nesting trywith blocks again? > > 2. Use the ; to switch to the alternate form of resource management: try ( > a ; b ) {} no longer requires that is an expression of type 'Disposable' (or > a variable declaration of a Disposable), and instead, b is run at the end > analogous to your proposal. > > Then, for all objects that know how to dispose of themselves, you just go > try ( object ) { stuff }, but when they don't, you can work around it with > try ( object ; closeIt ) { stuff }. That's a great idea. It would encourage people to build APIs around a common interface but still allow using a different style of programming or enable proper resource cleanup even in situations where the shear reference to the resource is not enough to dispose it. What am I talking about? > NOTE: I'm not actually in favour of this, because, at the risk of taking a > contentious position, I don't rate the libraries that can't deal with > Disposable very highly. SWT was absolutely excellent when it was released, > and the java community owes it a great thank you for lighting the fire of > competition under awt/swing's behind, but between new swing versions and > javaFX, SWT's time has gone, eclipse needs to migrate over, and SWT needs to > slowly but surely go away now. Locks are handled just as well, IMO, with the > existing try/finally structure, primarily because lock.unlock() generally > doesn't throw exceptions, which is a big reason for using ARM in the first > place. > > --Reinier Zwitserloot ... I'm thinking of numerous situations where propper clean-up is the responsibility of third party code, not the resource itself. This is usually the case of libraries that are build as a wrapper arround some other lower-level API and expose references to lower-level resources. Take for example Hibernate. There's a snippet of code from an "identity generator" (the resources are not closed optimally here since exceptions thrown in resource cleanup override main exceptions. The reason? Probably laziness): try { PreparedStatement st = session.getBatcher().prepareSelectStatement(sql); try { ResultSet rs = st.executeQuery(); try { rs.next(); return rs.getLong(1); } finally { rs.close(); } } finally { session.getBatcher().closeStatement(st); } } catch (SQLException sqle) { throw JDBCExceptionHelper.convert( session.getFactory().getSQLExceptionConverter(), sqle, "could not execute select statement", sql ); } ... here a special class called Batcher is the manager of the JDBC resource called PreparedStatement. Proper initialization and cleanup is it's responsibillity. You may argue that Hibernate should not "leak" lower-level API through it's own API and should wrap PreparedStatement in it's own class. That is the ideal world. In reality this is often practiced to make code more "economic". Regards, Peter From Ulf.Zibis at gmx.de Wed Apr 15 07:33:04 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Wed, 15 Apr 2009 16:33:04 +0200 Subject: scripts and results (was Helping to find the usefulness of a proposal) In-Reply-To: <60287e9e1530b3e1ae49976316e8dc57.squirrel@wmail.gradsoft.ua> References: <60287e9e1530b3e1ae49976316e8dc57.squirrel@wmail.gradsoft.ua> Message-ID: <49E5F020.7060508@gmx.de> Hi Ruslan, I would like to see the results for "objects and expressions in switch" which includes: - string in switch - instanceof switch I guess a very big chunk of all if-else if-structures would be covered by: http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html A n y C A P A C I T Y t o a d d t h i s p a t t e r n t o y o u r s c r i p t ? ? As I argued before, I'm against the current syntax of the "string in switch"-proposal, as it weakens switch..case semantics for identity, and it encumbers later enhancements for the future. See: http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html. - Ulf Am 07.04.2009 02:33, Ruslan Shevchenko schrieb: > Good day, > > Few days ago Stephan give idea about writing simple script, which > count amount of possible-optimizations of existing code. > > So, I wrote few checks for some of such entries. They count > low bound of number of code patterns, which can be optimized with > some of coin proposal and situated on distinct source lines. > > I'm afraid that information, which come from count of such code patterns > can give incorrect direction: when we have such patterns in code, > it's means that problem is not so big and we can easy live with one. > Big language problems solved (or not) in non-trivial way, when we have no > common (may be ugly) workaround. > For example. in Java we rare will see BigDecimal.add() because it is not > easy to work with BigDecimals, instead people work with double and have > troubles > with floating points rounding issues (see > http://www.ddj.com/java/184405721)). > Yet one example - choosing another language for implementing db-intensive > parts of projects. > > Ok, you warned; data still can be interesting: > > Checked patterns was: > string in switch > instanceof switch > byte literals > multi catch > loop by iterator, with call remove inside loop > > (if you want include other checks, you can add one at > etc/checkers_coin.def or ask me [but without any warranty]) > > > Exists one proposal, which I can't find on Joe blog: is change of variable > subtype inside 'if instance' statement > I. e. patterns look: > if (x instanceof something) > { > something sx = (something)x; > } > And proposal tell type 'x' as 'something' inside dominate if block. > Are anybody remember such proposal or it's was my fantasy ? > > > Some results: > > For jetty6_11: (web server) > byte literal : 52 > elvis : 43 > instanceof switch : 8 > loop with remove : 0 > multi catch : 22 > string in switch : 19 > Files:187 > > For gwt-user (google ajax library) > byte literal : 2 > elvis : 30 > instanceof switch : 6 > loop with remove : 5 > multi catch : 9 > string in switch : 10 > Files:920 > > For openjdk-jdk part: (system library) > byte literal : 1245 > elvis : 725 > instanceof switch : 252 > loop with remove : 61 > multi catch : 349 > string in switch : 380 > Files:7375 > > > > If you want to play with checks - most easy way is get special modified > source > distributive of JavaChecker, which I published as 2.5.0p0 and run it, i.e. > (assuming you on Unix console) > > retrive distributive: > > wget > http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerSourceInstaller-2.5.0p0.jar > > run installer: > java -jar JavaCheckerSourceInstaller-2.5.0p0.jar > (install one from UI) > > cd > > vi build-check-external.xml, look at few last tasks at end > > vi check-external.properties > > add own task and run one, as example: > ant -f build-check-external.xml check-coin-openjdk > > Note, that speed of JavaChecker is far from ideal: openJDK-jdk > processed near 50 minutes, so be patient ;) > > Hope, this information can be useful, as one (and not main) of sources. > > Regards ! > > > > > From paul.martin at gmail.com Wed Apr 15 15:54:04 2009 From: paul.martin at gmail.com (paul.martin at gmail.com) Date: Wed, 15 Apr 2009 22:54:04 +0000 Subject: Helping to find the usefulness of a proposal In-Reply-To: <49E3ECFC.6000002@sun.com> Message-ID: <001485f6307408a1e304679fd349@google.com> (In reply to "On Apr 14, 2009 2:5am, Joe Darcy wrote:") Hi, Some of this discussion is frustrating. I think that to say that "the list received few serious actual proposals" is unfair, at least in terms of the enthusiasm of the discussions, and in terms of the criticism of the proposals themselves. I also don't remember seeing many requests for further detail in discussions about proposals, so it is unfair to criticise their "degree of thoroughness" after the process has closed. Further detail (including prototypes) could always have been provided where necessary, though in most cases I don't think that this was required - the extra detail would be most useful when taking selected proposals further on in the process, but that detail would not necessarily be required when making that selection. Some proposals were effectively repeating RFEs, but without knowing why you didn't include them on your initial candidate list we cannot know whether raising them as proposals is actually justified (maybe you missed an important use case). For example my proposal on named parameters does have a relevant bug: 6444738 (which admittedly I did not mention, though I did reference another), which has an evaluation comment of "We should do this for 7; parameter names are also needed for keyword parameters". Named parameters were even on the slides at a recent (March) Sun Java presentation in London, but they don't now seem to be on the cards for Java 7. My proposal was really to ask why not, but I don't think that question was answered. I am also not suggesting that the selected proposals will not be useful and should not be chosen - they are all good choices (though they mainly ease syntax rather than increasing the capabilities of the language). However, I would like to know why other proposals were not selected, but this only needs to be at a high level. For example, the following categorisation would work for me: 'Good' (the right size, but not as good as the selected proposals), 'out of scope' for Coin (good, but too hard), 'rejected' (we won't ever do this - though a brief reason would help), and 'not understood'. Much of this is probably just miscommunication and misunderstanding: after looking through your posts and presentations in the light of this discussion, I can see that you probably did want fewer and more detailed proposals, but that wasn't clear (to me at least) in your weekly blog posts and comments on the proposals. Hopefully this all makes sense. I really did enjoy the process, and appreciate the effort that you put in to make it happen. But maybe a little 'finessing' of your conclusions would keep me happy! Regards, Paul From reinier at zwitserloot.com Wed Apr 15 17:03:09 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 16 Apr 2009 02:03:09 +0200 Subject: Splitting the meat of a proposal from the trivial details. In-Reply-To: <001485f6307408a1e304679fd349@google.com> References: <001485f6307408a1e304679fd349@google.com> Message-ID: <906692CA-71E0-4869-9591-076C05A15420@zwitserloot.com> Actually, Joe has repeatedly turned down proposals because they were laughably incomplete, and Neal Gafter had gone through the trouble of writing up an example proposal before March 1st that showed most of the concerns that were nonetheless completely skipped in most proposals (such as definitive assignment rules). However - I still mostly agree with your sentiment. The amount of work and detail required before a proposal was considered 'complete' was considerable, and yet the vast majority of proposals (even with the neccessary detail) were clearly going to be rejected (only 4 to 5, tops, that's been said many times). This provides a dilemma: Put in all that effort for not much to show for it? I felt that many (but not all) of the proposals essentially had enough detail in them to allow you to figure out if they were a good idea or not. If there had been another month, such a half-finished proposal could have been pointed out as 'would be on the shortlist, if only someone went through the effort of going through all the details, including writing down something like the definitive assignment rules. I think we'd have seen more useful discussion on proposals, and waste less time on trivialities, if it had been set up like that. For example, I was going to write up my plan to allow named parameters in method signatures, but in the end decided against it, because writing out the full JLS spec including chapter and verse would have been too much effort, compared to the tiny chance it would have been considered worthy for coin. If, however, there was a separate pre- proposal phase, I could have easily written up the gist of the proposal, many examples, and ample support that my proposal would be backwards and migration compatible, would not lead to much confusion, and would not be amiguous. If, then, the proposal would be accepted as 'likely good for java, -if- fully specced and no surprises turn up', I'd gladly have taken the time to write it out in excruciating detail, and cook up a prototype. This Project Coin was pressed for time, so much more than a month just wasn't on the table, but for next time, I suggest smearing out coin across 3 months: Day 1-30: Pre-proposal Month. A Pre-proposal discusses the feature at hand, what it'll solve, ample example code of real-life situations so we can all assess the utility and impact of the change, and much discussion about backwards and migration compatibility, how confusing the feature may be in certain situations (a.k.a. the java puzzler factor), and if the proposal is ambiguous. This is not the time to complain about potential problems and ambiguities for which the complainer-to-be can already think of a fairly simple solution by himself - this is about fundamental issues with a proposal, and the merits of each. Not for sweating the small stuff. The deadline for submitting a pre-proposal is day 20 (to give pre- proposals submitted on the deadline at least 10 days to be discussed). Day 31-37: Rest week. Day 38-45: Pre-proposal sorting. Be it via polling or internal decision by sun or a combination of the two, this is the time to sort pre-proposals into 'no way', and 'on the shortlist'. Day 45-90: Prototype and spec month. This is the time for the shortlisted proposals to be fully specced (with chapter and verse of the JLS as well as rewrites for the JLS), and preferably a working prototype. The deadline for delivering the spec+prototype is day 75, to give the list time to analyse all proposals, even those submitted on the deadline. This IS the time to name rare and easily solved nitpicks, ambiguities, no matter how trivial, and other ommissions. At this point the discussion should turn towards implementation detail, and not so much the merits (all pre-proposals on the shortlist have already been deemed as having the merit to make it, so if you don't like a proposal that's on the shortlist, or you do like one that isn't, tough - the decision has been made, move on). Of course, proposals that end up being more complicated than they appeared to be in the pre-proposal phase can still be discussed on merit (is it STILL worth it, now that we figured out it's going to be this complicated?). I would be tempted to say that ONLY shortlisted pre-proposals should even be considered in this phase, as to keep down unrelated chatter on pet projects. Aftermath: The shortlist is amended: Those on the shortlist that were unsifficiently specced out are tossed, regardless of merit (if it was such a good idea, ostensibly someone would have written it up properly). Those that are fully specced are reconsidered again. Preferably soon after the end of the 3 month period, the semi-official list is released. (semi-official as in: These are the new language features, barring unexpected surprises when we implement these into the JLS and javac). How some of the proposals would have gone, if the above flow had been used for coin: ARM - posted early in the pre-proposal phase, all the discussion we've seen, without the need for Josh to keep updating the proposal in all that detail. Somewhere around today, Josh or someone else coordinating with Josh, starts working on a prototype. 2 months from now, with a complete spec and prototype, ARM is officially accepted into java7 (well, if there hadn't been JSR issues). Neal's expression blocks - little discussion (we haven't seen much in coin either), but nobody can come up with serious issues either, and neal adequatedly shows that the block proposal is unlikely to cause serious issues. For whatever reason (denying pre-proposals should not need a lengthy defense), the pre-proposal is not put on the shortlist, and that's where it ends. --Reinier Zwitserloot On Apr 16, 2009, at 00:54, paul.martin at gmail.com wrote: > (In reply to "On Apr 14, 2009 2:5am, Joe Darcy > wrote:") > > Hi, > > Some of this discussion is frustrating. I think that to say that > "the list > received few serious actual proposals" is unfair, at least in terms > of the > enthusiasm of the discussions, and in terms of the criticism of the > proposals themselves. I also don't remember seeing many requests for > further detail in discussions about proposals, so it is unfair to > criticise > their "degree of thoroughness" after the process has closed. Further > detail > (including prototypes) could always have been provided where > necessary, > though in most cases I don't think that this was required - the extra > detail would be most useful when taking selected proposals further > on in > the process, but that detail would not necessarily be required when > making > that selection. > > Some proposals were effectively repeating RFEs, but without knowing > why you > didn't include them on your initial candidate list we cannot know > whether > raising them as proposals is actually justified (maybe you missed an > important use case). For example my proposal on named parameters > does have > a relevant bug: 6444738 (which admittedly I did not mention, though > I did > reference another), which has an evaluation comment of "We should do > this > for 7; parameter names are also needed for keyword parameters". Named > parameters were even on the slides at a recent (March) Sun Java > presentation in London, but they don't now seem to be on the cards > for Java > 7. My proposal was really to ask why not, but I don't think that > question > was answered. > > I am also not suggesting that the selected proposals will not be > useful and > should not be chosen - they are all good choices (though they mainly > ease > syntax rather than increasing the capabilities of the language). > However, I > would like to know why other proposals were not selected, but this > only > needs to be at a high level. For example, the following categorisation > would work for me: 'Good' (the right size, but not as good as the > selected > proposals), 'out of scope' for Coin (good, but too hard), > 'rejected' (we > won't ever do this - though a brief reason would help), and 'not > understood'. > > Much of this is probably just miscommunication and misunderstanding: > after > looking through your posts and presentations in the light of this > discussion, I can see that you probably did want fewer and more > detailed > proposals, but that wasn't clear (to me at least) in your weekly > blog posts > and comments on the proposals. > > Hopefully this all makes sense. I really did enjoy the process, and > appreciate the effort that you put in to make it happen. But maybe a > little 'finessing' of your conclusions would keep me happy! > > Regards, > > Paul > From neal at gafter.com Wed Apr 15 17:33:55 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 15 Apr 2009 17:33:55 -0700 Subject: Helping to find the usefulness of a proposal In-Reply-To: <001485f6307408a1e304679fd349@google.com> References: <49E3ECFC.6000002@sun.com> <001485f6307408a1e304679fd349@google.com> Message-ID: <15e8b9d20904151733o32920606ve31c5ade09b6c4fd@mail.gmail.com> On Wed, Apr 15, 2009 at 3:54 PM, wrote: > Some of this discussion is frustrating. I think that to say that "the list > received few serious actual proposals" is unfair, at least in terms of the > enthusiasm of the discussions, and in terms of the criticism of the > proposals themselves. Paul- Specificity is needed to determine if a proposal is simple enough for project Coin. I didn't bother commenting on proposals that had only a hint of a specification. An RFE - requesting that a problem be solved (even if it suggests a direction for the solution) - is far from a proposal for a specific solution. Evaluating an RFE to the needed level of detail would require we not just comment on the problem space, but evaluate the entire solution space and comment on the best of the solutions we can imagine. The proposer was supposed to do that, and describe precisely one selected solution. I know that is a lot of work and may require specialized skills. That is why the readers of a proposal cannot be expected to do it. I didn't bother commenting on some proposals because I just didn't see much benefit compared to the effort. As much fun as it is to discuss language design, this list is not really the best place for that design to take place. If a lot of discussion is needed to move a proposal forward now, that is a sign that the proposal is complex, or imprecise, or immature and likely to require extensive discussion and refinement in the expert group. Any of these suggests that the proposal would probably require more effort than is appropriate for project Coin. Regards, Neal From Joe.Darcy at Sun.COM Wed Apr 15 21:35:24 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Wed, 15 Apr 2009 21:35:24 -0700 Subject: Splitting the meat of a proposal from the trivial details. In-Reply-To: <906692CA-71E0-4869-9591-076C05A15420@zwitserloot.com> References: <001485f6307408a1e304679fd349@google.com> <906692CA-71E0-4869-9591-076C05A15420@zwitserloot.com> Message-ID: <49E6B58C.7020107@sun.com> Reinier Zwitserloot wrote: > Actually, Joe has repeatedly turned down proposals because they were > laughably incomplete, Quite so! > and Neal Gafter had gone through the trouble of > writing up an example proposal before March 1st that showed most of > the concerns that were nonetheless completely skipped in most > proposals (such as definitive assignment rules). > Part of my goal of sending in the strings in switch proposal (first post!) was to demonstrate the sort of details that can come up even in the simplest of changes. > However - I still mostly agree with your sentiment. The amount of work > and detail required before a proposal was considered 'complete' was > considerable, and yet the vast majority of proposals (even with the > neccessary detail) were clearly going to be rejected (only 4 to 5, > tops, that's been said many times). > Yes, the limited size of the set of possible proposals was established before the call for proposals started. However, the time required to write up even a fairly detailed proposal, say 8 hours, pales in comparison to the possible effort needed to fully implement a proposal. For example, implementing just the *single method* Class.isEnum probably took around five hours of effort during JDK 5. While this method is only two lines long, three tries were needed before getting the right two lines; more detail on why this happened is described in: http://blogs.sun.com/darcy/entry/so_you_want_to_change > This provides a dilemma: Put in all that effort for not much to show > for it? > As I've stated before, Project Coin is a participatory process, which means people have the opportunity to participate in the work of a proposal too :-) > I felt that many (but not all) of the proposals essentially had enough > detail in them to allow you to figure out if they were a good idea or > not. If there had been another month, such a half-finished proposal > could have been pointed out as 'would be on the shortlist, if only > someone went through the effort of going through all the details, > including writing down something like the definitive assignment rules. > I think we'd have seen more useful discussion on proposals, and waste > less time on trivialities, if it had been set up like that. > While some iteration and refinement of proposals is fine and expected, details are not trivialities. Seemingly small details can make a difference and having some set of details available early allows better decisions to be made. > For example, I was going to write up my plan to allow named parameters > in method signatures, but in the end decided against it, because > writing out the full JLS spec including chapter and verse would have > been too much effort, compared to the tiny chance it would have been > considered worthy for coin. If, however, there was a separate pre- > proposal phase, I could have easily written up the gist of the > proposal, many examples, and ample support that my proposal would be > backwards and migration compatible, would not lead to much confusion, > and would not be amiguous. If, then, the proposal would be accepted as > 'likely good for java, -if- fully specced and no surprises turn up', > I'd gladly have taken the time to write it out in excruciating detail, > and cook up a prototype. > > > This Project Coin was pressed for time, so much more than a month just > wasn't on the table, but for next time, I suggest smearing out coin > across 3 months: > The future existence of what would be known of Project Coin was announced on December 8, 2008 (http://blogs.sun.com/darcy/entry/small_language_changes_jdk_7). This included an overview of the coming call for proposals and a link to "So you want to change the Java Programming Language...", whose content served as the skeleton for the later proposal form. The proposal form was published in January 27, 2009 (http://blogs.sun.com/darcy/entry/project_coin) and the mailing list started a month later, February 27, 2009. So there was a three month period before the call for proposals officially got underway, and a month after the form was published but before a proposal could be submitted, where interested parties could think about proposal ideas and possibly implement them, guided by the published criteria for the effort. There were a few inquiries to the list to ask for help drafting a proposal and some "pre-proposals" sent in to get a reading on whether a proposal topic would be smiled upon, both of which are good, on-topic uses of the list! However, after my unfavorable assessment of the "Source and Encoding keyword" pre-proposal (http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000298.html) was sent to the list, people choose to continue the discussion for a time. Some continued discussion is fine, but people who send in proposals or pre-proposals don't to tend to give up right away ;-) To reiterate terms of roles and responsibilities here, "Especially with the maturity of the Java platform, the onus is on the proposer to convince that a language change should go in; the onus is not to prove the change should stay out." http://blogs.sun.com/darcy/entry/criteria_for_desirable_small_language December 23, 2008 Having thought through the details is one way to be more convincing. -Joe From Joe.Darcy at Sun.COM Wed Apr 15 23:00:23 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Wed, 15 Apr 2009 23:00:23 -0700 Subject: Helping to find the usefulness of a proposal In-Reply-To: <15e8b9d20904151733o32920606ve31c5ade09b6c4fd@mail.gmail.com> References: <49E3ECFC.6000002@sun.com> <001485f6307408a1e304679fd349@google.com> <15e8b9d20904151733o32920606ve31c5ade09b6c4fd@mail.gmail.com> Message-ID: <49E6C977.5080702@sun.com> Neal Gafter wrote: > On Wed, Apr 15, 2009 at 3:54 PM, wrote: > >> Some of this discussion is frustrating. I think that to say that "the list >> received few serious actual proposals" is unfair, at least in terms of the >> enthusiasm of the discussions, and in terms of the criticism of the >> proposals themselves. >> > > Paul- > > Specificity is needed to determine if a proposal is simple enough for > project Coin. I didn't bother commenting on proposals that had only a > hint of a specification. An RFE - requesting that a problem be solved > (even if it suggests a direction for the solution) - is far from a > proposal for a specific solution. Evaluating an RFE to the needed > level of detail would require we not just comment on the problem > space, but evaluate the entire solution space and comment on the best > of the solutions we can imagine. The proposer was supposed to do > that, and describe precisely one selected solution. I know that is a > lot of work and may require specialized skills. That is why the > readers of a proposal cannot be expected to do it. > Moreover, the set of people currently with these skills is small and it would be helpful if this set grew in size. The Project Coin proposal form and other material was intended to give guidance on all that can be required as part of the task of growing the Java language so that more people can participate now and going forward. Discussions on the list provide a public, archived record of the proposals, their analysis, and decision making to better inform current and future discussions. Certainly merely sending an incomplete proposal to the list should in no way be expected to oblige others to undertake the hard task of analyzing and completing the work! -Joe From Ruslan at Shevchenko.Kiev.UA Wed Apr 15 23:27:08 2009 From: Ruslan at Shevchenko.Kiev.UA (Ruslan Shevchenko) Date: Thu, 16 Apr 2009 09:27:08 +0300 (EEST) Subject: scripts and results (was Helping to find the usefulness of a proposal) In-Reply-To: <49E5F020.7060508@gmx.de> References: <60287e9e1530b3e1ae49976316e8dc57.squirrel@wmail.gradsoft.ua> <49E5F020.7060508@gmx.de> Message-ID: <114ad93adfd2eb30f7ecd1388b69b1be.squirrel@wmail.gradsoft.ua> > Hi Ruslan, > > I would like to see the results for > > "objects and expressions in switch" > > which includes: > - string in switch > - instanceof switch > > I guess a very big chunk of all if-else if-structures would be covered by: > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html > Ok, I will alloc some time during next week-end for more patterns and statistics and will try include this one. This will some 'near' refinemed of proposal, becouse original proposal does not define what is 'leftPart' and 'rightPart' of Java expression in formal way [this is not so trivial, as expected. For example what left part will be in function expressions: 'this' or nothing ?. How we split chained expressions on left and right ?] For this reasons, I guess probability that this proposal will seen seriously is very low. (Second change which I plan: add statistics about relative number of chainged construction/number of all such constructions). > A n y C A P A C I T Y t o a d d t h i s p a t t e r n t o y > o u r s c r i p t ? ? > > As I argued before, I'm against the current syntax of the "string in > switch"-proposal, as it weakens switch..case semantics for identity, and > it encumbers later enhancements for the future. See: > http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html. > > - Ulf > > > > Am 07.04.2009 02:33, Ruslan Shevchenko schrieb: >> Good day, >> >> Few days ago Stephan give idea about writing simple script, which >> count amount of possible-optimizations of existing code. >> >> So, I wrote few checks for some of such entries. They count >> low bound of number of code patterns, which can be optimized with >> some of coin proposal and situated on distinct source lines. >> >> I'm afraid that information, which come from count of such code patterns >> can give incorrect direction: when we have such patterns in code, >> it's means that problem is not so big and we can easy live with one. >> Big language problems solved (or not) in non-trivial way, when we have >> no >> common (may be ugly) workaround. >> For example. in Java we rare will see BigDecimal.add() because it is >> not >> easy to work with BigDecimals, instead people work with double and have >> troubles >> with floating points rounding issues (see >> http://www.ddj.com/java/184405721)). >> Yet one example - choosing another language for implementing >> db-intensive >> parts of projects. >> >> Ok, you warned; data still can be interesting: >> >> Checked patterns was: >> string in switch >> instanceof switch >> byte literals >> multi catch >> loop by iterator, with call remove inside loop >> >> (if you want include other checks, you can add one at >> etc/checkers_coin.def or ask me [but without any warranty]) >> >> >> Exists one proposal, which I can't find on Joe blog: is change of >> variable >> subtype inside 'if instance' statement >> I. e. patterns look: >> if (x instanceof something) >> { >> something sx = (something)x; >> } >> And proposal tell type 'x' as 'something' inside dominate if block. >> Are anybody remember such proposal or it's was my fantasy ? >> >> >> Some results: >> >> For jetty6_11: (web server) >> byte literal : 52 >> elvis : 43 >> instanceof switch : 8 >> loop with remove : 0 >> multi catch : 22 >> string in switch : 19 >> Files:187 >> >> For gwt-user (google ajax library) >> byte literal : 2 >> elvis : 30 >> instanceof switch : 6 >> loop with remove : 5 >> multi catch : 9 >> string in switch : 10 >> Files:920 >> >> For openjdk-jdk part: (system library) >> byte literal : 1245 >> elvis : 725 >> instanceof switch : 252 >> loop with remove : 61 >> multi catch : 349 >> string in switch : 380 >> Files:7375 >> >> >> >> If you want to play with checks - most easy way is get special modified >> source >> distributive of JavaChecker, which I published as 2.5.0p0 and run it, >> i.e. >> (assuming you on Unix console) >> >> retrive distributive: >> >> wget >> http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerSourceInstaller-2.5.0p0.jar >> >> run installer: >> java -jar JavaCheckerSourceInstaller-2.5.0p0.jar >> (install one from UI) >> >> cd >> >> vi build-check-external.xml, look at few last tasks at end >> >> vi check-external.properties >> >> add own task and run one, as example: >> ant -f build-check-external.xml check-coin-openjdk >> >> Note, that speed of JavaChecker is far from ideal: openJDK-jdk >> processed near 50 minutes, so be patient ;) >> >> Hope, this information can be useful, as one (and not main) of sources. >> >> Regards ! >> >> >> >> >> > > From markmahieu at googlemail.com Wed Apr 15 23:40:43 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Thu, 16 Apr 2009 07:40:43 +0100 Subject: Some notes on Elvis and Other Null-Safe Operators In-Reply-To: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> References: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> Message-ID: <6BDB603A-7DCB-4621-9691-E31566265C32@googlemail.com> One more thought regarding Elvis and friends. In the code-base I'm currently working on, I keep seeing code like the following: Map> map = ... if (map != null) { Set fooSet = map.get(key); if (fooSet != null) { for (Foo foo : fooSet) { ... } } } which can be 'simplified' in a number of ways, for example with the liberal sprinkling of a couple of null-transforming methods: Set fooSet = emptyIfNull(map).get(key); for (Foo foo : emptyIfNull(fooSet)) { ... } Alternatively, with Elvis etc it could be written like this: for (Foo foo : map?.get(key) ?: Collections.emptySet()) { ... } Which doesn't seem like much of an improvement, to me. But I keep thinking that, in the context of this proposal, a null-safe form of the foreach loop might not be so bad: for (Foo foo :? map?.get(key)) { ... } I seem to recall that kind of example being talked about fairly extensively during JSR-201, but I think the discussion then was around whether foreach should be 'null-safe' by default. Perhaps it's an example of trying to fit the proposal to the use-case, though. Mark From paul.martin at gmail.com Thu Apr 16 01:35:20 2009 From: paul.martin at gmail.com (Paul Martin) Date: Thu, 16 Apr 2009 09:35:20 +0100 Subject: Helping to find the usefulness of a proposal In-Reply-To: <49E6C977.5080702@sun.com> References: <49E3ECFC.6000002@sun.com> <001485f6307408a1e304679fd349@google.com> <15e8b9d20904151733o32920606ve31c5ade09b6c4fd@mail.gmail.com> <49E6C977.5080702@sun.com> Message-ID: <4ce75f920904160135m66750f12ja9e85c134082c554@mail.gmail.com> Hi, Joe, Neal, and Reinier - many thanks for your replies. I think that I do understand the process much better now, and appreciate its goals. I had actually considered just asking the question about named parameters and/or just submitting a pre-proposal, which in hindsight would probably have been more useful (maybe I'll update the existing related bugs if necessary). In particular, I hadn't really considered the following idea, but can see that it is a valuable result of the process: > ... Discussions on the list provide a > public, archived record of the proposals, their analysis, and decision > making to better inform current and future discussions. Being able to see why changes were made and what was considered is definitely a good thing. Once again, thanks for your replies. Regards, Paul From brucechapman at paradise.net.nz Thu Apr 16 03:12:21 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Thu, 16 Apr 2009 22:12:21 +1200 Subject: PROPOSAL: Underscores in numbers In-Reply-To: <11482659.1238468832504.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> References: <11482659.1238468832504.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> Message-ID: <49E70485.5050100@paradise.net.nz> I am just doing some work (in kijaro) building prototype compiler for my integer literal proposals, and this proposal, and during testing found a wee bug in this spec. > long alsoMaxLong = 9_223_372_036_854_775_808L; that particular literal is only valid as the right hand side of a unary minus. The last digit should be changed to a '7'. Will post a link to the prototype in the next few days now that I have everything working. I still need to create something that is relatively easy to download and deploy. Bruce From reinier at zwitserloot.com Thu Apr 16 03:51:28 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 16 Apr 2009 12:51:28 +0200 Subject: Splitting the meat of a proposal from the trivial details. In-Reply-To: <49E6B58C.7020107@sun.com> References: <001485f6307408a1e304679fd349@google.com> <906692CA-71E0-4869-9591-076C05A15420@zwitserloot.com> <49E6B58C.7020107@sun.com> Message-ID: <059B6404-A031-4340-ADC8-92BDBFDB2719@zwitserloot.com> If Coin did effectively take 3 months, that's all the more reason to open up coin-dev for the complete 3 month timespan! By restricting discussion to the shortlist after a month and a week, a lot of interesting but not relevant chatter about proposals that definitely won't make the grade anyway can be weeded out. At times I felt the coin discussion turned needlessly specific for early stage proposals, and yet for other proposals, the idle banter on vague proposals was distracting from finalizing the details on something like ARM. --Reinier Zwitserloot On Apr 16, 2009, at 06:35, Joseph D. Darcy wrote: > Reinier Zwitserloot wrote: >> Actually, Joe has repeatedly turned down proposals because they >> were laughably incomplete, > > Quite so! > >> and Neal Gafter had gone through the trouble of writing up an >> example proposal before March 1st that showed most of the concerns >> that were nonetheless completely skipped in most proposals (such >> as definitive assignment rules). >> > > Part of my goal of sending in the strings in switch proposal (first > post!) was to demonstrate the sort of details that can come up even > in the simplest of changes. > >> However - I still mostly agree with your sentiment. The amount of >> work and detail required before a proposal was considered >> 'complete' was considerable, and yet the vast majority of >> proposals (even with the neccessary detail) were clearly going to >> be rejected (only 4 to 5, tops, that's been said many times). >> > > Yes, the limited size of the set of possible proposals was > established before the call for proposals started. > > However, the time required to write up even a fairly detailed > proposal, say 8 hours, pales in comparison to the possible effort > needed to fully implement a proposal. > > For example, implementing just the *single method* Class.isEnum > probably took around five hours of effort during JDK 5. While this > method is only two lines long, three tries were needed before > getting the right two lines; more detail on why this happened is > described in: > http://blogs.sun.com/darcy/entry/so_you_want_to_change > >> This provides a dilemma: Put in all that effort for not much to >> show for it? >> > > As I've stated before, Project Coin is a participatory process, > which means people have the opportunity to participate in the work > of a proposal too :-) > >> I felt that many (but not all) of the proposals essentially had >> enough detail in them to allow you to figure out if they were a >> good idea or not. If there had been another month, such a half- >> finished proposal could have been pointed out as 'would be on the >> shortlist, if only someone went through the effort of going >> through all the details, including writing down something like the >> definitive assignment rules. I think we'd have seen more useful >> discussion on proposals, and waste less time on trivialities, if >> it had been set up like that. >> > > While some iteration and refinement of proposals is fine and > expected, details are not trivialities. Seemingly small details can > make a difference and having some set of details available early > allows better decisions to be made. > >> For example, I was going to write up my plan to allow named >> parameters in method signatures, but in the end decided against >> it, because writing out the full JLS spec including chapter and >> verse would have been too much effort, compared to the tiny chance >> it would have been considered worthy for coin. If, however, there >> was a separate pre- proposal phase, I could have easily written up >> the gist of the proposal, many examples, and ample support that my >> proposal would be backwards and migration compatible, would not >> lead to much confusion, and would not be amiguous. If, then, the >> proposal would be accepted as 'likely good for java, -if- fully >> specced and no surprises turn up', I'd gladly have taken the time >> to write it out in excruciating detail, and cook up a prototype. >> >> >> This Project Coin was pressed for time, so much more than a month >> just wasn't on the table, but for next time, I suggest smearing >> out coin across 3 months: >> > > The future existence of what would be known of Project Coin was > announced on December 8, 2008 (http://blogs.sun.com/darcy/entry/small_language_changes_jdk_7 > ). This included an overview of the coming call for proposals and a > link to "So you want to change the Java Programming Language...", > whose content served as the skeleton for the later proposal form. > The proposal form was published in January 27, 2009 (http://blogs.sun.com/darcy/entry/project_coin > ) and the mailing list started a month later, February 27, 2009. > > So there was a three month period before the call for proposals > officially got underway, and a month after the form was published > but before a proposal could be submitted, where interested parties > could think about proposal ideas and possibly implement them, guided > by the published criteria for the effort. > > There were a few inquiries to the list to ask for help drafting a > proposal and some "pre-proposals" sent in to get a reading on > whether a proposal topic would be smiled upon, both of which are > good, on-topic uses of the list! However, after my unfavorable > assessment of the "Source and Encoding keyword" pre-proposal (http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000298.html > ) was sent to the list, people choose to continue the discussion for > a time. Some continued discussion is fine, but people who send in > proposals or pre-proposals don't to tend to give up right away ;-) > To reiterate terms of roles and responsibilities here, > > "Especially with the maturity of the Java platform, the onus is on > the proposer to convince that a language change should go in; the > onus is not to prove the change should stay out." > http://blogs.sun.com/darcy/entry/criteria_for_desirable_small_language > December 23, 2008 > > Having thought through the details is one way to be more convincing. > > -Joe > From scolebourne at joda.org Sat Apr 18 03:33:31 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Sat, 18 Apr 2009 11:33:31 +0100 Subject: Some notes on Elvis and Other Null-Safe Operators In-Reply-To: <6BDB603A-7DCB-4621-9691-E31566265C32@googlemail.com> References: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> <6BDB603A-7DCB-4621-9691-E31566265C32@googlemail.com> Message-ID: <49E9AC7B.3010509@joda.org> Mark Mahieu wrote: > Which doesn't seem like much of an improvement, to me. But I keep > thinking that, in the context of this proposal, a null-safe form of > the foreach loop might not be so bad: > > for (Foo foo :? map?.get(key)) { > ... > } I certainly think thats an interesting idea. However, having a null list is something that rarely comes up in the code I write. I think thats because I always return an empty list from methods and never null (something that is definitely good practice). Where the null-safe operators come in is in handling object model structure such as a bean holding an optional value (String/Integer/Date etcc), or a bean holding another optional bean (person holding optional spouse). In these cases, holding null to represent the absence of data is a valid design choice. Stephen From markmahieu at googlemail.com Sat Apr 18 12:17:07 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Sat, 18 Apr 2009 20:17:07 +0100 Subject: Some notes on Elvis and Other Null-Safe Operators In-Reply-To: <49E9AC7B.3010509@joda.org> References: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> <6BDB603A-7DCB-4621-9691-E31566265C32@googlemail.com> <49E9AC7B.3010509@joda.org> Message-ID: <7ED41D61-84A5-4149-82F1-D39333038C21@googlemail.com> On 18 Apr 2009, at 11:33, Stephen Colebourne wrote: > Mark Mahieu wrote: >> Which doesn't seem like much of an improvement, to me. But I keep >> thinking that, in the context of this proposal, a null-safe form of >> the foreach loop might not be so bad: >> >> for (Foo foo :? map?.get(key)) { >> ... >> } > > I certainly think thats an interesting idea. > > However, having a null list is something that rarely comes up in the > code I write. I think thats because I always return an empty list from > methods and never null (something that is definitely good practice). Yes, if I were writing the code I mentioned I would also consider using different data structures entirely, such as: http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/ common/collect/Multimap.html That's not always an option though. It would certainly be a fairly substantial change in my example. Mark From bugeaud at gmail.com Sat Apr 18 15:15:42 2009 From: bugeaud at gmail.com (Jean-Baptiste Bugeaud) Date: Sun, 19 Apr 2009 00:15:42 +0200 Subject: SUBMISSION : A second look on "named parameters" Message-ID: <2dc3bd00904181515o2df0a1d3n3cf5ddd75d58d4ff@mail.gmail.com> Hi everybody, Here is an late submission, sorry I missed the initial deadline. If you think (as I do) that this is a key small change for lots of improvement, maybe there is still a very small gap to go for JDK7;-) A proposition including the same goal was introduced in JDK6 JSR but withdawn in final version. So legacy impact, issues ... should be already well known by the JDK core team. This second look has tried to solve all the problems. Let's go .... Author(s): Jean-Baptiste BUGEAUD, Paris, France OVERVIEW : FEATURE SUMMARY : Introduce named parameter on methods into the language MAJOR ADVANTAGE : Integration with the legacy, fully backward compatible. Clear paradigm separation. MAJOR BENEFIT : Consistent way of naming the parameter help to unify existing APIs, remove boiler plate core thus simplify object marshaling and reflection usage (WS, JMX, EJB ...). MAJOR DISADVANTAGE : Semantic of static keyword on parameter might not be clear for beginers ALTERNATIVES : Usage of existing bytecode handling lib can expose the parameter names already, but this leads to dependency [5][6] and potential security issues. Usage of APT[7] to store parameter names constraint to a prequirement : apply it to all the code you target. This is unlikely to happen for JARS you have not created, thus reducing the potential benefits. EXAMPLE SIMPLE EXAMPLE : (1a) : class OrderManager{ public void order(String product, int amount){ // do the login } } (1b) class OrderManager{ public void order(static String product, static int amount){ // do the login } } (2a) void displayOrderCriteria(){ Method[] methods = OrderManager.class.getMedthods(); for (Method m : methods){ System.out.println("To call :"+m); for(String n : m.getParameterNames[]){ System.out.println("\tYou must provide :"+n); } } } (2b) void displayOrderCriteria(){ Method[] methods = OrderManager.class.getMedthods(); for (Method m : methods){ System.out.println("To call :"+m); for(String n : m.getStaticParameterNames[]){ System.out.println("\tYou must provide :"+n); } } } ADVANCED EXAMPLE : (3.1) package java.lang.annotation @Documented @Retention(value = RetentionPolicy.SOURCE) @Target( { ElementType.METHOD, ElementType.ANNOTATION_TYPE }) public @interface StaticParameterNames { }; (3.2) @Retention(value = RetentionPolicy.RUNTIME) @Target( { ElementType.METHOD }) @Inside(WebService.class) @ValidWebOperation @StaticParameterNames public @interface WebMethod { String operationName() default ""; String action() default ""; }; (3.3) @WebService class LoginManager{ @WebMethod public void doLogin(String user, char[] password){ // simply log the user } } DETAILS SPECIFICATION : Historicaly, method's parameter names can be stored in the Java bytecode using appropriate compiler switch [2]. Although, no standard API is available to benefit from them they aready. But when compiler optimisation is set or an obfuscater is enabled, then are no more available. This is not reliable. Such inconsistency, along with some other problems, have prevented the inclusion for JDK6 of previous proposition [3][4]. This proposition of small language change, introduce named parameter on methods into the language thru the add of a new language paradigm : static named parameter. At source level, this new kind of parameter is simply a regular parameter with the modifier static set on it. As a summary, we will get two kind of parameters in the language : - regular named parameter (see method on (1a)) : the legacy, we "keep the good-old way", parameter might be stored in bytecode depending on compiler option, no change on language/semantic/compilation - static named parameter (see method on (1b)) : a regular named parameter with a static modifier added, whatever happens (compiler option, obfuscator, etc) parameter name will always be kept at bytecode level. At Java API level, on java.lang.reflec.Method, two new method will help API implementer to leverage both kind of parameters. - String[] getParameterNames() - String[] getParameterStaticNames() IDE would be most interrested into calling the first one. But API implementer (such as JAXWS for instance) requiring a consistent behavior could rely on the second. But they could downgrade on the first one for legacy JAR if they wish so. Introduction of an annotation StaticParameterNames could also be leverage by API implementer to include automatic parameter name storage. This one alone will ease lots of library code. For instance, in JAXWS (see example 3.3), WebParam are now optional to get a web service working : WebMethod would be enough as long as JAXWS implementer apply StaticParameterNames on the WebMethod annotation (see example 3.2). COMPILATION : Static named parameters are compiled the same way of regular named ones but with addition of the static modifier set on the reference at the bytecode level and the parameter name parameter kept in the table. No compiler/optimizer/obfuscator should remove/change the parameter names at bytecode level on a static named parameter. Thus, at a higher level, although not taking part of the method signature (and call resolution), the static named parameter could now be seen as part of the method contract: changing a static named parameter's name could have the same impact as renaming a method. This is the developper resposability to analyze impact of such a change. If a method is tagged with the annotation (or an inherited annotation) StaticParameterNames, all its method parameter should be compiled as if they were static named parameters. TESTING : Compile test classes (such as examples 1a & 1b) using compiler with the feature enable with and without optimization enable (the one that remove the parameter names on regular named parameters). For each scenario (with & without optimization) : Call the reflection API for listing regular named parameters, and check according to the names that should be returned as per the test class. Call the reflection API for listing static named parameters, and check according to the names that should be returned as per the test class. LIBRARY SUPPORT : Two methods must be added to java.lang.relfect.Method : String[] getParameterNames() List the parameter names as existing in the bytecode. No guaranty of reliability is made : can be renamed, removed, added, ... Array is of the same size of getParameterTypes(), for a given index, if the corresponding name is not found a null value is returned. String[] getParameterStaticNames() List the static parameter names as existing in the bytecode. Those named are reliable. Any change impact the contract. Array is of the same size of getParameterTypes(), for a given index, if the corresponding parameter is not tagged with static modifier, a null value is returned. StaticParameterNames (see example 3.1) annotation must be introduced to indicate to the compiler all parameters of a tagged method are meant to be static nammed parameters although not tagged with the static modifier. This anotation can tag other annotation. OTHER CHANGES: Any existing API willing to benefit from this feature, could inherit from StaticParameterNames but this is out of scope of this proposal. COMPATIBILITY MIGRATION : Manual migration is done adding static modifier on parameters. Automatic migration could be done by APIs leader using the StaticParameterNames annotation, thus all the existing code base would be migrated at the next build automatically. COMPATIBILITY : BREAKING CHANGES: no, this is the reason of using static modifier. EXISTING PROGRAMS: code using legacy class can benefit from the getParameterNames(). But getParameterStaticNames() will always return an array of null values. REFERENCES EXISTING BUGS http://bugs.sun.com/view_bug.do?bug_id=6444738 URL FOR PROTOTYPE None at this time. Early feasibility check in the native VM coden plus pure Java code is feasible [5]. [1] http://paulhammant.com/blog/parameter-names-for-java6-question.html [2] http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javac.html [3] http://weblogs.java.net/blog/mreinhold/archive/2005/12/mustang_release.html [4] http://blogs.sun.com/mr/entry/java_se_6_public_review [5] http://paranamer.codehaus.org/ [6] http://www.jroller.com/eu/entry/using_asm_to_read_mathod [7] http://weblogs.java.net/blog/emcmanus/archive/2006/06/using_annotatio.html From reinier at zwitserloot.com Sat Apr 18 17:14:16 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Sun, 19 Apr 2009 02:14:16 +0200 Subject: SUBMISSION : A second look on "named parameters" In-Reply-To: <2dc3bd00904181515o2df0a1d3n3cf5ddd75d58d4ff@mail.gmail.com> References: <2dc3bd00904181515o2df0a1d3n3cf5ddd75d58d4ff@mail.gmail.com> Message-ID: <79191A56-6622-4AFE-A999-02280E1A9CD0@zwitserloot.com> Your proposal is very incomplete. Three major nits: A. Did I miss something, or did you totally forget to include an example of calling a method with named parameters? Something like: doLogin(user: "foobar", password: new char[] { 'a', 'b', 'c' }); B. Why static? You might as well have picked 'strictfp' - it's a total non-sequitur choice. Re-use of existing keywords is not really a panacea; it waters down the anchoring ability of a keyword to virtually nothing. I'm not sure if context-sensitive keywords are any better, but java7 is already going to have at least one ('module'), so don't beat around the bush and just call it 'named'). Could be just me, but introducing a change which is not backwards compatible IF you have a type that's called 'named' (written just like that, all-lower case), is not something I find troublesome in the least. That's very ugly code, and a migration tool can fix this easily. C. You don't mention having default values for parameters, which is sort of the point of this exercise (otherwise you really still need builders ; any method that has so many parameters that they need names probably needs a builder, and without defaults, not providing one and instead relying on named params is just an inferior bandaid to your ugly API; to get it right you STILL need to provide a builder. If, however, parameters can have defaults, then you no longer need to make builders at all). I suggest you look over the coin-dev mailing list; I entered a rough sketch of a named parameters proposal near the end of coin. I never wrote it up because I thought of it far too close to the deadline, and it's still of such high impact that I doubt it would pass muster for coin. --Reinier Zwitserloot On Apr 19, 2009, at 00:15, Jean-Baptiste Bugeaud wrote: > Hi everybody, > > Here is an late submission, sorry I missed the initial deadline. If > you think (as I do) that this is a key small change for lots of > improvement, maybe there is still a very small gap to go for JDK7;-) > > A proposition including the same goal was introduced in JDK6 JSR but > withdawn in final version. So legacy impact, issues ... should be > already well known by the JDK core team. This second look has tried to > solve all the problems. > > Let's go .... > > Author(s): Jean-Baptiste BUGEAUD, Paris, France > > OVERVIEW : > FEATURE SUMMARY : Introduce named parameter on methods into the > language > MAJOR ADVANTAGE : Integration with the legacy, fully backward > compatible. Clear paradigm separation. > MAJOR BENEFIT : Consistent way of naming the parameter help to unify > existing APIs, remove boiler plate core thus simplify object > marshaling and reflection usage (WS, JMX, EJB ...). > MAJOR DISADVANTAGE : Semantic of static keyword on parameter might > not be clear for beginers > ALTERNATIVES : Usage of existing bytecode handling lib can expose > the parameter names already, but this leads to dependency [5][6] and > potential security issues. Usage of APT[7] to store parameter names > constraint to a prequirement : apply it to all the code you target. > This is unlikely to happen for JARS you have not created, thus > reducing the potential benefits. > > EXAMPLE > > SIMPLE EXAMPLE : > > (1a) : > > class OrderManager{ > public void order(String product, int amount){ > // do the login > } > } > > (1b) > > class OrderManager{ > public void order(static String product, static int amount){ > // do the login > } > } > > (2a) > void displayOrderCriteria(){ > Method[] methods = OrderManager.class.getMedthods(); > for (Method m : methods){ > System.out.println("To call :"+m); > for(String n : m.getParameterNames[]){ > System.out.println("\tYou must provide :"+n); > } > } > } > > (2b) > void displayOrderCriteria(){ > Method[] methods = OrderManager.class.getMedthods(); > for (Method m : methods){ > System.out.println("To call :"+m); > for(String n : m.getStaticParameterNames[]){ > System.out.println("\tYou must provide :"+n); > } > } > } > > ADVANCED EXAMPLE : > > (3.1) > package java.lang.annotation > > @Documented > @Retention(value = RetentionPolicy.SOURCE) > @Target( { ElementType.METHOD, ElementType.ANNOTATION_TYPE }) > public @interface StaticParameterNames { > }; > > (3.2) > > @Retention(value = RetentionPolicy.RUNTIME) > @Target( { ElementType.METHOD }) > @Inside(WebService.class) > @ValidWebOperation > @StaticParameterNames > public @interface WebMethod { > String operationName() default ""; > String action() default ""; > }; > > > (3.3) > > @WebService > class LoginManager{ > @WebMethod public void doLogin(String user, char[] password){ > // simply log the user > } > } > > DETAILS > > SPECIFICATION : > > Historicaly, method's parameter names can be stored in the Java > bytecode using appropriate compiler switch [2]. Although, no standard > API is available to benefit from them they aready. But when compiler > optimisation is set or an obfuscater is enabled, then are no more > available. This is not reliable. > > Such inconsistency, along with some other problems, have prevented the > inclusion for JDK6 of previous proposition [3][4]. > > This proposition of small language change, introduce named parameter > on methods into the language thru the add of a new language paradigm : > static named parameter. At source level, this new kind of parameter is > simply a regular parameter with the modifier static set on it. > > As a summary, we will get two kind of parameters in the language : > - regular named parameter (see method on (1a)) : the legacy, we "keep > the good-old way", parameter might be stored in bytecode depending on > compiler option, no change on language/semantic/compilation > - static named parameter (see method on (1b)) : a regular named > parameter with a static modifier added, whatever happens (compiler > option, obfuscator, etc) parameter name will always be kept at > bytecode level. > > At Java API level, on java.lang.reflec.Method, two new method will > help API implementer to leverage both kind of parameters. > - String[] getParameterNames() > - String[] getParameterStaticNames() > > IDE would be most interrested into calling the first one. But API > implementer (such as JAXWS for instance) requiring a consistent > behavior could rely on the second. But they could downgrade on the > first one for legacy JAR if they wish so. > > Introduction of an annotation StaticParameterNames could also be > leverage by API implementer to include automatic parameter name > storage. This one alone will ease lots of library code. For instance, > in JAXWS (see example 3.3), WebParam are now optional to get a web > service working : WebMethod would be enough as long as JAXWS > implementer apply StaticParameterNames on the WebMethod annotation > (see example 3.2). > > COMPILATION : > > Static named parameters are compiled the same way of regular named > ones but with addition of the static modifier set on the reference at > the bytecode level and the parameter name parameter kept in the table. > No compiler/optimizer/obfuscator should remove/change the parameter > names at bytecode level on a static named parameter. > > Thus, at a higher level, although not taking part of the method > signature (and call resolution), the static named parameter could now > be seen as part of the method contract: changing a static named > parameter's name could have the same impact as renaming a method. This > is the developper resposability to analyze impact of such a change. > > If a method is tagged with the annotation (or an inherited annotation) > StaticParameterNames, all its method parameter should be compiled as > if they were static named parameters. > > TESTING : > > Compile test classes (such as examples 1a & 1b) using compiler with > the feature enable with and without optimization enable (the one that > remove the parameter names on regular named parameters). > > For each scenario (with & without optimization) : > Call the reflection API for listing regular named parameters, and > check according to the names that should be returned as per the test > class. > Call the reflection API for listing static named parameters, and check > according to the names that should be returned as per the test class. > > LIBRARY SUPPORT : > > Two methods must be added to java.lang.relfect.Method : > > String[] getParameterNames() > > List the parameter names as existing in the bytecode. No guaranty of > reliability is made : can be renamed, removed, added, ... > Array is of the same size of getParameterTypes(), for a given index, > if the corresponding name is not found a null value is returned. > > String[] getParameterStaticNames() > > List the static parameter names as existing in the bytecode. Those > named are reliable. Any change impact the contract. > Array is of the same size of getParameterTypes(), for a given index, > if the corresponding parameter is not tagged with static modifier, a > null value is returned. > > > StaticParameterNames (see example 3.1) annotation must be introduced > to indicate to the compiler all parameters of a tagged method are > meant to be static nammed parameters although not tagged with the > static modifier. This anotation can tag other annotation. > > > OTHER CHANGES: > > Any existing API willing to benefit from this feature, could inherit > from StaticParameterNames but this is out of scope of this proposal. > > COMPATIBILITY > > MIGRATION : > Manual migration is done adding static modifier on parameters. > Automatic migration could be done by APIs leader using the > StaticParameterNames annotation, thus all the existing code base would > be migrated at the next build automatically. > > > COMPATIBILITY : > > BREAKING CHANGES: no, this is the reason of using static modifier. > EXISTING PROGRAMS: code using legacy class can benefit from the > getParameterNames(). But getParameterStaticNames() will always return > an array of null values. > > > REFERENCES > > EXISTING BUGS > > http://bugs.sun.com/view_bug.do?bug_id=6444738 > > URL FOR PROTOTYPE > > None at this time. Early feasibility check in the native VM coden plus > pure Java code is feasible [5]. > > > [1] http://paulhammant.com/blog/parameter-names-for-java6- > question.html > [2] http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javac.html > [3] http://weblogs.java.net/blog/mreinhold/archive/2005/12/mustang_release.html > [4] http://blogs.sun.com/mr/entry/java_se_6_public_review > [5] http://paranamer.codehaus.org/ > [6] http://www.jroller.com/eu/entry/using_asm_to_read_mathod > [7] http://weblogs.java.net/blog/emcmanus/archive/2006/06/using_annotatio.html > From Joe.Darcy at Sun.COM Sat Apr 18 17:20:41 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Sat, 18 Apr 2009 17:20:41 -0700 Subject: SUBMISSION : A second look on "named parameters" In-Reply-To: <2dc3bd00904181515o2df0a1d3n3cf5ddd75d58d4ff@mail.gmail.com> References: <2dc3bd00904181515o2df0a1d3n3cf5ddd75d58d4ff@mail.gmail.com> Message-ID: <49EA6E59.3080700@sun.com> Yes, we are well aware of the desire for named parameters from some quarters and the list received some related proposals. This late submission will not be considered. Regards, -Joe Jean-Baptiste Bugeaud wrote: > Hi everybody, > > Here is an late submission, sorry I missed the initial deadline. If > you think (as I do) that this is a key small change for lots of > improvement, maybe there is still a very small gap to go for JDK7;-) > > A proposition including the same goal was introduced in JDK6 JSR but > withdawn in final version. So legacy impact, issues ... should be > already well known by the JDK core team. This second look has tried to > solve all the problems. > > Let's go .... > > Author(s): Jean-Baptiste BUGEAUD, Paris, France > > OVERVIEW : > FEATURE SUMMARY : Introduce named parameter on methods into the language > MAJOR ADVANTAGE : Integration with the legacy, fully backward > compatible. Clear paradigm separation. > MAJOR BENEFIT : Consistent way of naming the parameter help to unify > existing APIs, remove boiler plate core thus simplify object > marshaling and reflection usage (WS, JMX, EJB ...). > MAJOR DISADVANTAGE : Semantic of static keyword on parameter might > not be clear for beginers > ALTERNATIVES : Usage of existing bytecode handling lib can expose > the parameter names already, but this leads to dependency [5][6] and > potential security issues. Usage of APT[7] to store parameter names > constraint to a prequirement : apply it to all the code you target. > This is unlikely to happen for JARS you have not created, thus > reducing the potential benefits. > > EXAMPLE > > SIMPLE EXAMPLE : > > (1a) : > > class OrderManager{ > public void order(String product, int amount){ > // do the login > } > } > > (1b) > > class OrderManager{ > public void order(static String product, static int amount){ > // do the login > } > } > > (2a) > void displayOrderCriteria(){ > Method[] methods = OrderManager.class.getMedthods(); > for (Method m : methods){ > System.out.println("To call :"+m); > for(String n : m.getParameterNames[]){ > System.out.println("\tYou must provide :"+n); > } > } > } > > (2b) > void displayOrderCriteria(){ > Method[] methods = OrderManager.class.getMedthods(); > for (Method m : methods){ > System.out.println("To call :"+m); > for(String n : m.getStaticParameterNames[]){ > System.out.println("\tYou must provide :"+n); > } > } > } > > ADVANCED EXAMPLE : > > (3.1) > package java.lang.annotation > > @Documented > @Retention(value = RetentionPolicy.SOURCE) > @Target( { ElementType.METHOD, ElementType.ANNOTATION_TYPE }) > public @interface StaticParameterNames { > }; > > (3.2) > > @Retention(value = RetentionPolicy.RUNTIME) > @Target( { ElementType.METHOD }) > @Inside(WebService.class) > @ValidWebOperation > @StaticParameterNames > public @interface WebMethod { > String operationName() default ""; > String action() default ""; > }; > > > (3.3) > > @WebService > class LoginManager{ > @WebMethod public void doLogin(String user, char[] password){ > // simply log the user > } > } > > DETAILS > > SPECIFICATION : > > Historicaly, method's parameter names can be stored in the Java > bytecode using appropriate compiler switch [2]. Although, no standard > API is available to benefit from them they aready. But when compiler > optimisation is set or an obfuscater is enabled, then are no more > available. This is not reliable. > > Such inconsistency, along with some other problems, have prevented the > inclusion for JDK6 of previous proposition [3][4]. > > This proposition of small language change, introduce named parameter > on methods into the language thru the add of a new language paradigm : > static named parameter. At source level, this new kind of parameter is > simply a regular parameter with the modifier static set on it. > > As a summary, we will get two kind of parameters in the language : > - regular named parameter (see method on (1a)) : the legacy, we "keep > the good-old way", parameter might be stored in bytecode depending on > compiler option, no change on language/semantic/compilation > - static named parameter (see method on (1b)) : a regular named > parameter with a static modifier added, whatever happens (compiler > option, obfuscator, etc) parameter name will always be kept at > bytecode level. > > At Java API level, on java.lang.reflec.Method, two new method will > help API implementer to leverage both kind of parameters. > - String[] getParameterNames() > - String[] getParameterStaticNames() > > IDE would be most interrested into calling the first one. But API > implementer (such as JAXWS for instance) requiring a consistent > behavior could rely on the second. But they could downgrade on the > first one for legacy JAR if they wish so. > > Introduction of an annotation StaticParameterNames could also be > leverage by API implementer to include automatic parameter name > storage. This one alone will ease lots of library code. For instance, > in JAXWS (see example 3.3), WebParam are now optional to get a web > service working : WebMethod would be enough as long as JAXWS > implementer apply StaticParameterNames on the WebMethod annotation > (see example 3.2). > > COMPILATION : > > Static named parameters are compiled the same way of regular named > ones but with addition of the static modifier set on the reference at > the bytecode level and the parameter name parameter kept in the table. > No compiler/optimizer/obfuscator should remove/change the parameter > names at bytecode level on a static named parameter. > > Thus, at a higher level, although not taking part of the method > signature (and call resolution), the static named parameter could now > be seen as part of the method contract: changing a static named > parameter's name could have the same impact as renaming a method. This > is the developper resposability to analyze impact of such a change. > > If a method is tagged with the annotation (or an inherited annotation) > StaticParameterNames, all its method parameter should be compiled as > if they were static named parameters. > > TESTING : > > Compile test classes (such as examples 1a & 1b) using compiler with > the feature enable with and without optimization enable (the one that > remove the parameter names on regular named parameters). > > For each scenario (with & without optimization) : > Call the reflection API for listing regular named parameters, and > check according to the names that should be returned as per the test > class. > Call the reflection API for listing static named parameters, and check > according to the names that should be returned as per the test class. > > LIBRARY SUPPORT : > > Two methods must be added to java.lang.relfect.Method : > > String[] getParameterNames() > > List the parameter names as existing in the bytecode. No guaranty of > reliability is made : can be renamed, removed, added, ... > Array is of the same size of getParameterTypes(), for a given index, > if the corresponding name is not found a null value is returned. > > String[] getParameterStaticNames() > > List the static parameter names as existing in the bytecode. Those > named are reliable. Any change impact the contract. > Array is of the same size of getParameterTypes(), for a given index, > if the corresponding parameter is not tagged with static modifier, a > null value is returned. > > > StaticParameterNames (see example 3.1) annotation must be introduced > to indicate to the compiler all parameters of a tagged method are > meant to be static nammed parameters although not tagged with the > static modifier. This anotation can tag other annotation. > > > OTHER CHANGES: > > Any existing API willing to benefit from this feature, could inherit > from StaticParameterNames but this is out of scope of this proposal. > > COMPATIBILITY > > MIGRATION : > Manual migration is done adding static modifier on parameters. > Automatic migration could be done by APIs leader using the > StaticParameterNames annotation, thus all the existing code base would > be migrated at the next build automatically. > > > COMPATIBILITY : > > BREAKING CHANGES: no, this is the reason of using static modifier. > EXISTING PROGRAMS: code using legacy class can benefit from the > getParameterNames(). But getParameterStaticNames() will always return > an array of null values. > > > REFERENCES > > EXISTING BUGS > > http://bugs.sun.com/view_bug.do?bug_id=6444738 > > URL FOR PROTOTYPE > > None at this time. Early feasibility check in the native VM coden plus > pure Java code is feasible [5]. > > > [1] http://paulhammant.com/blog/parameter-names-for-java6-question.html > [2] http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javac.html > [3] http://weblogs.java.net/blog/mreinhold/archive/2005/12/mustang_release.html > [4] http://blogs.sun.com/mr/entry/java_se_6_public_review > [5] http://paranamer.codehaus.org/ > [6] http://www.jroller.com/eu/entry/using_asm_to_read_mathod > [7] http://weblogs.java.net/blog/emcmanus/archive/2006/06/using_annotatio.html > > From jjb at google.com Sun Apr 19 23:45:15 2009 From: jjb at google.com (Joshua Bloch) Date: Sun, 19 Apr 2009 23:45:15 -0700 Subject: Automatic Resource Management, V.2 Message-ID: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> Fellow Coiners, Thanks for all your feedback on the Automatic Resource Management proposal. I have revised the proposal in light of these comments. The new version (V.2) can be seen at this URL: http://docs.google.com/Doc?id=ddv8ts74_3fs7483dp . It is included below for archival purposes. Josh Automatic Resource Management (V.2) *AUTHOR: *Joshua Bloch *OVERVIEW* FEATURE SUMMARY: A *resource* is as an object that must be closed manually, such as a java.io.InputStream, OutputStream, Reader, Writer, Formatter; java.nio.Channel; java.net.socket; java.sql.Connection, Statement, ResultSet, or java.awt.Graphics. The *automatic resource management statement* is a form of the try statement that declares one or more resources. The scope of these resource declarations is limited to the statement. When the statement completes, whether normally or abruptly, all of its resources are closed automatically. MAJOR ADVANTAGE: The automatic resource management statement obviates the need for manual resource termination, which has proven ugly and error prone. Even good programmers get it wrong most of the time. For example, Sun?s guide to Persistent Connections (http://tinyurl.com/6b5jc7) gets it wrong in code that claims to be exemplary. Likewise, the solution on page 88 of Bloch and Gafter?s *Java Puzzlers* (Addison-Wesley, 2006) is badly broken, and no one ever noticed. In fact, 2/3 of the uses of the close method in the JDK itself are wrong! The price for failing to terminate resources properly is resource leaks or even outright failures, which may be silent (as in *Java Puzzlers*). Even the ?correct? idioms for manual resource management are deficient: if an exception is thrown in the try block, and another when closing the resource in the finally block, the second exception supplants the first, making it difficult to determine the real cause of the trouble. In other words, by responsibly closing your resource even during some catastrophic event, you can actually erase all record of the event, resulting in many wasted hours of debugging. While it is possible to write code to suppress the second exception in favor of the first, virtually no one does, as it is just too verbose. This is not a theoretical problem; it has greatly complicated the debugging of large systems. A secondary advantage of the automatic resource management construct is that it can suppress the uninteresting (second) exception in favor of the interesting (first) one with no effort on the part of the programmer, and no loss in the clarity of the program. Like the for-each statement (introduced in Java 1.5), the automatic resource management statement is a small piece of syntactic sugar with a very high power-to-weight ratio. MAJOR DISADVANTAGE: Like all syntactic sugar, this construct removes a bit of Java?s ?what you see is what you get? character (?transparency?). Another disadvantage is increased coupling between the language specification and libraries. ALTERNATIVES: The benefits of this proposal cannot be had without a language change. Absent a language change, you must close resources manually. That is why Java?s competitors have automatic resource management constructs (C# has using blocks and C++ has destructors). *NONTRIVIAL CHANGES IN THIS VERSION* 1. Renamed interface Disposable to AutoCloseable and moved it from package java.lang to java.lang.auto. 2. Enhanced statement to allow expressions in place of declarations to designate resources. 3. Added support for retention of suppressed exceptions. 4. Added list of types to be retrofitted. 5. Added design FAQ with additional examples. *EXAMPLES* SIMPLE EXAMPLE: Here is a static method to read the first line of a file, demonstrating the minimal (nearly) correct code to release a single resource today. static String readFirstLineFromFile(String path) throws IOException { BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); } finally { br.close(); } } Unfortunately, if the readLine and close invocations both throw exceptions, the latter exception supplants the former. The only practical way around this today would to be to ignore any exception thrown by the close invocation. While this might be reasonable in the case of a Reader or InputStream, it would be disastrous for a Writer or OutputStream. Here?s how it would look with an automatic resource management statement: static String readFirstLineFromFile2(String path) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(path)) { return br.readLine(); } } ADVANCED EXAMPLES*:* Here is a static method to make a copy of a file, demonstrating the minimal correct code to release two resources today: static void copy(String src, String dest) throws IOException { InputStream in = new FileInputStream(src); try { OutputStream out = new FileOutputStream(dest); try { byte[] buf = new byte[8 * 1024]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); } finally { out.close(); } } finally { in.close(); } } Here?s how it would look with an automatic resource management statement: static void copy(String src, String dest) throws IOException { try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest)) { byte[] buf = new byte[8192]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); } } *DETAILS* * * SPECIFICATION: What follows is not intended to be a formal JLS-quality specification. It emphasizes brevity and clarity over thoroughness. SYNTAX: The production for *TryStatement* in JLS ?14.20 would be extended with this alternative: *TryStatement*: try ( *ResourceSpecifications* ) *Block Catchesopt Finallyopt* *Resource**Specifications*: *Resource**Specification* *Resource**Specification *; *Resource**Specifications* *Resource**Specification**:* * **LocalVariableDeclaration* * Expression* * * The type of each *LocalVariableDeclaration* or *Expression *in a * ResourceDeclarations *must be a subtype of AutoCloseable. Such types are known as *resource types*. SEMANTICS and COMPILATION: An automatic resource management statement with a single local variable declaration and no *Finally* or *Catches* would behave as if replaced by the following source code: { final *LocalVariableDeclaration* ; try *Block* finally { *localVar*.close(); // *localVar* is the variable declared in * LocalVariableDeclaration* } } An automatic resource management statement with a single resource expression and no *Finally* or *Catches* would behave as if replaced by the following source code: { final *T**ype* #localVar = *Expression*; try *Block* finally { #*localVar*.close(); } } The variable #localVar is a compiler-generated identifier distinct from any other identifiers (compiler-generated or otherwise) that are in scope (JLS ?6.3) at the point where the automatic resource management statement occurs. The *Type *in the above desugaring is replaced by the static type of * Expression*. An automatic resource management statement with multiple resource specifications (declarations or expressions) and no *Finally* or *Catches* would behave as if (recursively) replaced by the following source code: { final *LocalVariableDeclaration* ; // First variable declaration try( *ResourceDeclarations* ) *Block* finally { // Remaining resource declarations *localVar*.close(); // *localVar* is the variable declared in * LocalVariableDeclaration* } } When you initially desugar an automatic resource management statement with n resource specifications for n > 1, you get an automatic resource management statement with n-1 resource declarations. After n such replacements, you have n nested try-finally statements, and the desugaring is complete. A single declaration that declares multiple resources is treated as if it were multiple declarations, each declaring a single resource. Note that resource declarations are implicitly final. For consistency with existing constructs with implicit modifiers, it is legal (though discouraged) for the programmer to provide an explicit final modifier. Note that the close method is only called on resources whose declarations (or expressions) execute without throwing an exception, and that the first such exception causes the statement to complete abruptly. An automatic resource management statement with a *Finally* or *Catches* would behave as if replaced by the following code (which contains an automatic resource management statement with no *Finally* or *Catches that must be expanded as per the desugaring above*). Note that resources are closed before any explicit finally or catch clauses have executed, and that resource variable declarations are not in scope in explicit finally and catch clauses: try { try ( *ResourceDeclarations* ) *Block* }* Catchesopt Finallyopt* The above desugarings are simplified for pedagogical purposes. They solve most of the problems described above but one problem remains: if the *Block* throws one exception, and the automatically generated close invocation throws another, the latter exception supplants the former. This shortcoming is corrected by using a slightly more complex desugaring for the single-local-variable-declaration forms of the construct. In this desugaring, an exception thrown during the lifetime of a resource (the * Block*) receives priority over an exception thrown by an automatically generated close invocation. Such a *suppressed exception* is not discarded, but is associated with the *primary exception *(the one thrown from the * Block*), and can be extracted using Throwable's getSuppressedExceptions method. The following desugaring should be regarded as definitive (though the compiler is free to emit any object code that obeys its semantics): { final *LocalVariableDeclaration* ; // Or final *T**ype* #localVar = * Expression *; Throwable #primaryException = null; try *Block* catch (final Throwable #t) { #primaryException = t; throw #t; } finally { if (#primaryException != null) { try { localVar.close(); } catch(Exception #suppressedException) { #primaryException.addSuppressedException(#suppressedException); } } else { localVar.close(); } } } The variables #primaryException, #t, and #suppressedException are compiler-generated identifiers that are distinct from one and other, and from any other identifiers (compiler-generated or otherwise) that are in scope (JLS ?6.3) at the point where the automatic resource management statement occurs. This de-sugaring takes advantage of the ability to rethrow a final caught exception, which has been proposed for Java 7. The present proposal does * not* depend on this ability. In its absence, one could use a method such as sneakyThrow (*Java Puzzlers*, Puzzle 43). It is suggested that the line number table emitted by the compiler make the automatically generated resource-closing code appear to come from the last line of the *Block* (which will contain a close bracket), immediately prior to any *Catches**opt* or *Finally**opt*. TYPE SYSTEM: The proposal has no effect on the type system (other than classifying certain types as resources). REACHABILITY AND DEFINITE ASSIGNMENT: The reachability and definite assignment rules for this construct are specified by the desugaring above. It has been noted that under certain pathological conditions, the compiler must generate an error message indicating that the construct can throw an exception that cannot occur. These pathological conditions are unlikely to occur in any real code. If we ever wish to address this issue, we could do so by modifying the DA/DU rules for the language so that the following program becomes legal: public static void main(String[] args) { if (false) throw new Exception(); // Compiler error! } TESTING: The proposed construct can be tested by writing automatic resource management statements with a number of resources varying from 1 to some upper limit (say 10). Each resource can throw an exception (or not) during initialization, use, or termination. JUnit assertions are added to check that all resources opened are automatically closed, and that the correct exception (if any) is thrown. LIBRARY SUPPORT: A class must implement a designated interface to make it eligible for automatic resource management. An obvious choice would be Closeable, but unfortunately its close method is specified to throw IOException, which precludes its use in a general purpose resource management facility. It is, however, possible to retrofit Closeable with a superinterface: *package** java.lang.auto;* */*** * * A resource that must be closed when it is no longer needed.* * */* *public interface AutoCloseable {* * void close() throws Exception;* *}* package java.io; public interface Closeable *extends AutoCloseable* { void close() throws IOException; } Retrofitting java.io.Closeable to implement AutoCloseable will also provide automatic resource management for its 11 subinterfacs and 81 implementing classes in the JDK. Other existing classes and interfaces can be similarly retrofitted, for example: package java.sql; interface Connection *extends AutoCloseable* { void close() throws SQLException; ... // (and all the other members of the Connection interface) } Other types that should be retrofitted include java.sql.Statement, PreparedStatement, ResultSet; and java.awt.Graphics. Other possibilities include java.nio.channels.FileLock; javax.imageio.ImageReader, ImageWriter; javax.naming.Context; javax.xml.stream.XMLEventReader, XMLEventWriter, XMLStreamReader, XMLStreamWriter; java.beans.XMLEncoder, and XMLDecoder. It is best to err on the side of caution, and to only retrofit classes that we know are appropriate for automatic resource management. More classes can be retrofitted over time, and new types can be designed with automatic resource management in mind. See this document for additional information . To support automatic retention of suppressed exceptions (for high-quality diagnostics), we add these methods to java.lang.Throwable: /** * Adds the specified exception to the list of exceptions that were suppressed, * typically by the automatic resource management statement, in order to * deliver this exception. */ public void addSuppressedException(Throwable suppressedException); /** * Returns an array containing all of the exceptions that were suppressed, * typically by the automatic resource management statement, in order to * deliver this exception. */ public Throwable[] getSuppressedExceptions(). The printStackTrace method should be modified to append the stack traces for any suppressed exceptions. REFLECTIVE APIS: This proposal has no effect on core reflective APIs. The tree API inside javac ( http://java.sun.com/javase/6/docs/jdk/api/javac/tree/index.html) would require a minor extension. OTHER CHANGES: No other parts of the platform need be to be updated. MIGRATION: As discussed above in *Library Support*, any lexically scoped resource type that must be closed manually should be retrofitted to implement the AutoCloseable interface. New code using classes that implement AutoCloseable should use automatic resource management statements (for clarity and correctness). Manual resource management in existing code can be replaced by automatic resource management for increased clarity and improved behavior. Given the number of resource management errors observed in existing code, it may be worth the time to do this systematically. It is very easy to do this with any modern IDE, which can search for all uses of a method (such as java.io.Closeable.close()). *COMPATIBILITY* * * BREAKING CHANGES: All previously valid programs remain valid, and their semantics is unaffected. * * EXISTING PROGRAMS: Source and class files of earlier versions are unaffected by this feature. No new overloadings or overridings can occur. *REFERENCES* * * EXISTING BUGS: 4888664, 4364906, 4331290, 4215007, 4120342. *DESIGN FAQ* *1. Does the construct support locks?* The automatic resource management statement was not designed for use with locks. The synchronized block already handles Java's built-in monitor locks. The java.util.concurrent.locks.Lock interface and its implementations were added to handle some special cases that built-in synchronization doesn't support, such as non-block-structured locking, and most programmers have no need for them. (Many uses of Lock would be better replaced by a higher-level java.util.concurrent abstraction such as Semaphore, CountDownLatch, or CyclicBarrier.) Also, it is quite straightforward to acquire and release these locks manually, so even legitimate users of the Lock interface have little incentive to use a more automated solution: myLock.lock(); try { // Access the resource protected by myLock } finally { myLock.unlock(); } That said, it *is* possible to use the proposed automatic resource management statement for lock management with the aid of an adapter like this one: interface AutoLock extends AutoCloseable { AutoLock lock(); // Locks lock and returns this void close(); // Unlocks lock } static AutoLock autoLock(final Lock lock) { return new AutoLock() { public AutoLock lock() { lock.lock(); return this; } public void close() { lock.unlock(); } }; } With this adapter, you can use the following code to perform locked access with automatic unlocking: AutoLock al = autoLock(myLock); ... try(al.lock()) { // Access the resource protected by lck } *2. Does the construct allow access to resources after an exception is thrown from within the block, but before the resource is closed?* Not directly. The need for this functionality is rare. The workaround is to nest a try-catch block inside the automatic resource management statement: try (LineNumberReader reader = getInput()) { try { parseInput(reader); } catch (CharacterCodingException ex) { report("Char encoding error at line " + reader.getLineNumber()); throw ex; // Rethrow the exception } } * 3. Does the construct work properly with ?decorated? resources?* There is a low probability of a resource leak when the construct is used in this fashion: try (BufferedReader br = new BufferedReader(new FileReader(path)) { ... // Use buffered reader } The problem is that there is a ?window of vulnerability? in between the time the FileReader is constructed and the time the BufferedReader is constructed. If the BufferedReader construction fails, say, because there is insufficient memory for the buffer, the construct will *not *close the FileReader. This is unfortunate but generally acceptable. The window of vulnerability is small, and it seems likely that the application is moribund if decorator construction fails. In the unlikely event that this level of risk is unacceptable for your application, you can eliminate the window of vulnerability by treating the object and its decorator as separate resources: try (FileReader fr = new FileReader(path) { try (BufferedReader br = new BufferedReader(fr) { ... // Use buffered reader } } * 4. Does the construct support resource types whose termination method has a name other than **close**?* Not directly. There are two obvious ways in which the construct could have supported this functionality. One is to designate the termination method with an annotation. But this violates the rule that annotations cannot change the semantics of a program (JLS ?9.7). The other is to use an actual modifier to denote the termination method (the finally keyword has been proposed for this purpose). This would, however, require a class file format change, and a mandate changes to tools such as JavaDoc. The resulting construct would be more ?magical,? and wouldn't mesh as well with Java?s type system. The proposed construct is an ?80-20? solution. It is aimed squarely at solving the serious problem of Closeables. Most resources can be retrofitted to implement AutoCloseable, but a few can't (e.g., interface types that do not already contain a parameterless close method and class types that contain a parameterless close method with the wrong return type or semantics). For such resources, we recommend the use of an adapter, such as AutoLock above. The exact form of the adapter will differ depending on the details of the resource. *5. Some failures of the **close** method can be safely ignored (e.g., closing a file that was open for read). Does the construct provide for this? * No. While this functionality seems attractive, it is not clear that it's worth the added complexity. As a practical matter these ?harmless exceptions? rarely if ever occur, so a program will be no more robust if these exceptions are ignored. If you feel you must ignore them, there is a workaround, but it isn't pretty: static void copy(String src, String dest) throws IOException { boolean done = false; try (InputStream in = new FileInputStream(src)) { try(OutputStream out = new FileOutputStream(dest)) { byte[] buf = new byte[8192]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); } done = true; } catch(IOException e) { if (!done) throw e; } } *ACKNOWLEDGMENTS* I thank the members of the coin-dev list and my colleagues at Google for all of the useful input on earlier versions of this proposal. From forax at univ-mlv.fr Mon Apr 20 00:11:04 2009 From: forax at univ-mlv.fr (=?windows-1252?Q?R=E9mi_Forax?=) Date: Mon, 20 Apr 2009 09:11:04 +0200 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> Message-ID: <49EC2008.5040308@univ-mlv.fr> Joshua Bloch a ?crit : > Fellow Coiners, > > Thanks for all your feedback on the Automatic Resource Management proposal. > I have revised the proposal in light of these comments. The new version > (V.2) can be seen at this URL: > http://docs.google.com/Doc?id=ddv8ts74_3fs7483dp . It is included below for > archival purposes. > > Josh > Hi josh, just a small question why AutoClosable is specified to be in java.lang.auto and not java.lang. regards, R?mi From jjb at google.com Mon Apr 20 00:30:36 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 20 Apr 2009 00:30:36 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <49EC2008.5040308@univ-mlv.fr> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <49EC2008.5040308@univ-mlv.fr> Message-ID: <17b2302a0904200030j47c348f5ha40c744d8e9ff246@mail.gmail.com> R?mi, Good question. We did it to eliminate the possibility of name clashes in existing programs. JBoss actually uses the name AutoCloseable. Types in java.lang are automatically imported, and putting AutoCloseable in java.lang.auto avoids this issue. It doesn't make the construct any less usable, as you don't have to mention AutoCloseable explicitly to use the construct. Josh On Mon, Apr 20, 2009 at 12:11 AM, R?mi Forax wrote: > Joshua Bloch a ?crit : > >> Fellow Coiners, >> >> Thanks for all your feedback on the Automatic Resource Management >> proposal. >> I have revised the proposal in light of these comments. The new version >> (V.2) can be seen at this URL: >> http://docs.google.com/Doc?id=ddv8ts74_3fs7483dp . It is included below >> for >> archival purposes. >> >> Josh >> >> > Hi josh, > just a small question why AutoClosable is specified to be in java.lang.auto > and not java.lang. > > regards, > R?mi > From bugeaud at gmail.com Mon Apr 20 01:18:30 2009 From: bugeaud at gmail.com (Jean-Baptiste Bugeaud) Date: Mon, 20 Apr 2009 10:18:30 +0200 Subject: SUBMISSION : A second look on "named parameters" / Clarification on the scope Message-ID: <2dc3bd00904200118s35e085fdk6f4ef3cac83cd6e9@mail.gmail.com> Hello Reinier, Hello Joe, Thanks for your feedback. 2009/4/19 Reinier Zwitserloot : > Your proposal is very incomplete. Three major nits: > > A. Did I miss something, or did you totally forget to include an example of > calling a method with named parameters? Something like: > > doLogin(user: "foobar", password: new char[] { 'a', 'b', 'c' }) Reiner, I think my submission name is misleading everybody. This is not the same thing you debate some times back. My mistake ... I should have clarified from the start : I do not look at adding direct call by parameter name into the language (say "? la" ObjectiveC). But simply a reliable way access to parameter name and name a parameter's name in static way thru time. See bug 6444738 for differences. Parameter names are very usefull information in most cases, and at this time, either implementers use duplicate annotation (dummy annotations storing again the same name) or they use tools such as ASM to workaround the lack of API in the JDK. At the begining, I thought this requirement did not required a small synthax language change : a new API would be enough. But soon I realized that introducing name parameter that are static thru time, introduce anyway a new paradigm in the language that developer should be able to control directly : do I want this parameter name to be static thu time ? or do I want to let the compiler decide as usual ? A compiler option is not the suitable tool for this. If this is a global switch, it will not offer the fine grain required. If this is a per class/per package option, it will clutter the command line. And in both cases, it will not offer paradigm separation with the legacy. Thus you can not rely on the parameter name because you never know if developper has stored the name accidentaly or for purpose. > B. Why static? You might as well have picked 'strictfp' - it's a total > non-sequitur choice. Re-use of existing keywords is not really a panacea; it > waters down the anchoring ability of a keyword to virtually nothing. I'm not > sure if context-sensitive keywords are any better, but java7 is already > going to have at least one ('module'), so don't beat around the bush and > just call it 'named'). Could be just me, but introducing a change which is > not backwards compatible IF you have a type that's called 'named' (written > just like that, all-lower case), is not something I find troublesome in the > least. That's very ugly code, and a migration tool can fix this easily. Because of the definition a dictionary gives of it : something like "showing little change" is exactly what I meant for this paradigm. And no "strictfp", as well as "const" and "goto" are not matching, you see ;-) If you think that this worth integrating a new keywork, then there is room for debate. I think static fits perfectly and is clear enough. AFAIK, we already have final that is contextual? why not static too ? final is already stretched between two things : do not overload member and do not reasign variable. With the proposed language changed static modifier will be stretched between static thru instances for members and static thru time for variables. > C. You don't mention having default values for parameters, which is sort of > the point of this exercise (otherwise you really still need builders ; any > method that has so many parameters that they need names probably needs a > builder, and without defaults, not providing one and instead relying on > named params is just an inferior bandaid to your ugly API; to get it right > you STILL need to provide a builder. If, however, parameters can have > defaults, then you no longer need to make builders at all). This is because I am not asking for named call of method ... simply for a way to access name of parameter. Just a completely different topic. I don't see why a parameter on an EJB is not meanfull for the external ? same for an webservice ? why a parameter name could not be meanfull ? I don't get your point. My design decision is the kind of decision that led to erasure based genericity : it has some drawback, loss of real parametrics instances that could be usefull while reflection. But was the right decision at the right time or either we would have lots binary compatibility or we would still be debating wether or not implementing generics. My proposition on parameter name is analog, it is just meant to be used ASAP but does it does not fully solve all the possible expectations from this topic scope. Namely, should we call "by parameter name" in the language ? and how ? Room is let for the coming decade ;-) But the propopsition does not close doors to anything. > I suggest you look over the coin-dev mailing list; I entered a rough sketch > of a named parameters proposal near the end of coin. I never wrote it up > because I thought of it far too close to the deadline, and it's still of > such high impact that I doubt it would pass muster for coin. Yes I've followed the debate :) But, again its my mistake "call by parameter names" is a much more complex topic with lots of performance/plaform impact. This is not a small language change IMHO. Again, I do not look for calling a direct method call using named parameters .... just a way to retreive them. -- -- Joe, yes "late I am" ;-) FYI, I got this proposition cooking for several months I was not able to find time to write & post it to you (pittyfull isn't it). If we remove the "language change" part (static named parameter) and only keep the getParameterNames() API part (keep the regular parameter name), do you think this can be pushed to JDK7 even if out of scope of coin ? This is a very small change to the API and would solve lot of time from lot of people. I mean, this API (along with the rest of the named parameter spec) was removed from JDK6, skiping this in JDK7 means years again to wait for it ? I think we are too much getting dependent on tools such as ASM in lots of places (JavaEE implementation stacks for instance). And we have a good opportunity to remove the dependency for a clean/simple solution IMHO. Best Regards, JB From scolebourne at joda.org Mon Apr 20 02:31:11 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 20 Apr 2009 10:31:11 +0100 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> Message-ID: <4b4f45e00904200231p9ce1625o84f7281ccc514b78@mail.gmail.com> 2009/4/20 Joshua Bloch : > * 3. Does the construct work properly with ?decorated? resources?* > ? ?try (FileReader fr = new FileReader(path) { > ? ? ? ?try (BufferedReader br = new BufferedReader(fr) { > ? ? ? ? ? ?... // Use buffered reader > ? ? ? ?} > ? ?} Would this section be better written: try (FileReader fr = new FileReader(path); BufferedReader br = new BufferedReader(fr) { ... // Use buffered reader } ie. the second resource is derived from the first within one ARM block. (More generally, I think I'd prefer a single resource per ARM, as I think its a lot clearer overall and more consistent, but since you've allowed it in the proposal, I assume you'd want to keep to that style.) Stephen From reinier at zwitserloot.com Mon Apr 20 03:16:05 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 20 Apr 2009 12:16:05 +0200 Subject: SUBMISSION : A second look on "named parameters" / Clarification on the scope In-Reply-To: <2dc3bd00904200118s35e085fdk6f4ef3cac83cd6e9@mail.gmail.com> References: <2dc3bd00904200118s35e085fdk6f4ef3cac83cd6e9@mail.gmail.com> Message-ID: Ah, now I understand. I've got a much simpler proposal to address this issue. NB: Joe, I know coin's long gone, but perhaps consider this one anyway - it seems to me that some sort of named parameters proposal is likely to be accepted in the future, and adding names now should ease transition. As part of the effort I've listed all possibly complication I can come up with, at the end. Proposal: Starting from the new class file format introduced in java7 (due to module support, the class format is definitely getting a version bump), all compilers MUST put the names of the parameters in the class file (javac -g style), and obfuscators/compressors/whatever MUST NOT remove this; a class file with version v50 (or whatever number its going to end up being) won't even pass the verifier without the names in place. Add an API call on the java.lang.reflect.Method object to obtain the names of the parameters (returns a String[], or 'null' if they aren't there. Calling this on a param-less method returns an empty array, not null). Having the names is an all-or-nothing situation: Either the names are all there and this call works, or some/all are missing, and then this call does not work. I'm not sure if you can even have just a few names defined in the .class file format, but even if you can, that situation should be so extremely rare, its not worth writing up a complicated rule for). It is guaranteed that if the array exists (is not null), then each array element is not null. Voila. No need to turn in a proposal that's more complicated than most just to solve this simple problem. Complications: A) It would no longer be possible to rewrite a v49 and below class without debug info into a v50 and up class file without having the source file, but I don't actually know of any tools that attempt to do this. B) Code that generates class files on the fly (like proxy generators and the like) will need to consider the names of method parameters if/ when they update the class file format they generate to v50+. A proxy generator has issues when it is trying to generate a v50+ proxy where its input object's class spec AND the input interface to proxy on are both v49- without debug info, for example. C) A (bad) quick-fix for either of the above issues is to just use 'arg0', 'arg1', 'arg2', analogous to what e.g. eclipse does when showing method signatures for methods in classes where there is no source, no debug info and no javadoc. This is not at all the right idea. A small risk that the class file format documentation should mention as not being appropriate unless there is absolutely no other option. D) Most code these days ships with source, or javadoc, or debug info, so that auto-complete shows the proper names for each parameter, but this certainly isn't true for /all/ java code out there. After this change, method param names become visible to all. This may not be a desired side-effect for programming shops that export libraries to clients where their method parameter names are inappropriate (swear words, or 'x', 'y', and 'z' and this creates deserved but nevertheless unexpected ridicule for sucking at programming style). I think this is an acceptable price to pay. Parameters are method-local which are extremely easy to rename with your friendly neighbourhood IDE's refactor tool. E) While technically the names are NOT part of API, and you CAN freely change names around without breaking any code, old or new, the names still do become a little more enshrined as at least almost part of the public API. This is already the case to some extent (param names show up in various tooling support such as javadoc and auto-completing IDEs) but this change would move parameter names a little more towards a complete member of public API. This is an issue, but its also the point of this proposal: Move towards a java world where parameter names are universally available and are meaningful. I don't think this is a serious problem, because A) names already have a flavour of importance right now, and B) While they become more important with this proposal, they still aren't true public API, and changing names even after this proposal is accepted is not backwards incompatible. F) Confusion may arise when these names are unintentionally taken as being either part of public API, or being hierarchical; they are in fact neither. For example, this proposal makes no attempt to harmonize name conflicts; if interface A has void foo(int bar), and interface B has void foo(int baz), you can still of course write a class that implements both of these. You can even name your foo's parameter 'floobargle', of course. The aim of this proposal does not involve making parameter names inherit sensibly. --Reinier Zwitserloot On Apr 20, 2009, at 10:18, Jean-Baptiste Bugeaud wrote: > Hello Reinier, Hello Joe, > > Thanks for your feedback. > > 2009/4/19 Reinier Zwitserloot : >> Your proposal is very incomplete. Three major nits: >> >> A. Did I miss something, or did you totally forget to include an >> example of >> calling a method with named parameters? Something like: >> >> doLogin(user: "foobar", password: new char[] { 'a', 'b', 'c' }) > > Reiner, I think my submission name is misleading everybody. This is > not the same thing you debate some times back. My mistake ... I should > have clarified from the start : I do not look at adding direct call by > parameter name into the language (say "? la" ObjectiveC). But simply a > reliable way access to parameter name and name a parameter's name in > static way thru time. See bug 6444738 for differences. > > Parameter names are very usefull information in most cases, and at > this time, either implementers use duplicate annotation (dummy > annotations storing again the same name) or they use tools such as ASM > to workaround the lack of API in the JDK. > > At the begining, I thought this requirement did not required a small > synthax language change : a new API would be enough. But soon I > realized that introducing name parameter that are static thru time, > introduce anyway a new paradigm in the language that developer should > be able to control directly : do I want this parameter name to be > static thu time ? or do I want to let the compiler decide as usual ? > > A compiler option is not the suitable tool for this. > If this is a global switch, it will not offer the fine grain required. > If this is a per class/per package option, it will clutter the > command line. > And in both cases, it will not offer paradigm separation with the > legacy. Thus you can not rely on the parameter name because you never > know if developper has stored the name accidentaly or for purpose. > >> B. Why static? You might as well have picked 'strictfp' - it's a >> total >> non-sequitur choice. Re-use of existing keywords is not really a >> panacea; it >> waters down the anchoring ability of a keyword to virtually >> nothing. I'm not >> sure if context-sensitive keywords are any better, but java7 is >> already >> going to have at least one ('module'), so don't beat around the >> bush and >> just call it 'named'). Could be just me, but introducing a change >> which is >> not backwards compatible IF you have a type that's called >> 'named' (written >> just like that, all-lower case), is not something I find >> troublesome in the >> least. That's very ugly code, and a migration tool can fix this >> easily. > > Because of the definition a dictionary gives of it : something like > "showing little change" is exactly what I meant for this paradigm. And > no "strictfp", as well as "const" and "goto" are not matching, you see > ;-) > > If you think that this worth integrating a new keywork, then there is > room for debate. I think static fits perfectly and is clear enough. > AFAIK, we already have final that is contextual? why not static too ? > final is already stretched between two things : do not overload member > and do not reasign variable. > > With the proposed language changed static modifier will be stretched > between static thru instances for members and static thru time for > variables. > >> C. You don't mention having default values for parameters, which is >> sort of >> the point of this exercise (otherwise you really still need >> builders ; any >> method that has so many parameters that they need names probably >> needs a >> builder, and without defaults, not providing one and instead >> relying on >> named params is just an inferior bandaid to your ugly API; to get >> it right >> you STILL need to provide a builder. If, however, parameters can have >> defaults, then you no longer need to make builders at all). > > This is because I am not asking for named call of method ... simply > for a way to access name of parameter. Just a completely different > topic. > I don't see why a parameter on an EJB is not meanfull for the external > ? same for an webservice ? why a parameter name could not be meanfull > ? I don't get your point. > > My design decision is the kind of decision that led to erasure based > genericity : it has some drawback, loss of real parametrics instances > that could be usefull while reflection. But was the right decision at > the right time or either we would have lots binary compatibility or we > would still be debating wether or not implementing generics. > > My proposition on parameter name is analog, it is just meant to be > used ASAP but does it does not fully solve all the possible > expectations from this topic scope. Namely, should we call "by > parameter name" in the language ? and how ? > > Room is let for the coming decade ;-) But the propopsition does not > close doors to anything. > >> I suggest you look over the coin-dev mailing list; I entered a >> rough sketch >> of a named parameters proposal near the end of coin. I never wrote >> it up >> because I thought of it far too close to the deadline, and it's >> still of >> such high impact that I doubt it would pass muster for coin. > > Yes I've followed the debate :) But, again its my mistake "call by > parameter names" is a much more complex topic with lots of > performance/plaform impact. This is not a small language change IMHO. > Again, I do not look for calling a direct method call using named > parameters .... just a way to retreive them. > > -- -- > > Joe, yes "late I am" ;-) > > FYI, I got this proposition cooking for several months I was not able > to find time to write & post it to you (pittyfull isn't it). > > If we remove the "language change" part (static named parameter) and > only keep the getParameterNames() API part (keep the regular parameter > name), do you think this can be pushed to JDK7 even if out of scope of > coin ? This is a very small change to the API and would solve lot of > time from lot of people. > > I mean, this API (along with the rest of the named parameter spec) was > removed from JDK6, skiping this in JDK7 means years again to wait for > it ? I think we are too much getting dependent on tools such as ASM in > lots of places (JavaEE implementation stacks for instance). And we > have a good opportunity to remove the dependency for a clean/simple > solution IMHO. > > Best Regards, > JB From brucechapman at paradise.net.nz Mon Apr 20 03:37:05 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Mon, 20 Apr 2009 22:37:05 +1200 Subject: PROTOTYPE: In-Reply-To: <11482659.1238468832504.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> References: <11482659.1238468832504.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> Message-ID: <49EC5051.9000705@paradise.net.nz> A prototype compiler for the follow proposals Underscores in numbers Narrow Hexadecimal and Binary Integer Literals Byte and Short Integer Literal Suffixes is now available at https://kijaro.dev.java.net/servlets/ProjectDocumentList?folderID=11247&expandFolder=11247&folderID=8804 I have bundled them altogether so that the interaction between underscores and the others can be assessed and so that the two new literal forms can be compared side by side. There is one fault in the test class, fix that and it should compile and run. -- Joe, should we update the proposals with this information or is this email sufficient? Bruce From forax at univ-mlv.fr Mon Apr 20 03:43:45 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 20 Apr 2009 12:43:45 +0200 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904200030j47c348f5ha40c744d8e9ff246@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <49EC2008.5040308@univ-mlv.fr> <17b2302a0904200030j47c348f5ha40c744d8e9ff246@mail.gmail.com> Message-ID: <49EC51E1.6@univ-mlv.fr> Joshua Bloch a ?crit : > R?mi, > > Good question. We did it to eliminate the possibility of name clashes > in existing programs. JBoss actually uses the name AutoCloseable. > Types in java.lang are automatically imported, and putting > AutoCloseable in java.lang.auto avoids this issue. It doesn't make the > construct any less usable, as you don't have to mention AutoCloseable > explicitly to use the construct. > > Josh I don't like the fact that the JDK will contains a package with only one interface just to avoid name clash that is hypothetical because classes of the current package are imported before java.lang ones and everybody should avoid to use import *. In my opinion, (which is biased) , I prefer sacrificing source backward compatibility to having to take 15 minutes each year because I will have to explain to my students why the package java.lang.auto with one interface exists. Else what about renaming (yes again) AutoCloseable to ARMCloseable ? R?mi From reinier at zwitserloot.com Mon Apr 20 03:47:17 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 20 Apr 2009 12:47:17 +0200 Subject: Automatic Resource Management, V.2 In-Reply-To: <4b4f45e00904200231p9ce1625o84f7281ccc514b78@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4b4f45e00904200231p9ce1625o84f7281ccc514b78@mail.gmail.com> Message-ID: <1386C5FF-8568-439B-AA4C-2FCDF8663D00@zwitserloot.com> The usage of package java.lang.auto isn't neccessary; classes in your own package always take precedence over java.lang classes, and any import statement that clashes with a java.lang class takes precedence over java.lang. In other words, if there is an interface named 'jboss.AutoCloseable', then all classes in the jboss package will automatically use that AutoCloseable. Any code not in the jboss package that includes the statement "import jboss.AutoCloseable", will also use jboss's AutoCloseable. Client code (that is, code that USES trywith blocks) never needs to know about the name 'AutoCloseable' to use them. Any code that wants to be an ARM-style closable that is in jboss code will need be explicit: public class IAmClosable implements java.lang.AutoCloseable { private AutoCloseable jbossAutoCloseable; public void close() {} } but such code has to be explicit even if AutoCloseable was moved to java.lang.auto as well, so I doubt thats relevant. A search through a lot of java libraries did not produce any (public API) results for 'AutoCloseable': http://myjavadoc.net/search/search-java.php/AutoCloseable http://www.google.com/codesearch?hl=en&lr=&q=AutoCloseable+lang%3Ajava&sbtn=Search So it seems that org.jboss.remoting.spi.AutoCloseable is the only one. So, the only remaining issues are the following: A) Confusion for jboss and whatever other library(ies) are lurking out there with an AutoCloseable. Forgetting to import the 'right' AutoCloseable gets you the 'wrong' one. However, this confusion is pretty much unavoidable; just like when Iterable was added, seeing the words 'AutoCloseable' in a sourcefile will instinctivly make a java programmer think it must be java.lang.(auto.)AutoCloseable. There's a java puzzler dedicated to this principle, which creates a local version of String. In other words, putting AutoCloseable in another package doesn't help all that much. So, I say: not important enough; not enough applicable classes and the alternative doesn't clear up enough confusion. B) trying to import "jboss.*" will NOT take precedence over the implicit java.lang.* import; instead javac emits a compiler error: bar/Bar.java:7: reference to Integer is ambiguous, both class bla.Integer in bla and class java.lang.Integer in java.lang match Integer y = new Integer(12); So, its technically true there could be a migration compatibility issue, but I wouldn't be surprised if there isn't a single line of java code in existence that actually would run into this problem. I say: Not important enough; star imports are rarely used, there aren't many packages where this conflict can occur, java.lang.Iterable had the same problem and I've never seen a complaint there either, and a compiler error that hints at the problem (as above) is the next-best- thing to just working normally. If I weigh these issues against creating a new package in the java.lang space, as well as putting only 1 type inside it, as well as being inconsistent with how java.lang.Iterable was handled (which could easily have been put in java.util if this had been any concern back then) I think its clear that just putting AutoCloseable in java.lang is preferable. --Reinier Zwitserloot Like it? Tip it! http://tipit.to On Apr 20, 2009, at 11:31, Stephen Colebourne wrote: > 2009/4/20 Joshua Bloch : >> * 3. Does the construct work properly with ?decorated? resources?* >> try (FileReader fr = new FileReader(path) { >> try (BufferedReader br = new BufferedReader(fr) { >> ... // Use buffered reader >> } >> } > > Would this section be better written: > > try (FileReader fr = new FileReader(path); BufferedReader br = new > BufferedReader(fr) { > ... // Use buffered reader > } > > ie. the second resource is derived from the first within one ARM > block. > > (More generally, I think I'd prefer a single resource per ARM, as I > think its a lot clearer overall and more consistent, but since you've > allowed it in the proposal, I assume you'd want to keep to that > style.) > > Stephen > From brucechapman at paradise.net.nz Mon Apr 20 04:00:34 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Mon, 20 Apr 2009 23:00:34 +1200 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> Message-ID: <49EC55D2.6010305@paradise.net.nz> Joshua Bloch wrote: > Fellow Coiners, > > Thanks for all your feedback on the Automatic Resource Management proposal. > I have revised the proposal in light of these comments. The new version > (V.2) can be seen at this URL: > http://docs.google.com/Doc?id=ddv8ts74_3fs7483dp . It is included below for > archival purposes. > > Josh > - SNIP - > An automatic resource management statement with a single resource expression > and no *Finally* or *Catches* would behave as if replaced by the following > source code: > > > > { > > final *T**ype* #localVar = *Expression*; > The type in the generated declaration above could simply be AutoClosable rather than the specific type of the expression? (and especially so if the expression had a type which was an intersection type - which I think is possible). Bruce From paul.martin at gmail.com Mon Apr 20 05:32:33 2009 From: paul.martin at gmail.com (Paul Martin) Date: Mon, 20 Apr 2009 13:32:33 +0100 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> Message-ID: <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> Hi, I've got a few minor comments/questions: > To support automatic retention of suppressed exceptions (for high-quality > diagnostics), we add these methods to java.lang.Throwable: > ... > /** > * Returns an array containing all of the exceptions that were suppressed, > * typically by the automatic resource management statement, in order to > * deliver this exception. > */ > public Throwable[] getSuppressedExceptions(). Why not return a List instead of an array (since Collections are generally nicer to use)? If an array is to be returned, is it a copy, or does changing its contents affect the Throwable? Will an empty array or null be returned if there are no suppressed exceptions? Would it be useful to distinguish exceptions suppressed by AutoCloseable and those suppressed by other mechanisms (e.g. with an associated enum or message, or even an EnumMap of )? Why exceptions were suppressed might be useful in future (unless it is expected that only AutoCloseable will suppress exceptions, or that it is unlikely that there will be multiple suppressors of exceptions). > The printStackTrace method should be modified to append the stack traces for > any suppressed exceptions. This might be difficult, particularly where there are a number of "cause" and "suppressed" exceptions (each of which might have their own) - it might be hard to associate each exception with its parent in the output (whereas currently "cause" has only one immediate parent and so it is easy to follow such a stack trace). This would also have an impact on the TESTING section (where "cause" exceptions should also be included). > *DESIGN FAQ* It might be nice to answer "Why is the 'try' keyword used instead of alternatives such as 'using'?" (though maybe only once the change has been released - probably not important at this stage). > *2. Does the construct allow access to resources after an exception is > thrown from within the block, but before the resource is closed?* I didn't really understand why this had to be the case - was it because resource variables are final and initialised in order, so if one resource fails to initialise it will not be in scope at all, so we cannot guarantee that any will be in scope in explicit catch and finally clauses? If so, couldn't they just be set to null if they were not initialised correctly? As you say, it is probably not a major issue in any case. > * 3. Does the construct work properly with ?decorated? resources?* ... > try (FileReader fr = new FileReader(path) { > try (BufferedReader br = new BufferedReader(fr) { > ... // Use buffered reader > } > } You are missing a closing ) on each of the try lines. Could this be rewritten as the following? try (FileReader fr = new FileReader(path); BufferedReader br = new BufferedReader(fr)) { ... // Use buffered reader } > * 4. Does the construct support resource types whose termination method has ... > with an annotation. But this violates the rule that annotations cannot > change the semantics of a program (JLS ?9.7). The other is to use an actual I can't see such a rule in the JLS - the closest seems to be "The purpose of an annotation is simply to associate information with the annotated program element" - is that what is meant? > *5. Some failures of the **close** method can be safely ignored (e.g., ... > these exceptions are ignored. If you feel you must ignore them, there is a > workaround, but it isn't pretty: Could you use a decorator to simplify the code a little, such as: public class HideAutoCloseableExceptionsAdapter implements AutoCloseable { private final AutoCloseable delegate; public HideAutoCloseableExceptionsAdapter(AutoCloseable delegate) { this.delegate = delegate; } @Override public void close() { try { delegate.close(); } catch (Exception e) { // Do nothing } } } static void copy(String src, String dest) throws IOException { InputStream in = new FileInputStream(src); try (new HideAutoCloseableExceptionsAdapter(in)) { try(OutputStream out = new FileOutputStream(dest)) { byte[] buf = new byte[8192]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); } } } } Otherwise the proposal looks good to me. Regards, Paul From jjb at google.com Mon Apr 20 07:09:45 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 20 Apr 2009 07:09:45 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <4b4f45e00904200231p9ce1625o84f7281ccc514b78@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4b4f45e00904200231p9ce1625o84f7281ccc514b78@mail.gmail.com> Message-ID: <17b2302a0904200709u4a2d3ecfh18888bdc87ab8e61@mail.gmail.com> Stephen, On Mon, Apr 20, 2009 at 2:31 AM, Stephen Colebourne wrote: > 2009/4/20 Joshua Bloch : > > * 3. Does the construct work properly with ?decorated? resources?* > > try (FileReader fr = new FileReader(path) { > > try (BufferedReader br = new BufferedReader(fr) { > > ... // Use buffered reader > > } > > } > > Would this section be better written: > > try (FileReader fr = new FileReader(path); BufferedReader br = new > BufferedReader(fr) { > ... // Use buffered reader > } > > ie. the second resource is derived from the first within one ARM block. Yes, thanks. Fixed. > > > (More generally, I think I'd prefer a single resource per ARM, as I > think its a lot clearer overall and more consistent, but since you've > allowed it in the proposal, I assume you'd want to keep to that > style.) Yes. May people really care about keeping the nesting depth low, and the ability to combine resources in a single ARM statement does that for them. Thanks again, Josh From jjb at google.com Mon Apr 20 07:15:05 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 20 Apr 2009 07:15:05 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <49EC51E1.6@univ-mlv.fr> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <49EC2008.5040308@univ-mlv.fr> <17b2302a0904200030j47c348f5ha40c744d8e9ff246@mail.gmail.com> <49EC51E1.6@univ-mlv.fr> Message-ID: <17b2302a0904200715u267785d5y46bc86fb39aa61ce@mail.gmail.com> R?mi, It is possible that we may end up with some other "auto" interfaces in future. And as mentioned, a package-based solution is 100% safe, as it requires explicit import. Of course I agree with you that package with a single class in it is a bit suspect. I think this is best left as an "open issue" for the time being. Thanks, Josh On Mon, Apr 20, 2009 at 3:43 AM, R?mi Forax wrote: > Joshua Bloch a ?crit : > >> R?mi, >> >> Good question. We did it to eliminate the possibility of name clashes in >> existing programs. JBoss actually uses the name AutoCloseable. Types in >> java.lang are automatically imported, and putting AutoCloseable in >> java.lang.auto avoids this issue. It doesn't make the construct any less >> usable, as you don't have to mention AutoCloseable explicitly to use the >> construct. >> >> Josh >> > > I don't like the fact that the JDK will contains a package with only one > interface > just to avoid name clash that is hypothetical because classes of the > current package are imported > before java.lang ones and everybody should avoid to use import *. > > In my opinion, (which is biased) , I prefer sacrificing source backward > compatibility to having to take > 15 minutes each year because I will have to explain to my students why the > package > java.lang.auto with one interface exists. > > Else what about renaming (yes again) AutoCloseable to ARMCloseable ? > > R?mi > From jjb at google.com Mon Apr 20 07:22:44 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 20 Apr 2009 07:22:44 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <1386C5FF-8568-439B-AA4C-2FCDF8663D00@zwitserloot.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4b4f45e00904200231p9ce1625o84f7281ccc514b78@mail.gmail.com> <1386C5FF-8568-439B-AA4C-2FCDF8663D00@zwitserloot.com> Message-ID: <17b2302a0904200722i58b261dav25f00d7c9466177f@mail.gmail.com> Reinier, These arguments are quite persuasive. Let's see what (if anything) others have to say, but I agree with you and R?mi at this point. Josh On Mon, Apr 20, 2009 at 3:47 AM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > The usage of package java.lang.auto isn't neccessary; classes in your own > package always take precedence over java.lang classes, and any import > statement that clashes with a java.lang class takes precedence over > java.lang. > > In other words, if there is an interface named 'jboss.AutoCloseable', then > all classes in the jboss package will automatically use that AutoCloseable. > Any code not in the jboss package that includes the statement "import > jboss.AutoCloseable", will also use jboss's AutoCloseable. Client code (that > is, code that USES trywith blocks) never needs to know about the name > 'AutoCloseable' to use them. Any code that wants to be an ARM-style closable > that is in jboss code will need be explicit: > > public class IAmClosable implements java.lang.AutoCloseable { > private AutoCloseable jbossAutoCloseable; > public void close() {} > } > > but such code has to be explicit even if AutoCloseable was moved to > java.lang.auto as well, so I doubt thats relevant. > > A search through a lot of java libraries did not produce any (public API) > results for 'AutoCloseable': > > http://myjavadoc.net/search/search-java.php/AutoCloseable > > > http://www.google.com/codesearch?hl=en&lr=&q=AutoCloseable+lang%3Ajava&sbtn=Search > > So it seems that org.jboss.remoting.spi.AutoCloseable is the only one. > > So, the only remaining issues are the following: > > A) Confusion for jboss and whatever other library(ies) are lurking out > there with an AutoCloseable. Forgetting to import the > 'right' AutoCloseable gets you the 'wrong' one. However, this confusion is > pretty much unavoidable; just like when Iterable was added, seeing the words > 'AutoCloseable' in a sourcefile will instinctivly make a java programmer > think it must be java.lang.(auto.)AutoCloseable. There's a java puzzler > dedicated to this principle, which creates a local version of String. In > other words, putting AutoCloseable in another package doesn't help all that > much. So, I say: not important enough; not enough applicable classes and the > alternative doesn't clear up enough confusion. > > B) trying to import "jboss.*" will NOT take precedence over the implicit > java.lang.* import; instead javac emits a compiler error: > > bar/Bar.java:7: reference to Integer is ambiguous, both class bla.Integer > in bla and class java.lang.Integer in java.lang match > Integer y = new Integer(12); > > So, its technically true there could be a migration compatibility issue, > but I wouldn't be surprised if there isn't a single line of java code in > existence that actually would run into this problem. I say: Not important > enough; star imports are rarely used, there aren't many packages where this > conflict can occur, java.lang.Iterable had the same problem and I've never > seen a complaint there either, and a compiler error that hints at the > problem (as above) is the next-best-thing to just working normally. > > > If I weigh these issues against creating a new package in the java.lang > space, as well as putting only 1 type inside it, as well as being > inconsistent with how java.lang.Iterable was handled (which could easily > have been put in java.util if this had been any concern back then) I think > its clear that just putting AutoCloseable in java.lang is preferable. > > > > --Reinier Zwitserloot > Like it? Tip it! > http://tipit.to > > > > On Apr 20, 2009, at 11:31, Stephen Colebourne wrote: > > 2009/4/20 Joshua Bloch : > > * 3. Does the construct work properly with ?decorated? resources?* > > try (FileReader fr = new FileReader(path) { > > try (BufferedReader br = new BufferedReader(fr) { > > ... // Use buffered reader > > } > > } > > > Would this section be better written: > > try (FileReader fr = new FileReader(path); BufferedReader br = new > BufferedReader(fr) { > ... // Use buffered reader > } > > ie. the second resource is derived from the first within one ARM block. > > (More generally, I think I'd prefer a single resource per ARM, as I > think its a lot clearer overall and more consistent, but since you've > allowed it in the proposal, I assume you'd want to keep to that > style.) > > Stephen > > > From jjb at google.com Mon Apr 20 07:34:21 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 20 Apr 2009 07:34:21 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <49EC55D2.6010305@paradise.net.nz> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <49EC55D2.6010305@paradise.net.nz> Message-ID: <17b2302a0904200734j31ef60afueb2eae2c95a44399@mail.gmail.com> Bruce, On Mon, Apr 20, 2009 at 4:00 AM, Bruce Chapman wrote: > >> >> final *T**ype* #localVar = *Expression*; >> >> > The type in the generated declaration above could simply be AutoClosable > rather than the specific type of the expression? Unfortunately it could not: if it were, the ARM statement could throw the wrong exception type. If Expression is of a subclass of AutoCloseable whose close method throws a particular set of exceptions (or none at all), it's important that the enclosing statement behaves as if #localVar.close() throws exactly the same set of exceptions. You are correct that it's not possible to express this in declaration in the source language, but I believe the compiler will have no trouble doing it. I will confirm this. This issue does merit a note in the spec, and I will write one shortly. Thanks, Josh From Ruslan at Shevchenko.Kiev.UA Mon Apr 20 07:58:58 2009 From: Ruslan at Shevchenko.Kiev.UA (Ruslan Shevchenko) Date: Mon, 20 Apr 2009 17:58:58 +0300 (EEST) Subject: Syntax patterns: more statistics. Message-ID: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> Good day, community ! I want to share some statistics about java usage patterns, related to some of coin-dev proposals. Main changes from previous post are: - added counts for 'if' syntax constructions, so we can say, hom many percents of if's can be eliminated by elvis operator ( [4-5]%) - added counts for 'catch' syntax constructions, so we can say that multicath eliminate 6-8% of all catch clauses. - added count for big integers integers (where undescore can be applicable, I guess this is x: x > 100000 || x < -10000) and for all integer literals. (underscore can be applicable to near 1%) - added count for object-switch proposal by Ulf Zibis (refining, that Left/Right part of expressions are first operand in equalirty expression or object in method call) - added count for rethrow proposal by Mark Mahieu (near 50% of all catches in some packages (!) ). - added count for catches inside finally block. (Is this is a real problem [?]). If anybody whant run checks on own dataset or/and add own check definitions: all procedure is the same as in my previous letter (see http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001442.html) except URL for last version is http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerSourceInstaller-2.5.0p1.jar Now summary statistics for some well-known packages: jetty (web server) all catchs : 281 all ifs : 764 all integer literals : 2903 big integer literals(undescores) : 25 byte literal : 52 catch in finally : 3 elvis : 43 instanceof switch : 8 loop with remove : 0 multi catch : 22 object switch : 31 rethrow clause : 34 string in switch : 19 Files:187 gwt-users (google java ajax client library) all catchs : 171 all ifs : 735 all integer literals : 2282 big integer literals(undescores) : 24 byte literal : 2 catch in finally : 2 elvis : 30 instanceof switch : 6 loop with remove : 5 multi catch : 9 object switch : 27 rethrow clause : 84 string in switch : 10 Files:920 hibernate (ORM toolkit) all catchs : 650 all ifs : 2410 all integer literals : 3240 big integer literals(undescores) : 12 byte literal : 1 catch in finally : 27 elvis : 182 instanceof switch : 28 loop with remove : 12 multi catch : 25 object switch : 94 rethrow clause : 450 string in switch : 86 Files:1372 openjdk7 (standard java library) all catchs : 8404 all ifs : 28494 all integer literals : 124356 big integer literals(undescores) : 4066 byte literal : 1454 catch in finally : 103 elvis : 877 instanceof switch : 318 loop with remove : 62 multi catch : 411 object switch : 1363 rethrow clause : 3264 string in switch : 445 Files:9252 Hope, this data will be useful in some cases. Regards ! From jjb at google.com Mon Apr 20 08:14:36 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 20 Apr 2009 08:14:36 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> Message-ID: <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> Paul, Thanks for the feedback. > > /** > > * Returns an array containing all of the exceptions that were > suppressed, > > * typically by the automatic resource management statement, in order to > > * deliver this exception. > > */ > > public Throwable[] getSuppressedExceptions(). > > Why not return a List instead of an array (since > Collections are generally nicer to use)? I did think about this, but I opted to stick with the pattern in enum types' values() method. That decision was made for performance. Arguably the performance issues are less important here, and the winds of change have blown further away from arrays since then, so I'm definitely open to switching this to a List if others think it's the right thing to do. > If an array is to be > returned, is it a copy, or does changing its contents affect the > Throwable? A copy. The spec should have made this explicit, and will do so. > Will an empty array or null be returned if there are no > suppressed exceptions? It goes without saying (literally) that an empty array will be returned (see Effective Java Item 43). > > > Would it be useful to distinguish exceptions suppressed by > AutoCloseable and those suppressed by other mechanisms (e.g. with an > associated enum or message, or even an EnumMap of )? > Why exceptions were suppressed might be useful in future (unless it > is expected that only AutoCloseable will suppress exceptions, or that > it is unlikely that there will be multiple suppressors of exceptions). This feels like overkill to me. > > > > The printStackTrace method should be modified to append the stack traces > for > > any suppressed exceptions. > > This might be difficult, particularly where there are a number of > "cause" and "suppressed" exceptions (each of which might have their > own) - it might be hard to associate each exception with its parent in > the output (whereas currently "cause" has only one immediate parent > and so it is easy to follow such a stack trace). I did think about this, and came to the conclusion that it wasn't so bad. The main problem is the "intermingling" of causes and suppressed exceptions. I will come up with a format and put an example in the spec. > This would also have > an impact on the TESTING section (where "cause" exceptions should also > be included). True! I'll fix this later today. > > > > *DESIGN FAQ* > > It might be nice to answer "Why is the 'try' keyword used instead of > alternatives such as 'using'?" (though maybe only once the change has > been released - probably not important at this stage). Yes. I'm sure the DESIGN FAQ will grow over time. As you can see, my current focus was on code samples for how to achieve specific effects. > > > > *2. Does the construct allow access to resources after an exception is > > thrown from within the block, but before the resource is closed?* > > I didn't really understand why this had to be the case - was it > because resource variables are final and initialised in order, so if > one resource fails to initialise it will not be in scope at all, so we > cannot guarantee that any will be in scope in explicit catch and > finally clauses? The only other reasonable rule that I could come up with was that the finally block was executed before the close, but only if all the resource declarations complete successfully, and that all resources were in scope, but these semantics are far less desirable. Perhaps this rates an FAQ. If so, couldn't they just be set to null if they > were not initialised correctly? It turns out that this is not an issue, as the catch/finally blocks won't get executed if any declarations fail. > As you say, it is probably not a > major issue in any case. Yep. > > * 3. Does the construct work properly with ?decorated? resources?* > ... > > try (FileReader fr = new FileReader(path) { > > try (BufferedReader br = new BufferedReader(fr) { > > ... // Use buffered reader > > } > > } > > You are missing a closing ) on each of the try lines. Yep. > > > Could this be rewritten as the following? > > try (FileReader fr = new FileReader(path); BufferedReader br = new > BufferedReader(fr)) { > ... // Use buffered reader > } > Yep. Done. > > > > * 4. Does the construct support resource types whose termination method > has > ... > > with an annotation. But this violates the rule that annotations cannot > > change the semantics of a program (JLS ?9.7). The other is to use an > actual > > I can't see such a rule in the JLS - the closest seems to be "The > purpose of an annotation is simply to associate information with the > annotated program element" - is that what is meant? Yes. That's how that prose has always been interpreted. > > > > *5. Some failures of the **close** method can be safely ignored (e.g., > ... > > these exceptions are ignored. If you feel you must ignore them, there is > a > > workaround, but it isn't pretty: > > Could you use a decorator to simplify the code a little, such as: > > public class HideAutoCloseableExceptionsAdapter implements AutoCloseable { > private final AutoCloseable delegate; > public HideAutoCloseableExceptionsAdapter(AutoCloseable delegate) { > this.delegate = delegate; > } > @Override > public void close() { > try { > delegate.close(); > } catch (Exception e) { > // Do nothing > } > } > } > > static void copy(String src, String dest) throws IOException { > InputStream in = new FileInputStream(src); > try (new HideAutoCloseableExceptionsAdapter(in)) { > try(OutputStream out = new FileOutputStream(dest)) { > byte[] buf = new byte[8192]; > int n; > while ((n = in.read(buf)) >= 0) > out.write(buf, 0, n); > } > } > } > } > Yes; you could do that. Of course you'd have to write a separate decorator for every such type. But it's worth mentioning that in the FAQ, and I will do so. Thanks again, Josh From mthornton at optrak.co.uk Mon Apr 20 08:25:27 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Mon, 20 Apr 2009 16:25:27 +0100 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> Message-ID: <49EC93E7.10909@optrak.co.uk> Joshua Bloch wrote: > > I did think about this, but I opted to stick with the pattern in enum types' > values() method. That decision was made for performance. Arguably the > performance issues are less important here, and the winds of change have > blown further away from arrays since then, so I'm definitely open to > switching this to a List if others think it's the right thing to do. > > Surely the VM is able to optimise away the trivial accessors in an immutable List backed by an array, and has been capable of this for quite a while? I really wonder if there was ever any significant performance gain obtained from this choice. In any case I vote for a List. Mark Thornton From neal at gafter.com Mon Apr 20 08:30:48 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 20 Apr 2009 08:30:48 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <1386C5FF-8568-439B-AA4C-2FCDF8663D00@zwitserloot.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4b4f45e00904200231p9ce1625o84f7281ccc514b78@mail.gmail.com> <1386C5FF-8568-439B-AA4C-2FCDF8663D00@zwitserloot.com> Message-ID: <15e8b9d20904200830x2063e5bftf67725cc816464d5@mail.gmail.com> On Mon, Apr 20, 2009 at 3:47 AM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > The usage of package java.lang.auto isn't neccessary; classes in your > own package always take precedence over java.lang classes, and any > import statement that clashes with a java.lang class takes precedence > over java.lang. Explicit *-imports do not take precedence over the implicit import of java.lang.*. From neal at gafter.com Mon Apr 20 08:46:12 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 20 Apr 2009 08:46:12 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> Message-ID: <15e8b9d20904200846v61dad02amdff38481dc91c0a0@mail.gmail.com> On Sun, Apr 19, 2009 at 11:45 PM, Joshua Bloch wrote: > Thanks for all your feedback on the Automatic Resource Management proposal. > I have revised the proposal in light of these comments. I am disappointed to see that this revision addresses none of the ergonomic issues reported earlier, not even those that were identified in the previous ARM proposal years ago and for which a solution was promised in the revision. From neal at gafter.com Mon Apr 20 08:52:22 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 20 Apr 2009 08:52:22 -0700 Subject: SUBMISSION : A second look on "named parameters" / Clarification on the scope In-Reply-To: References: <2dc3bd00904200118s35e085fdk6f4ef3cac83cd6e9@mail.gmail.com> Message-ID: <15e8b9d20904200852q70bf48bcm2c9beb8685902488@mail.gmail.com> Reiner- This is a library proposal, not a language proposal, so it doesn't need to be done inside project Coin. -Neal On Mon, Apr 20, 2009 at 3:16 AM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > Ah, now I understand. > > I've got a much simpler proposal to address this issue. > > NB: Joe, I know coin's long gone, but perhaps consider this one anyway > - it seems to me that some sort of named parameters proposal is likely > to be accepted in the future, and adding names now should ease > transition. As part of the effort I've listed all possibly > complication I can come up with, at the end. > > Proposal: > > > Starting from the new class file format introduced in java7 (due to > module support, the class format is definitely getting a version > bump), all compilers MUST put the names of the parameters in the class > file (javac -g style), and obfuscators/compressors/whatever MUST NOT > remove this; a class file with version v50 (or whatever number its > going to end up being) won't even pass the verifier without the names > in place. > > Add an API call on the java.lang.reflect.Method object to obtain the > names of the parameters (returns a String[], or 'null' if they aren't > there. Calling this on a param-less method returns an empty array, not > null). Having the names is an all-or-nothing situation: Either the > names are all there and this call works, or some/all are missing, and > then this call does not work. I'm not sure if you can even have just a > few names defined in the .class file format, but even if you can, that > situation should be so extremely rare, its not worth writing up a > complicated rule for). It is guaranteed that if the array exists (is > not null), then each array element is not null. > > Voila. No need to turn in a proposal that's more complicated than most > just to solve this simple problem. > > Complications: > > A) It would no longer be possible to rewrite a v49 and below class > without debug info into a v50 and up class file without having the > source file, but I don't actually know of any tools that attempt to do > this. > > B) Code that generates class files on the fly (like proxy generators > and the like) will need to consider the names of method parameters if/ > when they update the class file format they generate to v50+. A proxy > generator has issues when it is trying to generate a v50+ proxy where > its input object's class spec AND the input interface to proxy on are > both v49- without debug info, for example. > > C) A (bad) quick-fix for either of the above issues is to just use > 'arg0', 'arg1', 'arg2', analogous to what e.g. eclipse does when > showing method signatures for methods in classes where there is no > source, no debug info and no javadoc. This is not at all the right > idea. A small risk that the class file format documentation should > mention as not being appropriate unless there is absolutely no other > option. > > D) Most code these days ships with source, or javadoc, or debug info, > so that auto-complete shows the proper names for each parameter, but > this certainly isn't true for /all/ java code out there. After this > change, method param names become visible to all. This may not be a > desired side-effect for programming shops that export libraries to > clients where their method parameter names are inappropriate (swear > words, or 'x', 'y', and 'z' and this creates deserved but nevertheless > unexpected ridicule for sucking at programming style). I think this is > an acceptable price to pay. Parameters are method-local which are > extremely easy to rename with your friendly neighbourhood IDE's > refactor tool. > > E) While technically the names are NOT part of API, and you CAN freely > change names around without breaking any code, old or new, the names > still do become a little more enshrined as at least almost part of the > public API. This is already the case to some extent (param names show > up in various tooling support such as javadoc and auto-completing > IDEs) but this change would move parameter names a little more towards > a complete member of public API. This is an issue, but its also the > point of this proposal: Move towards a java world where parameter > names are universally available and are meaningful. I don't think this > is a serious problem, because A) names already have a flavour of > importance right now, and B) While they become more important with > this proposal, they still aren't true public API, and changing names > even after this proposal is accepted is not backwards incompatible. > > F) Confusion may arise when these names are unintentionally taken as > being either part of public API, or being hierarchical; they are in > fact neither. For example, this proposal makes no attempt to harmonize > name conflicts; if interface A has void foo(int bar), and interface B > has void foo(int baz), you can still of course write a class that > implements both of these. You can even name your foo's parameter > 'floobargle', of course. The aim of this proposal does not involve > making parameter names inherit sensibly. > > > --Reinier Zwitserloot > > > > On Apr 20, 2009, at 10:18, Jean-Baptiste Bugeaud wrote: > > > Hello Reinier, Hello Joe, > > > > Thanks for your feedback. > > > > 2009/4/19 Reinier Zwitserloot : > >> Your proposal is very incomplete. Three major nits: > >> > >> A. Did I miss something, or did you totally forget to include an > >> example of > >> calling a method with named parameters? Something like: > >> > >> doLogin(user: "foobar", password: new char[] { 'a', 'b', 'c' }) > > > > Reiner, I think my submission name is misleading everybody. This is > > not the same thing you debate some times back. My mistake ... I should > > have clarified from the start : I do not look at adding direct call by > > parameter name into the language (say "? la" ObjectiveC). But simply a > > reliable way access to parameter name and name a parameter's name in > > static way thru time. See bug 6444738 for differences. > > > > Parameter names are very usefull information in most cases, and at > > this time, either implementers use duplicate annotation (dummy > > annotations storing again the same name) or they use tools such as ASM > > to workaround the lack of API in the JDK. > > > > At the begining, I thought this requirement did not required a small > > synthax language change : a new API would be enough. But soon I > > realized that introducing name parameter that are static thru time, > > introduce anyway a new paradigm in the language that developer should > > be able to control directly : do I want this parameter name to be > > static thu time ? or do I want to let the compiler decide as usual ? > > > > A compiler option is not the suitable tool for this. > > If this is a global switch, it will not offer the fine grain required. > > If this is a per class/per package option, it will clutter the > > command line. > > And in both cases, it will not offer paradigm separation with the > > legacy. Thus you can not rely on the parameter name because you never > > know if developper has stored the name accidentaly or for purpose. > > > >> B. Why static? You might as well have picked 'strictfp' - it's a > >> total > >> non-sequitur choice. Re-use of existing keywords is not really a > >> panacea; it > >> waters down the anchoring ability of a keyword to virtually > >> nothing. I'm not > >> sure if context-sensitive keywords are any better, but java7 is > >> already > >> going to have at least one ('module'), so don't beat around the > >> bush and > >> just call it 'named'). Could be just me, but introducing a change > >> which is > >> not backwards compatible IF you have a type that's called > >> 'named' (written > >> just like that, all-lower case), is not something I find > >> troublesome in the > >> least. That's very ugly code, and a migration tool can fix this > >> easily. > > > > Because of the definition a dictionary gives of it : something like > > "showing little change" is exactly what I meant for this paradigm. And > > no "strictfp", as well as "const" and "goto" are not matching, you see > > ;-) > > > > If you think that this worth integrating a new keywork, then there is > > room for debate. I think static fits perfectly and is clear enough. > > AFAIK, we already have final that is contextual? why not static too ? > > final is already stretched between two things : do not overload member > > and do not reasign variable. > > > > With the proposed language changed static modifier will be stretched > > between static thru instances for members and static thru time for > > variables. > > > >> C. You don't mention having default values for parameters, which is > >> sort of > >> the point of this exercise (otherwise you really still need > >> builders ; any > >> method that has so many parameters that they need names probably > >> needs a > >> builder, and without defaults, not providing one and instead > >> relying on > >> named params is just an inferior bandaid to your ugly API; to get > >> it right > >> you STILL need to provide a builder. If, however, parameters can have > >> defaults, then you no longer need to make builders at all). > > > > This is because I am not asking for named call of method ... simply > > for a way to access name of parameter. Just a completely different > > topic. > > I don't see why a parameter on an EJB is not meanfull for the external > > ? same for an webservice ? why a parameter name could not be meanfull > > ? I don't get your point. > > > > My design decision is the kind of decision that led to erasure based > > genericity : it has some drawback, loss of real parametrics instances > > that could be usefull while reflection. But was the right decision at > > the right time or either we would have lots binary compatibility or we > > would still be debating wether or not implementing generics. > > > > My proposition on parameter name is analog, it is just meant to be > > used ASAP but does it does not fully solve all the possible > > expectations from this topic scope. Namely, should we call "by > > parameter name" in the language ? and how ? > > > > Room is let for the coming decade ;-) But the propopsition does not > > close doors to anything. > > > >> I suggest you look over the coin-dev mailing list; I entered a > >> rough sketch > >> of a named parameters proposal near the end of coin. I never wrote > >> it up > >> because I thought of it far too close to the deadline, and it's > >> still of > >> such high impact that I doubt it would pass muster for coin. > > > > Yes I've followed the debate :) But, again its my mistake "call by > > parameter names" is a much more complex topic with lots of > > performance/plaform impact. This is not a small language change IMHO. > > Again, I do not look for calling a direct method call using named > > parameters .... just a way to retreive them. > > > > -- -- > > > > Joe, yes "late I am" ;-) > > > > FYI, I got this proposition cooking for several months I was not able > > to find time to write & post it to you (pittyfull isn't it). > > > > If we remove the "language change" part (static named parameter) and > > only keep the getParameterNames() API part (keep the regular parameter > > name), do you think this can be pushed to JDK7 even if out of scope of > > coin ? This is a very small change to the API and would solve lot of > > time from lot of people. > > > > I mean, this API (along with the rest of the named parameter spec) was > > removed from JDK6, skiping this in JDK7 means years again to wait for > > it ? I think we are too much getting dependent on tools such as ASM in > > lots of places (JavaEE implementation stacks for instance). And we > > have a good opportunity to remove the dependency for a clean/simple > > solution IMHO. > > > > Best Regards, > > JB > > > From forax at univ-mlv.fr Mon Apr 20 09:18:36 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 20 Apr 2009 18:18:36 +0200 Subject: Automatic Resource Management, V.2 In-Reply-To: <15e8b9d20904200846v61dad02amdff38481dc91c0a0@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904200846v61dad02amdff38481dc91c0a0@mail.gmail.com> Message-ID: <49ECA05C.3030207@univ-mlv.fr> Neal Gafter a ?crit : > On Sun, Apr 19, 2009 at 11:45 PM, Joshua Bloch wrote: > > >> Thanks for all your feedback on the Automatic Resource Management proposal. >> I have revised the proposal in light of these comments. >> > > > I am disappointed to see that this revision addresses none of the ergonomic > issues reported earlier, not even those that were identified in the previous > ARM proposal years ago and for which a solution was promised in the > revision. > > It's perhaps crystal clear for everyone but me :) Could you be a little more specific about the issues your talking about ? R?mi From jjb at google.com Mon Apr 20 09:19:47 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 20 Apr 2009 09:19:47 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <15e8b9d20904200846v61dad02amdff38481dc91c0a0@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904200846v61dad02amdff38481dc91c0a0@mail.gmail.com> Message-ID: <17b2302a0904200919l11b78994ueae9c9f146fe32a@mail.gmail.com> Neal, > I am disappointed to see that this revision addresses none of the ergonomic > issues reported earlier, not even those that were identified in the previous > ARM proposal years ago and for which a solution was promised in the > revision. > I am sorry you're disappointed. I do believe I addressed all the substantive issues that you raised: (1) "try" is not a natural keyword for the intended semantics. You didn't really back this one up. Other people have commented on what a great fit they think it is. So we'll just have to consider it an issue of taste, on which reasonable men may disagree. > (2) Checked exceptions from close() should be discarded for some clients. The revision says this: *5. Some failures of the **close** method can be safely ignored (e.g., closing a file that was open for read). Does the construct provide for this? * No. While this functionality seems attractive, it is not clear that it's worth the added complexity. As a practical matter these ?harmless exceptions? rarely if ever occur, so a program will be no more robust if these exceptions are ignored. If you feel you must ignore them, there is a workaround, but it isn't pretty: static void copy(String src, String dest) throws IOException { boolean done = false; try (InputStream in = new FileInputStream(src)) { try(OutputStream out = new FileOutputStream(dest)) { byte[] buf = new byte[8192]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); } done = true; } catch(IOException e) { if (!done) throw e; } } > > (3) The nesting of new behavior with old behavior in the try statement > is a poor fit for many clients. [Discussion of LineNumberReader snipped] The revision says this: 2. Does the construct allow access to resources after an exception is thrown from within the block, but before the resource is closed? Not directly. The need for this functionality is rare. The workaround is to nest a try-catch block inside the automatic resource management statement: try (LineNumberReader reader = getInput()) { try { parseInput(reader); } catch (CharacterCodingException ex) { report("Char encoding error at line " + reader.getLineNumber()); throw ex; // Rethrow the exception } } > > (4) The proposed construct doesn't retrofit onto many APIs in the > profile of use-cases for which it was designed. The revision says this: * 4. Does the construct support resource types whose termination method has a name other than **close**?* Not directly. There are two obvious ways in which the construct could have supported this functionality. One is to designate the termination method with an annotation. But this violates the rule that annotations cannot change the semantics of a program (JLS ?9.7). The other is to use an actual modifier to denote the termination method (the finally keyword has been proposed for this purpose). This would, however, require a class file format change, and a mandate changes to tools such as JavaDoc. The resulting construct would be more ?magical,? and wouldn't mesh as well with Java?s type system. The proposed construct is an ?80-20? solution. It is aimed squarely at solving the serious problem of Closeables. Most resources can be retrofitted to implement AutoCloseable, but a few can't (e.g., interface types that do not already contain a parameterless close method and class types that contain a parameterless close method with the wrong return type or semantics). For such resources, we recommend the use of an adapter, such as AutoLock above. The exact form of the adapter will differ depending on the details of the resource. Regards, Josh From neal at gafter.com Mon Apr 20 09:39:21 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 20 Apr 2009 09:39:21 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904200919l11b78994ueae9c9f146fe32a@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904200846v61dad02amdff38481dc91c0a0@mail.gmail.com> <17b2302a0904200919l11b78994ueae9c9f146fe32a@mail.gmail.com> Message-ID: <15e8b9d20904200939n772b4d3fm7cfcb7ba18133511@mail.gmail.com> On Mon, Apr 20, 2009 at 9:19 AM, Joshua Bloch wrote: > >> I am disappointed to see that this revision addresses none of the >> ergonomic issues reported earlier, not even those that were identified in >> the previous ARM proposal years ago and for which a solution was promised in >> the revision. >> > > > I am sorry you're disappointed. I do believe I addressed all the > substantive issues that you raised: By "addressed", you appear to mean the specification intentionally does nothing about them, and the prose reinforces the point that those issues have not been reflected in changes to the spec. While each issue may be in the excluded 20% of an 80-20 solution, .80*.80*.80*.80 = .41 (i.e. we have a 41% solution). From scolebourne at joda.org Mon Apr 20 10:24:11 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 20 Apr 2009 18:24:11 +0100 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> Message-ID: <4b4f45e00904201024q7986a036q19a21293deba9435@mail.gmail.com> 2009/4/20 Joshua Bloch : >> Why not return a List instead of an array (since >> Collections are generally nicer to use)? > > I did think about this, but I opted to stick with the pattern in enum types' > values() method. ?That decision was made for performance. Arguably the > performance issues are less important here, and the winds of change have > blown further away from arrays since then, so I'm definitely open to > switching this to a List if others think it's the right thing to do. Definitely List. Arrays should be considered a deprecated type in all JDK arrays at this point IMO. We need to move beyond thinking about raw performance as a reason. For example, I would have much preferred Enums to have had a Map of name to enum as a generated method. I currently have to have a code generator create this for every enum I write. >> > The printStackTrace method should be modified to append the stack traces >> for any suppressed exceptions. >> >> This might be difficult, particularly where there are a number of >> "cause" and "suppressed" exceptions (each of which might have their >> own) - it might be hard to associate each exception with its parent in >> the output (whereas currently "cause" has only one immediate parent >> and so it is easy to follow such a stack trace). > > > I did think about this, and came to the conclusion that it wasn't so bad. > ?The main problem is the "intermingling" of causes and suppressed > exceptions. ?I will come up with a format and put an example in the spec. The proposal should strive to include enhanced stack traces. > > (More generally, I think I'd prefer a single resource per ARM, as I > > think its a lot clearer overall and more consistent, but since you've > > allowed it in the proposal, I assume you'd want to keep to that > > style.) > Yes. May people really care about keeping the nesting depth low, and > the ability to combine resources in a single ARM statement does that for them. In my own work, I would probably choose to go with a code convention requiring each ARM block to only have a single declaring variable. Stephen From Ruslan at Shevchenko.Kiev.UA Mon Apr 20 11:23:55 2009 From: Ruslan at Shevchenko.Kiev.UA (Ruslan Shevchenko) Date: Mon, 20 Apr 2009 21:23:55 +0300 (EEST) Subject: Automatic Resource Management, V.2 In-Reply-To: <4b4f45e00904201024q7986a036q19a21293deba9435@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> <4b4f45e00904201024q7986a036q19a21293deba9435@mail.gmail.com> Message-ID: > 2009/4/20 Joshua Bloch : >>> Why not return a List instead of an array (since >>> Collections are generally nicer to use)? >> >> I did think about this, but I opted to stick with the pattern in enum >> types' >> values() method. ?That decision was made for performance. Arguably the >> performance issues are less important here, and the winds of change have >> blown further away from arrays since then, so I'm definitely open to >> switching this to a List if others think it's the right thing to do. > Hmm, all low-level Java API is build on arrays. Exists (IMHO) two valuable options: or rewrite all (getStackTrace(), reflection) use collections, or leave all (and getSupressedException()) in arrays. Introiduce one method which return list, when all others still arrays is wrong. So, better now leave all in arrays, then may-be do special step to change all arrays to collection interfaces in java low-level api, if this needed. From forax at univ-mlv.fr Mon Apr 20 11:33:40 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 20 Apr 2009 20:33:40 +0200 Subject: Enum.getConstants() Was: Automatic Resource Management, V.2 In-Reply-To: <4b4f45e00904201024q7986a036q19a21293deba9435@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> <4b4f45e00904201024q7986a036q19a21293deba9435@mail.gmail.com> Message-ID: <49ECC004.9090502@univ-mlv.fr> Stephen Colebourne a ?crit : > 2009/4/20 Joshua Bloch : > >>> Why not return a List instead of an array (since >>> Collections are generally nicer to use)? >>> >> I did think about this, but I opted to stick with the pattern in enum types' >> values() method. That decision was made for performance. Arguably the >> performance issues are less important here, and the winds of change have >> blown further away from arrays since then, so I'm definitely open to >> switching this to a List if others think it's the right thing to do. >> > > Definitely List. Arrays should be considered a deprecated type in all > JDK arrays at this point IMO. We need to move beyond thinking about > raw performance as a reason. > > For example, I would have much preferred Enums to have had a Map of > name to enum as a generated method. I currently have to have a code > generator create this for every enum I write. > Hi Stephen, Are you aware of Class.getEnumConstants() ? I think that using this method you can write only one generic code for all enums. Moreover, this map already exists in the class java.lang.Class, if you want to expose it, you can vote for that RFE http://bugs.sun.com/view_bug.do?bug_id=5034509 R?mi From scolebourne at joda.org Mon Apr 20 11:39:12 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 20 Apr 2009 19:39:12 +0100 Subject: Enum.getConstants() Was: Automatic Resource Management, V.2 In-Reply-To: <49ECC004.9090502@univ-mlv.fr> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> <4b4f45e00904201024q7986a036q19a21293deba9435@mail.gmail.com> <49ECC004.9090502@univ-mlv.fr> Message-ID: <4b4f45e00904201139w358cf006y99f66e27aa69cd4e@mail.gmail.com> 2009/4/20 R?mi Forax : > Stephen Colebourne a ?crit : >> For example, I would have much preferred Enums to have had a Map of >> name to enum as a generated method. I currently have to have a code >> generator create this for every enum I write. >> > > Hi Stephen, > Are you aware of Class.getEnumConstants() ? > I think that using this method you can write only one generic code for all > enums. > > Moreover, this map already exists in the class java.lang.Class, if you want > to expose it, you can vote for that RFE > http://bugs.sun.com/view_bug.do?bug_id=5034509 Yes, I'm aware of that method. Like all APIs, its working out what might be needed in advance, and I happen to think that the collections API is much more flexible than arrays. Stephen From paul.martin at gmail.com Mon Apr 20 12:59:04 2009 From: paul.martin at gmail.com (Paul Martin) Date: Mon, 20 Apr 2009 20:59:04 +0100 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> Message-ID: <4ce75f920904201259w13fc7ad2i8cd9007669ca9a2d@mail.gmail.com> Hi, >> > *5. Some failures of the **close** method can be safely ignored (e.g., >> ... >> > these exceptions are ignored. If you feel you must ignore them, there is >> > a >> > workaround, but it isn't pretty: >> >> Could you use a decorator to simplify the code a little, such as: >> >> public class HideAutoCloseableExceptionsAdapter implements AutoCloseable { >> ? ? ? ?private final AutoCloseable delegate; >> ? ? ? ?public HideAutoCloseableExceptionsAdapter(AutoCloseable delegate) { >> ? ? ? ? ? ? ? ?this.delegate = delegate; >> ? ? ? ?} >> ? ? ? ?@Override >> ? ? ? ?public void close() { >> ? ? ? ? ? ? ? ?try { >> ? ? ? ? ? ? ? ? ? ? ? ?delegate.close(); >> ? ? ? ? ? ? ? ?} catch (Exception e) { >> ? ? ? ? ? ? ? ? ? ? ? ?// Do nothing >> ? ? ? ? ? ? ? ?} >> ? ? ? ?} >> } >> >> static void copy(String src, String dest) throws IOException { >> ? ? ? InputStream in = new FileInputStream(src); >> ? ? ? try (new HideAutoCloseableExceptionsAdapter(in)) { >> ? ? ? ? ? try(OutputStream out = new FileOutputStream(dest)) { >> ? ? ? ? ? ? ? byte[] buf = new byte[8192]; >> ? ? ? ? ? ? ? int n; >> ? ? ? ? ? ? ? while ((n = in.read(buf)) >= 0) >> ? ? ? ? ? ? ? ? ? out.write(buf, 0, n); >> ? ? ? ? ? } >> ? ? ? } >> ? } >> } > > Yes; you could do that. ?Of course you'd have to write a separate decorator > for every such type. ?But it's worth mentioning that in the FAQ, and I will > do so. Just to clarify, I think that "HideAutoCloseableExceptionsAdapter" should work with any AutoCloseable (as long as the decorated object is declared before the try), so you could use that to address Neal Gafter's point 5: "*5. Some failures of the **close** method can be safely ignored (e.g.,closing a file that was open for read). Does the construct provide for this?". Simply using a standard decorator would seem to be a reasonable solution (since ignoring close exceptions would normally be done on a usage case-by-case basis). Giving the adapter a better name, such as "IgnoreCloseExceptionAdapter" might help, or even a static factory method such as AutoCloseable autocloseQuietly(AutoCloseable delegate). Also, one question from: http://docs.google.com/Doc?id=ddv8ts74_1d7tz65fd > java.util.Iterator&AutoDisposable: > "We can learn from C# here, and avoid the same mistake that C# avoided. The simple solution is to make the for-each loop dispose the iterator if it implements AutoDisposable, as C# does. The point, in part, is to make the proposed construct not just useful in code that already exists (criterion [2]), but useful in code yet to be written." How can the compiler do this (determine whether an Iterable is also AutoDisposable)? An Iterable interface passed to the for-each loop might not be defined as AutoDisposable, but its runtime implementation might be. I don't see how this can be statically determined by the compiler, and I wouldn't think that we would want the type of each Iterable to be checked at runtime to determine whether it also implements AutoDisposable (in case some objects are AutoDisposable and other objects are not). The alternative of using the static type of the interface to extend AutoDisposable would also seem to be fragile - AutoDisposable objects would then sometimes not get closed by for-each loops. ResourceSpecifications are known to be AutoDisposable for ARM, so the problem doesn't exist there (the statically-determined interface/class used must implement AutoDisposable). One further comment about suppressed exceptions: I would suspect that in many cases that the suppressed exception may indeed represent the original error (for example out of space when writing to a file), but the exception caused by the close represents later information (e.g. none of the previous writes to the were actually flushed to the disk). Perhaps exceptions thrown by close should be structured so that sufficient information is available in the exception itself to handle the error, so that suppressed exceptions should not often need to be consulted directly. Also, I haven't seen much discussion comparing similar implementations in other languages (but may have missed it). From what I can see (but I haven't actually used either), .Net ignores suppressed exceptions and uses 'using (resource decls) { ... }' without optional catch and finally blocks. Python's 'with' statement seems to allow both '__enter__' and '__exit__' methods (without a common interface), but again without suppressed exceptions. I can't see any advantages for either over this ARM proposal. Finally, have you considered a syntax such as: using (*ResourceDeclarations*) *statement* ? Then I think that you could access the variables in catch blocks before the close method is called (though admittedly this really only saves a single level of nesting): using (MyResource var) try { ... } catch (MyException e) { // caught before AutoCloseable.close(); var.xxx(); } as well as try using (MyResource var) { ... } catch (MyException e) { // caught after AutoCloseable.close(); // so can't access var } Regards, Paul From neal at gafter.com Mon Apr 20 13:07:42 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 20 Apr 2009 13:07:42 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <4ce75f920904201259w13fc7ad2i8cd9007669ca9a2d@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> <4ce75f920904201259w13fc7ad2i8cd9007669ca9a2d@mail.gmail.com> Message-ID: <15e8b9d20904201307s7049bda4i7f28fd5b94757ab8@mail.gmail.com> On Mon, Apr 20, 2009 at 12:59 PM, Paul Martin wrote: > Also, one question from: http://docs.google.com/Doc?id=ddv8ts74_1d7tz65fd > > > java.util.Iterator&AutoDisposable: > > "We can learn from C# here, and avoid the same mistake that C# avoided. > The simple solution is to make the for-each loop dispose the iterator if it > implements AutoDisposable, as C# does. The point, in part, is to make the > proposed construct not just useful in code that already exists (criterion > [2]), but useful in code yet to be written." > > How can the compiler do this (determine whether an Iterable is also > AutoDisposable)? An Iterable interface passed to the for-each loop > might not be defined as AutoDisposable, but its runtime implementation > might be. I don't see how this can be statically determined by the > compiler, and I wouldn't think that we would want the type of each > Iterable to be checked at runtime to determine whether it also > implements AutoDisposable (in case some objects are AutoDisposable and > other objects are not). It's not the type of the Iterable that I suggest have special treatment, it is the Iterator. Since that iterator object is created by compiler-generated code and never visible to the user program, it makes quite a lot of sense for the generated code to arrange its disposal when appropriate. From jjb at google.com Mon Apr 20 13:26:45 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 20 Apr 2009 13:26:45 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <4ce75f920904201259w13fc7ad2i8cd9007669ca9a2d@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> <4ce75f920904201259w13fc7ad2i8cd9007669ca9a2d@mail.gmail.com> Message-ID: <17b2302a0904201326x78707ebbt8cb0704c99486feb@mail.gmail.com> Paul, On Mon, Apr 20, 2009 at 12:59 PM, Paul Martin wrote: > Hi, > > >> > *5. Some failures of the **close** method can be safely ignored (e.g., > > > > Yes; you could do that. Of course you'd have to write a separate > decorator > > for every such type. But it's worth mentioning that in the FAQ, and I > will > > do so. > > Just to clarify, I think that "HideAutoCloseableExceptionsAdapter" > should work with any AutoCloseable (as long as the decorated object is > declared before the try), so you could use that to address Neal > Gafter's point 5: "*5. Some failures of the **close** method can be > safely ignored (e.g.,closing a file that was open for read). Does the > construct provide for this?". Simply using a standard decorator would > seem to be a reasonable solution (since ignoring close exceptions > would normally be done on a usage case-by-case basis). Giving the > adapter a better name, such as "IgnoreCloseExceptionAdapter" might > help, or even a static factory method such as AutoCloseable > autocloseQuietly(AutoCloseable delegate). Yes, you are correct. I didn't read your example carefully. You don't need a separate adapter for each type if you're willing to declare the instance outside the scope of the block. As for the "AutoCloseableItertor" stuff, I think it can wait for a subsequent release. I see it as scope-creep that distracts from the central goals of the proposal and reduces the likelihood that it will be successfully delivered into Java 7. Regards, Josh From neal at gafter.com Mon Apr 20 13:35:44 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 20 Apr 2009 13:35:44 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904201326x78707ebbt8cb0704c99486feb@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> <4ce75f920904201259w13fc7ad2i8cd9007669ca9a2d@mail.gmail.com> <17b2302a0904201326x78707ebbt8cb0704c99486feb@mail.gmail.com> Message-ID: <15e8b9d20904201335p2b88665cva6feaa05eda6e12e@mail.gmail.com> On Mon, Apr 20, 2009 at 1:26 PM, Joshua Bloch wrote: > As for the "AutoCloseableItertor" stuff, I think it can wait for a > subsequent release. I see it as scope-creep that distracts from the central > goals of the proposal and reduces the likelihood that it will be > successfully delivered into Java 7. If you don't design this now, you may well find it impossible to add later without introducing a breaking change. From jjb at google.com Mon Apr 20 14:07:55 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 20 Apr 2009 14:07:55 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <15e8b9d20904201335p2b88665cva6feaa05eda6e12e@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> <4ce75f920904201259w13fc7ad2i8cd9007669ca9a2d@mail.gmail.com> <17b2302a0904201326x78707ebbt8cb0704c99486feb@mail.gmail.com> <15e8b9d20904201335p2b88665cva6feaa05eda6e12e@mail.gmail.com> Message-ID: <17b2302a0904201407l299398a6s88d9efcf806c6002@mail.gmail.com> Neal, On Mon, Apr 20, 2009 at 1:35 PM, Neal Gafter wrote: > On Mon, Apr 20, 2009 at 1:26 PM, Joshua Bloch wrote: > >> As for the "AutoCloseableItertor" stuff, I think it can wait for a >> subsequent release. I see it as scope-creep that distracts from the >> central >> goals of the proposal and reduces the likelihood that it will be >> successfully delivered into Java 7. > > > If you don't design this now, you may well find it impossible to add later > without introducing a breaking change. > That's always possible. I'm not averse to thinking about it once the main work is done. I'd be especially interested in this functionality along with some API changes to Scanner, which implements Iterator (not Iterable) and has a close method but doesn't implement Closeable. Right now, you can't even use Scanner with a for-each loop, which is a shame. If you could use it (or some variant) with a for-each loop and the for-each loop automatically closed the underlying character source, that would be nice; it would eliminate a lot of boilerplate. In C# (as you know) IEnumerator extends IDisposeable. This is not an unreasonable design if you're starting from a clean sheet. We can't do that, which means we'd need to add the notions of AutoCloseIterable, whose iterator method returns an AutoCloseIterator, which extends both AutoCloseable and Iterable. The we'd have a for-each method whose behavior differed depending on the static type of its iterable. This is a bit scary, in that it violates a fundamental API design guideline. Is the result worth this complexity? Maybe. I do like the idea of being able to say (roughly): for(String token : Scanner.fancyFactory(file)) { ... // Do something with the token } Of course this would automatically close the underlying file, and there would be different versions of the factory to read different types from the file. But we're a long way from that. Josh Josh From neal at gafter.com Mon Apr 20 14:32:20 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 20 Apr 2009 14:32:20 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904201407l299398a6s88d9efcf806c6002@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> <4ce75f920904201259w13fc7ad2i8cd9007669ca9a2d@mail.gmail.com> <17b2302a0904201326x78707ebbt8cb0704c99486feb@mail.gmail.com> <15e8b9d20904201335p2b88665cva6feaa05eda6e12e@mail.gmail.com> <17b2302a0904201407l299398a6s88d9efcf806c6002@mail.gmail.com> Message-ID: <15e8b9d20904201432j350625e6md5c3b7c00f6c957c@mail.gmail.com> On Mon, Apr 20, 2009 at 2:07 PM, Joshua Bloch wrote: > Neal, > On Mon, Apr 20, 2009 at 1:35 PM, Neal Gafter wrote: > >> On Mon, Apr 20, 2009 at 1:26 PM, Joshua Bloch wrote: >> >>> As for the "AutoCloseableItertor" stuff, I think it can wait for a >>> subsequent release. I see it as scope-creep that distracts from the >>> central >>> goals of the proposal and reduces the likelihood that it will be >>> successfully delivered into Java 7. >> >> >> If you don't design this now, you may well find it impossible to add later >> without introducing a breaking change. >> > > That's always possible. I'm not averse to thinking about it once the main > work is done. > That's a reasonable approach, if you don't mind redoing the main work once that thinking is done. The risk is that you'll have too much invested in the design by that time to be flexible about addressing this. > In C# (as you know) IEnumerator extends IDisposeable. > I don't know that because it is not true. IEnumerator does not extend IDisposable ( http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx), though IEnumerator does ( http://msdn.microsoft.com/en-us/library/78dfe2yb.aspx). So as you can see, that's not necessary to get the desired behavior. > we'd need to add the notions of AutoCloseIterable, whose iterator method > returns an AutoCloseIterator, which extends both AutoCloseable and Iterable. > The we'd have a for-each method whose behavior differed depending on the static > type of its iterable. This is a bit scary, in that it violates a > fundamental API design guideline. > "need" is too strong a word; that is simply one design option, and I agree that this may be a poor starting point. However, if a solution isn't included when the feature is introduced, you may end up forcing this design. From jjb at google.com Mon Apr 20 14:48:36 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 20 Apr 2009 14:48:36 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <15e8b9d20904201432j350625e6md5c3b7c00f6c957c@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> <4ce75f920904201259w13fc7ad2i8cd9007669ca9a2d@mail.gmail.com> <17b2302a0904201326x78707ebbt8cb0704c99486feb@mail.gmail.com> <15e8b9d20904201335p2b88665cva6feaa05eda6e12e@mail.gmail.com> <17b2302a0904201407l299398a6s88d9efcf806c6002@mail.gmail.com> <15e8b9d20904201432j350625e6md5c3b7c00f6c957c@mail.gmail.com> Message-ID: <17b2302a0904201448t12299eb4p253995511f9417f0@mail.gmail.com> Neal, If you have a nice design, feel free to share it with the rest of us. Josh On Mon, Apr 20, 2009 at 2:32 PM, Neal Gafter wrote: > On Mon, Apr 20, 2009 at 2:07 PM, Joshua Bloch wrote: > >> Neal, >> On Mon, Apr 20, 2009 at 1:35 PM, Neal Gafter wrote: >> >>> On Mon, Apr 20, 2009 at 1:26 PM, Joshua Bloch wrote: >>> >>>> As for the "AutoCloseableItertor" stuff, I think it can wait for a >>>> subsequent release. I see it as scope-creep that distracts from the >>>> central >>>> goals of the proposal and reduces the likelihood that it will be >>>> successfully delivered into Java 7. >>> >>> >>> If you don't design this now, you may well find it impossible to add >>> later without introducing a breaking change. >>> >> >> That's always possible. I'm not averse to thinking about it once the main >> work is done. >> > > That's a reasonable approach, if you don't mind redoing the main work once > that thinking is done. The risk is that you'll have too much invested in the > design by that time to be flexible about addressing this. > > >> In C# (as you know) IEnumerator extends IDisposeable. >> > > I don't know that because it is not true. IEnumerator does not extend > IDisposable ( > http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx), > though IEnumerator does ( > http://msdn.microsoft.com/en-us/library/78dfe2yb.aspx). So as you can > see, that's not necessary to get the desired behavior. > > >> we'd need to add the notions of AutoCloseIterable, whose iterator method >> returns an AutoCloseIterator, which extends both AutoCloseable and Iterable. >> The we'd have a for-each method whose behavior differed depending on the static >> type of its iterable. This is a bit scary, in that it violates a >> fundamental API design guideline. >> > > "need" is too strong a word; that is simply one design option, and I agree > that this may be a poor starting point. However, if a solution isn't > included when the feature is introduced, you may end up forcing this design. > From markmahieu at googlemail.com Mon Apr 20 14:48:51 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Mon, 20 Apr 2009 22:48:51 +0100 Subject: Syntax patterns: more statistics. In-Reply-To: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> Message-ID: Hi Ruslan, Very nice - it'll be interesting to see the results when run against some other libraries I used for my own analysis. Thanks for sharing it! Regards, Mark 2009/4/20 Ruslan Shevchenko > Good day, community ! > > I want to share some statistics about java usage patterns, related to > some of coin-dev proposals. > > Main changes from previous post are: > - added counts for 'if' syntax constructions, so we can say, hom many > percents of if's can be eliminated by elvis operator ( [4-5]%) > - added counts for 'catch' syntax constructions, so we can say that > multicath eliminate 6-8% of all catch clauses. > - added count for big integers integers (where undescore can be > applicable, I guess this is x: x > 100000 || x < -10000) and for all > integer literals. > (underscore can be applicable to near 1%) > - added count for object-switch proposal by Ulf Zibis (refining, that > Left/Right part of expressions are first operand in equalirty expression > or object in method call) > - added count for rethrow proposal by Mark Mahieu (near 50% of all > catches in some packages (!) ). > - added count for catches inside finally block. (Is this is a real > problem [?]). > > If anybody whant run checks on own dataset or/and add own check > definitions: all procedure is the same as in my previous letter (see > http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001442.html) > except URL for last version > is > > http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerSourceInstaller-2.5.0p1.jar > > Now summary statistics for some well-known packages: > jetty (web server) > all catchs : 281 > all ifs : 764 > all integer literals : 2903 > big integer literals(undescores) : 25 > byte literal : 52 > catch in finally : 3 > elvis : 43 > instanceof switch : 8 > loop with remove : 0 > multi catch : 22 > object switch : 31 > rethrow clause : 34 > string in switch : 19 > Files:187 > > gwt-users (google java ajax client library) > all catchs : 171 > all ifs : 735 > all integer literals : 2282 > big integer literals(undescores) : 24 > byte literal : 2 > catch in finally : 2 > elvis : 30 > instanceof switch : 6 > loop with remove : 5 > multi catch : 9 > object switch : 27 > rethrow clause : 84 > string in switch : 10 > Files:920 > > hibernate (ORM toolkit) > all catchs : 650 > all ifs : 2410 > all integer literals : 3240 > big integer literals(undescores) : 12 > byte literal : 1 > catch in finally : 27 > elvis : 182 > instanceof switch : 28 > loop with remove : 12 > multi catch : 25 > object switch : 94 > rethrow clause : 450 > string in switch : 86 > Files:1372 > > openjdk7 (standard java library) > all catchs : 8404 > all ifs : 28494 > all integer literals : 124356 > big integer literals(undescores) : 4066 > byte literal : 1454 > catch in finally : 103 > elvis : 877 > instanceof switch : 318 > loop with remove : 62 > multi catch : 411 > object switch : 1363 > rethrow clause : 3264 > string in switch : 445 > Files:9252 > > Hope, this data will be useful in some cases. > Regards ! > > > > From i30817 at gmail.com Mon Apr 20 14:49:32 2009 From: i30817 at gmail.com (Paulo Levi) Date: Mon, 20 Apr 2009 22:49:32 +0100 Subject: Non-proposal: Final Interfaces Message-ID: <212322090904201449u4e19e48apc93722035555a317@mail.gmail.com> *I know this is much out of date for consideration, but i think that this is a idea that would really help library evolution, and i did not see any of this kind of strategy floating around in the other proposals. * * * *AUTHOR(S):* Paulo Levi Martins Faria, a student at FCUL, faculdade de ciencias da universidade de lisboa at Lisbon, Portugal. *OVERVIEW* A way for interfaces to be used as references outside a package, but the only implementations of them to exist on a package, to allow the evolution (adding) of methods to interfaces and all their implementations. FEATURE SUMMARY: insted of declaring interfaces as: package xyz; public interface A{ } or package xyz; interface A{ } declare them as : package xyz; public final interface A{ } And all implementations or extensions of A must be in the package xyz MAJOR ADVANTAGE: What makes the proposal a favorable change? This would allow library authors to control the evolution of the implementations of a common interface, deprecating old methods, while at the same time allowing clients to program to the interfaces. The prohibition of implementation/extension outside of package allows the library author to control the package evolution completly. I have personally seen cases where performance reasons lead to dangerous downcasts or using the raw type, and/or subclassing of various classes, to implement something more efficiently than the library core can, because of public interfaces. MAJOR BENEFIT: The jdk can decide if certain interfaces are not likely to be extended outside of the library, and thus control api evolution more completly. All methods that are deprecated can be deleted on the interface and all implementations (since they are controlled completly.) MAJOR DISADVANTAGE: Can not be retrofitted to existing api's (easily). Somewhat overlapping with abstract classes, but more powerfull. Losses flexibility of extension for clients, a risk i am well disposed towards. ALTERNATIVES: Can the benefits and advantages be had some way without a language change? Can think of a way how. *EXAMPLES* Show us the code! SIMPLE EXAMPLE: Show the simplest possible program utilizing the new feature. ADVANCED EXAMPLE: Show advanced usage(s) of the feature. *DETAILS* SPECIFICATION: Describe how the proposal affects the grammar, type system, and meaning of expressions and statements in the Java Programming Language as well as any other known impacts. COMPILATION: How would the feature be compiled to class files? Show how the simple and advanced examples would be compiled. Compilation can be expressed as at least one of a desugaring to existing source constructs and a translation down to bytecode. If a new bytecode is used or the semantics of an existing bytecode are changed, describe those changes, including how they impact verification. Also discuss any new class file attributes that are introduced. Note that there are many downstream tools that consume class files and that they may to be updated to support the proposal! I don't think that this changes compilation beyond the type checj TESTING: How can the feature be tested? Try to implement extend a final interface outside its package. LIBRARY SUPPORT: Are any supporting libraries needed for the feature? No. REFLECTIVE APIS: Do any of the various and sundry reflection APIs need to be updated? This list of reflective APIs includes but is not limited to core reflection (java.lang.Class and java.lang.reflect.*), javax.lang.model.*, the doclet API, and JPDA. Don't think so. OTHER CHANGES: Do any other parts of the platform need be updated too? Possibilities include but are not limited to JNI, serialization, and output of the javadoc tool. No. MIGRATION: Create a new final sub interface to public one on the api, deplicate methods taking that interface to use the new one. Deprecate the old methods and interfaces. Wait for the pichforks. *COMPATIBILITY* BREAKING CHANGES: Are any previously valid programs now invalid? If so, list one. None EXISTING PROGRAMS: How do source and class files of earlier platform versions interact with the feature? Can any new overloadings occur? Can any new overriding occur? No *REFERENCES* From neal at gafter.com Mon Apr 20 15:13:56 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 20 Apr 2009 15:13:56 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904201448t12299eb4p253995511f9417f0@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <4ce75f920904200532g14eabb81qd26cbfc3116084ee@mail.gmail.com> <17b2302a0904200814m24254707l20501fc5f8854290@mail.gmail.com> <4ce75f920904201259w13fc7ad2i8cd9007669ca9a2d@mail.gmail.com> <17b2302a0904201326x78707ebbt8cb0704c99486feb@mail.gmail.com> <15e8b9d20904201335p2b88665cva6feaa05eda6e12e@mail.gmail.com> <17b2302a0904201407l299398a6s88d9efcf806c6002@mail.gmail.com> <15e8b9d20904201432j350625e6md5c3b7c00f6c957c@mail.gmail.com> <17b2302a0904201448t12299eb4p253995511f9417f0@mail.gmail.com> Message-ID: <15e8b9d20904201513o5eaedb52p72ada0520eea824a@mail.gmail.com> On Mon, Apr 20, 2009 at 2:48 PM, Joshua Bloch wrote: > Neal, > If you have a nice design, feel free to share it with the rest of us. > I think you know I believe this problem space is best addressed by APIs rather than (less flexible) language features. Still, I repeat my suggestion that you look at the C# solution as a starting point. > > Josh > > > On Mon, Apr 20, 2009 at 2:32 PM, Neal Gafter wrote: > >> On Mon, Apr 20, 2009 at 2:07 PM, Joshua Bloch wrote: >> >>> Neal, >>> On Mon, Apr 20, 2009 at 1:35 PM, Neal Gafter wrote: >>> >>>> On Mon, Apr 20, 2009 at 1:26 PM, Joshua Bloch wrote: >>>> >>>>> As for the "AutoCloseableItertor" stuff, I think it can wait for a >>>>> subsequent release. I see it as scope-creep that distracts from the >>>>> central >>>>> goals of the proposal and reduces the likelihood that it will be >>>>> successfully delivered into Java 7. >>>> >>>> >>>> If you don't design this now, you may well find it impossible to add >>>> later without introducing a breaking change. >>>> >>> >>> That's always possible. I'm not averse to thinking about it once the >>> main work is done. >>> >> >> That's a reasonable approach, if you don't mind redoing the main work once >> that thinking is done. The risk is that you'll have too much invested in the >> design by that time to be flexible about addressing this. >> >> >>> In C# (as you know) IEnumerator extends IDisposeable. >>> >> >> I don't know that because it is not true. IEnumerator does not extend >> IDisposable ( >> http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx), >> though IEnumerator does ( >> http://msdn.microsoft.com/en-us/library/78dfe2yb.aspx). So as you can >> see, that's not necessary to get the desired behavior. >> >> >>> we'd need to add the notions of AutoCloseIterable, whose iterator method >>> returns an AutoCloseIterator, which extends both AutoCloseable and Iterable. >>> The we'd have a for-each method whose behavior differed depending on the static >>> type of its iterable. This is a bit scary, in that it violates a >>> fundamental API design guideline. >>> >> >> "need" is too strong a word; that is simply one design option, and I agree >> that this may be a poor starting point. However, if a solution isn't >> included when the feature is introduced, you may end up forcing this design. >> > > From scolebourne at joda.org Mon Apr 20 15:24:51 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 20 Apr 2009 23:24:51 +0100 Subject: Syntax patterns: more statistics. In-Reply-To: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> Message-ID: <4b4f45e00904201524q3d1660e8l3d02ef7b07fe29fe@mail.gmail.com> 2009/4/20 Ruslan Shevchenko : > Main changes from previous post are: > ?- added counts for 'if' syntax constructions, so we can say, hom many > ?percents of if's can be eliminated by elvis operator ( [4-5]%) > ?- added counts for 'catch' syntax constructions, so we can say that > multicath eliminate 6-8% of all catch clauses. > ?- added count for big integers integers (where undescore can be > applicable, I guess this is x: x > 100000 || x < -10000) and for all > integer literals. > ? (underscore can be applicable to near 1%) > ?- added count for object-switch proposal by Ulf Zibis (refining, that > Left/Right part of expressions are first operand in equalirty expression > or object in method call) > ?- added count for rethrow proposal by Mark Mahieu (near 50% of all > catches in some packages (!) ). > ?- added count for catches inside finally block. (Is this is a real > problem [?]). Good work, and some interesting figures - multi-catch and elvis are both higher than I would have guessed. Stephen From paul.martin at gmail.com Mon Apr 20 15:36:21 2009 From: paul.martin at gmail.com (paul.martin at gmail.com) Date: Mon, 20 Apr 2009 22:36:21 +0000 Subject: Automatic Resource Management, V.2 In-Reply-To: <15e8b9d20904201432j350625e6md5c3b7c00f6c957c@mail.gmail.com> Message-ID: <0016e6d7eaacdc64af0468042821@google.com> Hi, On Apr 20, 2009 10:32pm, Neal Gafter wrote: > On Mon, Apr 20, 2009 at 2:07 PM, Joshua Bloch jjb at google.com> wrote: ... >> In C# (as you know) IEnumerator extends IDisposeable. > I don't know that because it is not true. IEnumerator does not extend > IDisposable > (http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx), > though IEnumerator does > (http://msdn.microsoft.com/en-us/library/78dfe2yb.aspx). So as you can > see, that's not necessary to get the desired behavior. MSDN's foreach documentation actually describes C#'s expansion, which does seem to use reflection-style type casting to determine whether an enumerator implements IDisposable or not. From http://msdn.microsoft.com/en-us/library/aa664754.aspx (start quote) If the collection expression is of a type that implements the collection pattern (as defined above), the expansion of the foreach statement is: Copy Code E enumerator = (collection).GetEnumerator(); try { while (enumerator.MoveNext()) { ElementType element = (ElementType)enumerator.Current; statement; } } finally { IDisposable disposable = enumerator as System.IDisposable; if (disposable != null) disposable.Dispose(); } Significant optimizations of the above are often easily available. If the type E implements System.IDisposable, then the expression (enumerator as System.IDisposable) will always be non-null and the implementation can safely substitute a simple conversion for a possibly more expensive type test. Conversely, if the type E is sealed and does not implement System.IDisposable, then the expression (enumerator as System.IDisposable) will always evaluate to null. In this case, the implementation can safely optimize away the entire finally clause. (end quote) I expect that a similar mechanism would be possible in Java, though there would always be a trade-off on performance (in particular, I don't see how the runtime check can be avoided if an interface/non-final class is used). Another perspective may be to consider that with try (resource) { } (and C#'s using), the programmer is explicitly stating that automatic resource management is required; the purpose of this is mainly to simplify the error handling code - it is not to prevent the programmer from forgetting to take any action to close the resource. However, automatically closing the Iterator in a for-each loop seems different to that - it is now the compiler that is making the decision that a resource (may) need to be closed. This perspective could suggest that a way of explicitly indicating to the for-each loop that the Iterator is in fact AutoDisposable might be useful (even if its interface would ordinarily suggest otherwise at compile-time). Candidate solutions could include: - Casting the Iterable to (a subtype of) AutoDisposableIterable where necessary (which then returns AutoDisposableIterator). This would probably mean that close() would be defined as throwing Exception however, unless a cast to a subtype was used. - try for (T : myIterable) { } (though that specific syntax is probably ambiguous) - for try (T : myIterable) { } (would be ok?) Analysis tools such as FindBugs could potentially be extended to catch many (though not all) errors where AutoDisposable Iterators/Iterables are being used incorrectly (whatever the solution). Another alternative might be to have the try use a factory method that returns decorating Iterable, which when closed by the ARM block also closes the associated Iterator. However that is probably nastier than using a normal for ( ; ;) loop instead. Regards, Paul From tball at google.com Mon Apr 20 15:39:34 2009 From: tball at google.com (Tom Ball) Date: Mon, 20 Apr 2009 15:39:34 -0700 Subject: Syntax patterns: more statistics. In-Reply-To: <4b4f45e00904201524q3d1660e8l3d02ef7b07fe29fe@mail.gmail.com> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904201524q3d1660e8l3d02ef7b07fe29fe@mail.gmail.com> Message-ID: It is indeed good work, but like all metrics, these measurements need to be treated as rough indicators rather than firm values. The Jackpot project (an automated refactoring tool) had a rule to change if statements to conditional expressions -- it found a lot of candidates, but most were rejected by developers using the tool. When asked, developers gave readability as the primary concern, stating that it was worth some verbiage to make the code easier to read. My hunch is that a lot of potential elvis uses will be rejected for similar reasons. Tom On Mon, Apr 20, 2009 at 3:24 PM, Stephen Colebourne wrote: > 2009/4/20 Ruslan Shevchenko : >> Main changes from previous post are: >> ?- added counts for 'if' syntax constructions, so we can say, hom many >> ?percents of if's can be eliminated by elvis operator ( [4-5]%) >> ?- added counts for 'catch' syntax constructions, so we can say that >> multicath eliminate 6-8% of all catch clauses. >> ?- added count for big integers integers (where undescore can be >> applicable, I guess this is x: x > 100000 || x < -10000) and for all >> integer literals. >> ? (underscore can be applicable to near 1%) >> ?- added count for object-switch proposal by Ulf Zibis (refining, that >> Left/Right part of expressions are first operand in equalirty expression >> or object in method call) >> ?- added count for rethrow proposal by Mark Mahieu (near 50% of all >> catches in some packages (!) ). >> ?- added count for catches inside finally block. (Is this is a real >> problem [?]). > > Good work, and some interesting figures - multi-catch and elvis are > both higher than I would have guessed. > > Stephen > > From i30817 at gmail.com Mon Apr 20 15:49:21 2009 From: i30817 at gmail.com (Paulo Levi) Date: Mon, 20 Apr 2009 23:49:21 +0100 Subject: Non-proposal: Final Interfaces In-Reply-To: <212322090904201449u4e19e48apc93722035555a317@mail.gmail.com> References: <212322090904201449u4e19e48apc93722035555a317@mail.gmail.com> Message-ID: <212322090904201549h73d23c82t728ef2f4b15a45ac@mail.gmail.com> Actually the "All methods that are deprecated can be deleted on the interface and all implementations (since they are controlled completly.)" Doesn't apply since clients use the methods, but methods can be added "(since they are controlled completly.)". On Mon, Apr 20, 2009 at 10:49 PM, Paulo Levi wrote: > *I know this is much out of date for consideration, but i think that this > is a idea that would really help library evolution, and i did not see any of > this kind of strategy floating around in the other proposals. > * > > * > * > > *AUTHOR(S):* Paulo Levi Martins Faria, a student at FCUL, faculdade de > ciencias da universidade de lisboa at Lisbon, Portugal. > > *OVERVIEW* > > A way for interfaces to be used as references outside a package, but the > only implementations of them to exist on a package, to allow the evolution > (adding) of methods to interfaces and all their implementations. > > FEATURE SUMMARY: > > insted of declaring interfaces as: > > package xyz; > > public interface A{ > > } or > > package xyz; > > interface A{ > > } > > declare them as : > > package xyz; > > public final interface A{ > > } > > And all implementations or extensions of A must be in the package xyz > > > MAJOR ADVANTAGE: What makes the proposal a favorable change? > > This would allow library authors to control the evolution of the > implementations of a common interface, deprecating old methods, while at the > same time allowing clients to program to the interfaces. The prohibition of > implementation/extension outside of package allows the library author to > control the package evolution completly. I have personally seen cases where > performance reasons lead to dangerous downcasts or using the raw type, > and/or subclassing of various classes, to implement something more > efficiently than the library core can, because of public interfaces. > > MAJOR BENEFIT: > > The jdk can decide if certain interfaces are not likely to be extended > outside of the library, and thus control api evolution more completly. > > All methods that are deprecated can be deleted on the interface and all > implementations (since they are controlled completly.) > > MAJOR DISADVANTAGE: > > Can not be retrofitted to existing api's (easily). > > Somewhat overlapping with abstract classes, but more powerfull. > > Losses flexibility of extension for clients, a risk i am well disposed > towards. > > ALTERNATIVES: Can the benefits and advantages be had some way without a > language change? > > Can think of a way how. > > *EXAMPLES* > > Show us the code! > > SIMPLE EXAMPLE: Show the simplest possible program utilizing the new > feature. > > ADVANCED EXAMPLE: Show advanced usage(s) of the feature. > > *DETAILS* > > SPECIFICATION: Describe how the proposal affects the grammar, type system, > and meaning of expressions and statements in the Java Programming Language > as well as any other known impacts. > > COMPILATION: How would the feature be compiled to class files? Show how the > simple and advanced examples would be compiled. Compilation can be expressed > as at least one of a desugaring to existing source constructs and a > translation down to bytecode. If a new bytecode is used or the semantics of > an existing bytecode are changed, describe those changes, including how they > impact verification. Also discuss any new class file attributes that are > introduced. Note that there are many downstream tools that consume class > files and that they may to be updated to support the proposal! > > I don't think that this changes compilation beyond the type checj > > TESTING: How can the feature be tested? > > Try to implement extend a final interface outside its package. > > LIBRARY SUPPORT: Are any supporting libraries needed for the feature? > > No. > > REFLECTIVE APIS: Do any of the various and sundry reflection APIs need to > be updated? This list of reflective APIs includes but is not limited to core > reflection (java.lang.Class and java.lang.reflect.*), javax.lang.model.*, > the doclet API, and JPDA. > > Don't think so. > > OTHER CHANGES: Do any other parts of the platform need be updated too? > Possibilities include but are not limited to JNI, serialization, and output > of the javadoc tool. > > No. > > MIGRATION: > > Create a new final sub interface to public one on the api, deplicate > methods taking that interface to use the new one. Deprecate the old methods > and interfaces. Wait for the pichforks. > > *COMPATIBILITY* > > BREAKING CHANGES: Are any previously valid programs now invalid? If so, > list one. > > None > > EXISTING PROGRAMS: How do source and class files of earlier platform > versions interact with the feature? Can any new overloadings occur? Can any > new overriding occur? > > No > > *REFERENCES* > > From vapor1 at teleport.com Mon Apr 20 17:21:00 2009 From: vapor1 at teleport.com (Derek Foster) Date: Mon, 20 Apr 2009 20:21:00 -0400 (EDT) Subject: Automatic Resource Management, V.2 (wrt. 'finally') Message-ID: <11173751.1240273260729.JavaMail.root@elwamui-muscovy.atl.sa.earthlink.net> -----Original Message----- >From: Joshua Bloch >Sent: Apr 20, 2009 9:19 AM >To: coin-dev >Subject: Re: Automatic Resource Management, V.2 > >Neal, > >I do believe I addressed all the substantive issues that you raised: > >>(1) "try" is not a natural keyword for the intended semantics. > >> (3) The nesting of new behavior with old behavior in the try statement >> is a poor fit for many clients. [Discussion of LineNumberReader snipped] > >You didn't really back this one up. Other people have commented on what a >great fit they think it is. So we'll just have to consider it an issue of >taste, on which reasonable men may disagree. Hi, Josh. As much as I agree with the general goals of the ARM proposal, I'd like to point out that Neal isn't the only one to hold this opinion. I had the same reaction as Neal did when I saw that "try" was being used for this purpose. The 'try..catch..finally' construct is already one of the more complicated constructs in Java. I hate to see it complicated further by adding new functionality to it that really has nothing to do with its primary purpose (that of attempting an operation and then providing places for someone to handle exceptions from it). Also, I hate to see a mechanism that is basically type-agnostic be expanded with something that is so specific to file-based I/O. Your recent ARM proposal description, for instance, was complicated by the question of what to do with any other 'catch' or 'finally' clauses which might be present on the 'try'. The proposal was also somewhat unclear on whether or not a 'try' without any 'catches' or 'finally' clauses now becomes legal Java even if there are no initializers present. If another keyword had been chosen, these would not even have been issues that the proposal needed to address. I rather liked the suggestion that various people put forth a while ago for using the 'protected' keyword instead. Since it seems that it is not going to be used for a lock-related proposal anymore, why not use it for this? protected (FileReader in = new FileReader(whatever)) { doStuff(in.read()); } This would provide a nice, orthogonal feature that would be unrelated to the 'try' keyword, thus making for two smaller simpler features (protected and try) rather than one big complicated one (protected+try, as in the current proposal). Its syntax would also then be more analogous to the 'synchronized' keyword, which this feature is (IMHO) MUCH more semantically similar to than it is to 'try'. Like 'synchronized' (at least as far as closing/unlocking of resources go), ARM is a higher-level interface to a subset of functionality that is usually performed using try..finally. I don't think that the fact that closing of resources is usually IMPLEMENTED using 'try' is a good reason to make its INTERFACE syntactically similar to a try..catch..finally block, which has very different semantics. >The revision says this: > >* 4. Does the construct support resource types whose termination method has >a name other than **close**?* > >Not directly. There are two obvious ways in which the construct could have >supported this functionality. One is to designate the termination method >with an annotation. But this violates the rule that annotations cannot >change the semantics of a program (JLS ?9.7). The other is to use an actual >modifier to denote the termination method (the finally keyword has been >proposed for this purpose). This would, however, require a class file format >change, and a mandate changes to tools such as JavaDoc. The resulting >construct would be more ?magical,? and wouldn't mesh as well with Java?s >type system. This is my number one gripe with the current proposal: It's not extensible due to its dependence on the AutoCloseable interface and the need for a method named "close()". It's too specific to files. If I want to use it for locks, for disposeable objects, or for other similar kinds of resources, I have to jump through weird hoops and use adapter classes and so forth, or settle for my 'unlock' method being called 'close' just to fit the interface. Not Good. This is true even if I am coding up my own lock objects (with a 'lock()' method that returns 'this') rather than using those provided by java.util.concurrent. There is a better solution to this problem, which avoids the technical issues that have been raised above against annotations and the 'finally' keyword. It is possible to combine these approaches to get the desired behavior (a type-system-independent way to designate a closing method) without forcing a change to the class file format. In fact there is already an existing precedent for doing this: Enums. When the compiler compiles an 'enum' declaration, it generates a hidden annotation on the generated class, which identifies it as an enumerated type. This has implications for the compiler (such as the fact that another class can't extend such a type). Thus, the "annotations don't change program semantics" rule is being slightly bent in this case, but its spirit is preserved, since the annotation can't be used or even seen by ordinary users -- just by the compiler, and by JDK methods like "Class.isEnum". In the ARM proposal, we could do the same thing with the 'finally' keyword. If the compiler notices that the 'finally' keyword is present on a method, it can supply a hidden annotation on that method which qualifies it within the class file, so that this: public finally void dispose(); // or unlock(), or... desugars to this: @AutoClose public void dispose(); with the @AutoClose annotation being invisible to normal users of Java, in the same way as the annotation used to declare enum types currently is. Some further restrictions would be needed: 1) It is a compile-time error if the 'finally' keyword appears on more than one method within a type declaration. 2) It is a compile-time error if a type extends multiple supertypes with 'finally' methods which have incompatible signatures, but does not designate one of its own methods with the "finally" keyword. (This guarantees uniqueness of finally methods). With these rules in place, when attempting to compile an instance of the ARM construct, the compiler can then search up the inheritance tree for the first instance of a method with the @AutoClose annotation, and use that method it if it's present (or else provoke a compiler error: "this type has no finally method"). As far as I can see, the above approach is much less limiting than designating a magic interface (or pre-specified set of interfaces) such as AutoCloseable. It will make it much easier for existing classes and interfaces to be retrofitted to support ARM, since it won't affect their inheritance hierarchies. Note that it is still possible to define a class like AutoCloseable in this scenario, should someone still want to do so: interface AutoCloseable { finally void close() throws Exception; } Derek From vapor1 at teleport.com Mon Apr 20 21:37:52 2009 From: vapor1 at teleport.com (Derek Foster) Date: Tue, 21 Apr 2009 00:37:52 -0400 (EDT) Subject: PROTOTYPE: Message-ID: <24411601.1240288672402.JavaMail.root@elwamui-muscovy.atl.sa.earthlink.net> Hi, Bruce! I just wanted to offer a huge "THANK YOU!!!" for following up on this and doing actual implementation work. I have had a product release at work, as well as some challenges in my personal life, that have pretty much occupied all of my free time and have made it all but impossible over the last few weeks for me to do any more with Project Coin than to try to read the emails as they come in. Doing compiler implementation work was pretty much out of the question. It has been tremendously helpful that you have been continuing to work on these proposals in my absence. (I am now trying to work through the backlog of Coin-related emails that I wanted to answer but did not have time to, and I will try to update my proposals with the results of various list conversations regarding them ASAP.) Anyway, in reply to your earlier question about whether or not it was necessary to support underscores at the beginning or end of sequences of digits... I don't have a firm opinion on this. My proposal was written to allow it because I saw no particular reason to disallow it, but I must admit I can't think of any particularly compelling use cases for this behavior. I am considering rewriting my proposal to disallow it and instead go with your suggestion that underscores only be allowed within sequences of digits, instead of around them as well. (However, as I mentioned, I am somewhat short on time, although not as short as I was recently.) Do others have opinions as to whether this feature (the ability to put underscores at the beginning or end of sequences of digits within a number, such as "0x_5", "0x5_" or "52_") is either desirable or problematic? It seems that Bruce is feeling that it's unnecessary and possibly confusing, and I am now finding myself leaning somewhat towards that opinion myself, although if someone were to present a good example of a case where it might be useful, I might change my mind. Derek -----Original Message----- >From: Bruce Chapman >Sent: Apr 20, 2009 6:37 AM >To: coin-dev at openjdk.java.net >Cc: Derek Foster >Subject: PROTOTYPE: > >A prototype compiler for the follow proposals > >Underscores in numbers >Narrow Hexadecimal and Binary Integer Literals >Byte and Short Integer Literal Suffixes > >is now available at >https://kijaro.dev.java.net/servlets/ProjectDocumentList?folderID=11247&expandFolder=11247&folderID=8804 > >I have bundled them altogether so that the interaction between >underscores and the others can be assessed and so that the two new >literal forms can be compared side by side. > >There is one fault in the test class, fix that and it should compile and >run. > >-- Joe, should we update the proposals with this information or is this >email sufficient? > > >Bruce From Ruslan at Shevchenko.Kiev.UA Mon Apr 20 23:59:30 2009 From: Ruslan at Shevchenko.Kiev.UA (Ruslan Shevchenko) Date: Tue, 21 Apr 2009 09:59:30 +0300 (EEST) Subject: Syntax patterns: more statistics. In-Reply-To: References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> Message-ID: > Hi Ruslan, > > Very nice - it'll be interesting to see the results when run against some > other libraries I used for my own analysis. Thanks for sharing it! > Thanks. Results (about rethrow) was very surprising for me. Trying to analyze: I just see, that all this is 'system libraries' which provide some layer, i. e. may be have sence add some application code (open-source ERP, for example) to dataset. From Ruslan at Shevchenko.Kiev.UA Tue Apr 21 00:08:41 2009 From: Ruslan at Shevchenko.Kiev.UA (Ruslan Shevchenko) Date: Tue, 21 Apr 2009 10:08:41 +0300 (EEST) Subject: Syntax patterns: more statistics. In-Reply-To: <4b4f45e00904201524q3d1660e8l3d02ef7b07fe29fe@mail.gmail.com> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904201524q3d1660e8l3d02ef7b07fe29fe@mail.gmail.com> Message-ID: > > Good work, and some interesting figures - multi-catch and elvis are > both higher than I would have guessed. > Thanks. I also surprised by number of catches, which do only rethrow Trying to figure details, this is percents by packages: Jetty Gwt-user hibernate openjdk elvis/ifs*100 5.63 4.08 7.55 3.08 multicatch/cath*100 7.83 5.26 3.85 4.89 rethrow/cath*100 12.1 49.12 69.23 38.84 Also (as I wrote in previous code) all libraries (which I random get from hard drive) are system libraries, so exists sense look at application code. Also some organizations does not like null-s in API (I read, that google have such policy, but facts about gwt-user contradict this) > Stephen > > From Ruslan at Shevchenko.Kiev.UA Tue Apr 21 00:15:09 2009 From: Ruslan at Shevchenko.Kiev.UA (Ruslan Shevchenko) Date: Tue, 21 Apr 2009 10:15:09 +0300 (EEST) Subject: Syntax patterns: more statistics. In-Reply-To: References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904201524q3d1660e8l3d02ef7b07fe29fe@mail.gmail.com> Message-ID: <0d48edf00d3533cd9adab8ce7edc7fa6.squirrel@wmail.gradsoft.ua> > It is indeed good work, but like all metrics, these measurements need > to be treated as rough indicators rather than firm values. The Yes. > Jackpot project (an automated refactoring tool) had a rule to change > if statements to conditional expressions -- it found a lot of > candidates, but most were rejected by developers using the tool. When > asked, developers gave readability as the primary concern, stating > that it was worth some verbiage to make the code easier to read. My > hunch is that a lot of potential elvis uses will be rejected for > similar reasons. > Yes. How we can count this: look at languages where elvis implemented and find percentage of applicability. What we need for this (?) - just parser. So, in priniciple if exists publicy aviable groovy or C# parser (or compiler/interpreter which provide access to AST), we can try hack one, to count unused possibilities and expect that in java number would be near. > Tom > > On Mon, Apr 20, 2009 at 3:24 PM, Stephen Colebourne > wrote: >> 2009/4/20 Ruslan Shevchenko : >>> Main changes from previous post are: >>> ?- added counts for 'if' syntax constructions, so we can say, hom many >>> ?percents of if's can be eliminated by elvis operator ( [4-5]%) >>> ?- added counts for 'catch' syntax constructions, so we can say that >>> multicath eliminate 6-8% of all catch clauses. >>> ?- added count for big integers integers (where undescore can be >>> applicable, I guess this is x: x > 100000 || x < -10000) and for all >>> integer literals. >>> ? (underscore can be applicable to near 1%) >>> ?- added count for object-switch proposal by Ulf Zibis (refining, that >>> Left/Right part of expressions are first operand in equalirty >>> expression >>> or object in method call) >>> ?- added count for rethrow proposal by Mark Mahieu (near 50% of all >>> catches in some packages (!) ). >>> ?- added count for catches inside finally block. (Is this is a real >>> problem [?]). >> >> Good work, and some interesting figures - multi-catch and elvis are >> both higher than I would have guessed. >> >> Stephen >> >> > > From scolebourne at joda.org Tue Apr 21 00:53:13 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Tue, 21 Apr 2009 08:53:13 +0100 Subject: PROTOTYPE: In-Reply-To: <24411601.1240288672402.JavaMail.root@elwamui-muscovy.atl.sa.earthlink.net> References: <24411601.1240288672402.JavaMail.root@elwamui-muscovy.atl.sa.earthlink.net> Message-ID: <49ED7B69.7030704@joda.org> Derek Foster wrote: > Do others have opinions as to whether this feature (the ability to put underscores at the beginning or end of sequences of digits within a number, such as "0x_5", "0x5_" or "52_") is either desirable or problematic? It seems that Bruce is feeling that it's unnecessary and possibly confusing, and I am now finding myself leaning somewhat towards that opinion myself, although if someone were to present a good example of a case where it might be useful, I might change my mind. I would have expected no underscores at start or end, and no adjacent underscores. That seems like the main case. Stephen From markmahieu at googlemail.com Tue Apr 21 01:04:14 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Tue, 21 Apr 2009 09:04:14 +0100 Subject: Syntax patterns: more statistics. In-Reply-To: <0d48edf00d3533cd9adab8ce7edc7fa6.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904201524q3d1660e8l3d02ef7b07fe29fe@mail.gmail.com> <0d48edf00d3533cd9adab8ce7edc7fa6.squirrel@wmail.gradsoft.ua> Message-ID: That's a good idea, although again we'd need to be very careful about interpreting the results. For example, if we look at uses of both ?: and ?. in Groovy code, we should note that the Elvis operator is a relatively recent addition to the language, whereas the safe-navigation operator has been supported for much longer. In addition, much of the Groovy code I've seen uses the safe-navigation operator in ways that are not supported by the coin proposal. Mark 2009/4/21 Ruslan Shevchenko > > It is indeed good work, but like all metrics, these measurements need > > to be treated as rough indicators rather than firm values. The > > Yes. > > > Jackpot project (an automated refactoring tool) had a rule to change > > if statements to conditional expressions -- it found a lot of > > candidates, but most were rejected by developers using the tool. When > > asked, developers gave readability as the primary concern, stating > > that it was worth some verbiage to make the code easier to read. My > > hunch is that a lot of potential elvis uses will be rejected for > > similar reasons. > > > > Yes. > How we can count this: look at languages where elvis implemented and > find percentage of applicability. What we need for this (?) - just parser. > So, in priniciple if exists publicy aviable groovy or C# parser (or > compiler/interpreter which provide access to AST), we can try hack one, to > count unused possibilities and expect that in java number would be near. > > > > Tom > From brucechapman at paradise.net.nz Tue Apr 21 01:58:41 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Tue, 21 Apr 2009 20:58:41 +1200 Subject: PROTOTYPE: In-Reply-To: <24411601.1240288672402.JavaMail.root@elwamui-muscovy.atl.sa.earthlink.net> References: <24411601.1240288672402.JavaMail.root@elwamui-muscovy.atl.sa.earthlink.net> Message-ID: <49ED8AC1.6080209@paradise.net.nz> Derek Foster wrote: > Hi, Bruce! > > I just wanted to offer a huge "THANK YOU!!!" for following up on this and doing actual implementation work. Yeah, but you saved me from having to write the proposal, and to be honest ( https://kijaro.dev.java.net/servlets/ReadMsg?list=commits&msgNo=172 ), I think I got the easier half of the job, and half of that was just copying and pasting your tests from the spec. So thank YOU. Bruce From neal at gafter.com Tue Apr 21 08:00:10 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 21 Apr 2009 08:00:10 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> Message-ID: <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> On Sun, Apr 19, 2009 at 11:45 PM, Joshua Bloch wrote: > The variable #localVar is a compiler-generated identifier distinct from any > other identifiers (compiler-generated or otherwise) that are in scope (JLS > ?6.3) at the point where the automatic resource management statement > occurs. > The *Type *in the above desugaring is replaced by the static type of * > Expression*. > This introduces the possibility of local variables with intersection and recursive types. Such variables could not have occurred previously because they are not denotable. I believe there are three tables in the class file format that may be affected. Can you please include in the specification a description of how you want them handled? From jjb at google.com Tue Apr 21 08:34:40 2009 From: jjb at google.com (Joshua Bloch) Date: Tue, 21 Apr 2009 08:34:40 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> Message-ID: <17b2302a0904210834l55f665d9w52613c792989abb0@mail.gmail.com> Neal, Yes, this is the situation that Bruce Chapman pointed out earlier. As a practical matter, I suspect that resources will have rather simple types, but still the spec does have to cover this situation. If you have a good solution, feel free to share. Otherwise, hang on, and we'll see what we can come up with. Josh On Tue, Apr 21, 2009 at 8:00 AM, Neal Gafter wrote: > On Sun, Apr 19, 2009 at 11:45 PM, Joshua Bloch wrote: > >> The variable #localVar is a compiler-generated identifier distinct from >> any >> other identifiers (compiler-generated or otherwise) that are in scope (JLS >> ?6.3) at the point where the automatic resource management statement >> occurs. >> The *Type *in the above desugaring is replaced by the static type of * >> Expression*. >> > > This introduces the possibility of local variables with intersection and > recursive types. Such variables could not have occurred previously because > they are not denotable. I believe there are three tables in the class file > format that may be affected. Can you please include in the specification a > description of how you want them handled? > From Joe.Darcy at Sun.COM Tue Apr 21 08:35:16 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Tue, 21 Apr 2009 08:35:16 -0700 Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <49C56020.2070207@joda.org> References: <49C56020.2070207@joda.org> Message-ID: <49EDE7B4.2090006@sun.com> Catching up on proposal commenting, while I find the design generally acceptable, I remain unconvinced that the inability to replace all pre-JDK 5 for loops with some newer, improved for loop is a serious enough problem to justify further language changes beyond the enhanced for loop in JDK 5. Some data on how often such a new construct would be applicable would help here. -Joe Stephen Colebourne wrote: > Enhanced for each loop iteration control > > (re-sent with correct subject line) > > This proposal extends the for each loop to allow access to meta data > including the index and the remove method. > > (This proposal doesn't really go into enough detail - with JSR-310 my > time here is limited. I'd hope that there is just about enough though....) > > ----------------------------------------------------------------------------------- > Enhanced for each loop iteration control > > AUTHOR(S): > Stephen Colebourne > > *OVERVIEW* > > FEATURE SUMMARY: > Extends the Java 5 for-each loop to allow access to the loop index, > whether this is the first or last iteration, and to remove the current item. > > MAJOR ADVANTAGE: > The for-each loop is almost certainly the most new popular feature from > Java 5. It works because it increases the abstraction level - instead of > having to express the low-level details of how to loop around a list or > array (with an index or iterator), the developer simply states that they > want to loop and the language takes care of the rest. However, all the > benefit is lost as soon as the developer needs to access the index or to > remove an item. > > The original Java 5 for each work took a relatively conservative stance > on a number of issues aiming to tackle the 80% case. However, loops are > such a common form in coding that the remaining 20% that was not tackled > represents a significant body of code. > > The process of converting the loop back from the for each to be index or > iterator based is painful. This is because the old loop style if > significantly lower-level, more verbose and less clear. It is also > painful as most IDEs don't support this kind of 'de-refactoring'. > > MAJOR BENEFIT: > A common coding idiom is expressed at a higher abstraction than at > present. This aids readability and clarity. > > Accessing the index currently requires using an int based loop, or > placing a separate int counter outside the loop (which then remains in > scope after the loop). The proposed solution doesn't result in manual > manipulation of the index. > > Accessing the iterator remove requires using an iterator based loop. > With generics this is remarkably verbose. The proposed solution is > significantly shorter and cleaner. > > MAJOR DISADVANTAGE: > The enhanced for each loop is complicated with additional functionality. > (This is mitigated by being easy and obvious to use) > > More code is generated magically by the compiler. (This is mitigated by > a simple desugaring) > > ALTERNATIVES: > Use the existing language constructs, typically the standard for loop. > > Use BGGA/JCA style closures, with control statements. It should be noted > that these are consistently the most controversial parts of the closure > debate, making the 'let's wait for closures' argument against this > proposal weaker (as any final closures implementation may not include > control statements). > > > *EXAMPLES* > > SIMPLE EXAMPLE: > > StringBuilder buf = new StringBuilder(); > for (String str : list : it) { > if (str == null) { > it.remove(); > } > } > > whereas, today we write: > > StringBuilder buf = new StringBuilder(); > for (Iterator it = list.iterator(); it.hasNext();) { > String str = it.next(); > if (str == null) { > it.remove(); > } > } > > ADVANCED EXAMPLE: > > Example1: > > for (String str : list : it) { > System.out.println("Row " + it.index() + " has the value " + str); > } > > whereas, today we might write: > > int index = 0; > for (String str : list) { > System.out.println("Row " + index + " has the value " + str); > index++; > } > > or > > for (int i = 0; i < list.size(); i++) { > String str = list.get(i); > System.out.println("Row " + index + " has the value " + str); > } > > Example 2: > > StringBuilder buf = new StringBuilder(); > for (String str : list : it) { > if (it.isFirst()) { > buf.append(str); > } else { > buf.append(", ").append(str); > } > } > > StringBuilder buf = new StringBuilder(); > for (String str : list : it) { > if (it.isLast()) { > buf.append(str); > } else { > buf.append(str).append(", "); > } > } > > > *DETAILS* > > SPECIFICATION: > > Lexical: > No new tokens are added. The colon token is reused in the extended > enhanced for each statement. > > Syntax: > > EnhancedForStatement: > for ( VariableModifiersopt Type Identifier : Expression) Statement > for ( VariableModifiersopt Type Identifier : Expression : Ident) > Statement > > Semantics: > > The first enhanced for each statement (the current form) will compile as > it does today. > > The extended enhanced for each statement will operate as follows. > The iterator control variable is a standard variable declared to be > final. It will never be null. The type is dependent on whether the > expression is an array or an Iterable. It will either be > ArrayIterationControl or IterableIterationControl. The type is not > specified as it is redundent information, ie. the type is inferred. It > is scoped for the life of the loop. > > public final class IterableIterationControlIterator { > public IterableIterationControlIterator(Iterable iterable) { > this.control = new IterableIterationControl(iterable.iterator()); > } > public boolean hasNext() { return control.hasNext() } > public T next() { return control.next() } > public IterableIterationControl control() { return control } > } > public final class IterableIterationControl { > public IterableIterationControl(Iterator iteratorToWrap) { > this.it = iteratorToWrap; > } > boolean hasNext() { return it.hasNext() } > T next() { originalIndex++; if (lastWasRemoved) { lastWasRemoved = > false } else { index++ } return it.next() } > public T remove() { removed++; lastWasRemoved = true; return > it.remove() } > public int index() { return index } > public int originalIndex() { return originalIndex } > public boolean isFirst() { return index == 1 } > public boolean isLast() { return it.hasNext() == false } > } > > public final class ArrayIterationControlIterator { > public ArrayIterationControlIterator(T[] array) { > this.control = new ArrayIterationControl(array); > } > public boolean hasNext() { return control.hasNext() } > public T next() { return control.next() } > public ArrayIterationControl control() { return control } > } > public final class ArrayIterationControl { > public ArrayIterationControl(T[] array) { this.array = array; } > boolean hasNext() { return index < array.length; } > T next() { return array[++index]; } > public int index() { return index - 1; } > public boolean isFirst() { return index == 1; } > public boolean isLast() { return index == array.length; } > } > > Exception analysis: > The method remove() on the iteration control variable can throw an > UnsuportedOperationException. However, this is no different from any > other method call. > > Definite assignment: > The new variable iteration control variable is a final variable that is > definitely assigned from creation. > > COMPILATION: > The extended enhanced for each loop is implemented by wrapping the two > control classes around the Iterable or the array. > > The Iterable design is desugared from: > > for (T item : iterable : control) { ... } > > to: > { > IterableIterationControlIterator $it = new > IterableIterationControlIterator(iterable); > IterableIterationControl control = $it.control(); > while ($it.hasNext()) { > T item = $it.next(); > ... > } > } > > The array design is desugared similarly: > > { > ArrayIterationControlIterator $it = new > ArrayIterationControlIterator(iterable); > ArrayIterationControl control = $it.control(); > while ($it.hasNext()) { > T item = $it.next(); > ... > } > } > > There is the option to optimise this if the iteration control variable > is not assigned to any other variable or passed to any other method. > However, that is out of scope for now. > > TESTING: > Testing will be similar to the enhanced for loop. Arrays and Iterables > of various types and sizes will be used. The null expression will also > be tested. > > LIBRARY SUPPORT: > Yes, as detailed above. > > REFLECTIVE APIS: > No. > > OTHER CHANGES: > The javac tree API would need to be updated to model the change. > > MIGRATION: > Migration is not required. However, an IDE refactoring could now convert > more int and Iterator based for loops than it does at present. > > > *COMPATIBILITY* > > BREAKING CHANGES: > No breaking changes are known using this conversion scheme. > > EXISTING PROGRAMS: > This conversion is pure syntax sugar, so there are no known interactions > with existing programs. > > > *REFERENCES* > > EXISTING BUGS: > I searched the bug database, but nothing came up (which is surprising). > > URL FOR PROTOTYPE: > None > > DOCUMENTS: > [1] Stephen Colebourne's blog: > http://www.jroller.com/scolebourne/entry/java_7_for_each_loop > [2] Stephen Colebourne's original writeup: > http://docs.google.com/Edit?docID=dfn5297z_15ck7x5ghr > > > *DESIGN ISSUES* > There are numerous alternative ways in which this feature can be added. > These include: > - using the keyword: > for (String str : list) { > for.remove(); // problem is nested for loops > } > - using a label as a psuedo-variable: > it: for (String str : list) { > it:remove(); // note colon and not dot > } > - using an additional clause before the for each colon: > for (String str, int index : list) { > // no access to remove, and conflicts for for each for maps > } > > The chosen solution involves simple Java classes, and a simple desugar. > The downside of the chosen solution is performance, as it involves > creating two wrapping objects and routing hasNext() and next() via > additional layers of method calls. A possible extension would be for the > compiler to identify if the iteration control variable is not passed to > another method. If so, then the code could be all be generated inline. > > > > > > From Joe.Darcy at Sun.COM Tue Apr 21 08:36:07 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Tue, 21 Apr 2009 08:36:07 -0700 Subject: PROPOSAL: Named method parameters In-Reply-To: <4ce75f920903210915pa2b27b3g38841e342a78de77@mail.gmail.com> References: <4ce75f920903210915pa2b27b3g38841e342a78de77@mail.gmail.com> Message-ID: <49EDE7E7.7040907@sun.com> Catching up on responses, as has been further discussed on the list recently, requests in this general vein have been considered before in JDK 6. While there are certainly use-cases this facility could clarify, I remain unconvinced of the cost/benefit ratio of this proposal. A few design notes, a single @PublicParameterNames annotation with a boolean member could be used instead of a pair of "do it/don't do it" annotations. A full proposal for this facility would need to deal with the cases where the number of parameters in the class file differs from the number of parameters in the source code, a situation already mildly exposed when calling toGenericString on some Method and Constructor objects. Not supporting parameter reordering greatly simplifies the proposal by leaving method selection largely unaffected, but also seems to limit the usefulness of the proposal. If the main benefit is just seeing the parameter name in the program text; can't the IDE do that? I'd isn't clear to me how @PublicParameterNames would interact with overridden methods in class hierarchies. Presumably the names of the static type of the call site would need be match, even though the runtime type could differ. If a subclass overrode a method and changed its parameter names (which currently has no affect on compatibility), the subclass would no longer be substitutable for the parent class, which would break a fundamental design principle. At least there is no binary compatibility impact since the names would only be checked at compile time and binary compatibility is about preserving the ability to link. -Joe Paul Martin wrote: > I'd like to propose the implementation of optionally named method > parameters, and suggest that they are particularly useful when creating > immutable objects (which are important in our increasingly concurrent > world). > > Note that this is a topic that seems to have been considered before (see the > note in http://paulhammant.com/blog/announcing_paranamer.html which suggests > that it was even considered for Java 6), but I can't see it in the current > list of Java 7 changes or in the Project Coin mailing list archives (though > others have also discussed it in relation to Java 7, such as Alex Miller in > http://tech.puredanger.com/2007/08/15/dr-java7/ and > http://tech.puredanger.com/2007/10/11/java7-roundup-32/). Therefore I am > proposing it here - I think that it is an important change (unless anyone > can suggest how I can reasonably create an immutable object with four or > more properties without using a Builder or a list of unnamed parameters). > > Also note that other relevant references include: > http://blogs.sun.com/abuckley/entry/named_parameters (which discusses why > parameter reordering might be difficult), > http://beust.com/weblog/archives/000096.html (which suggests that we do not > need named parameters, but really just shows the use of the Builder pattern > which has limitations). > > > Named method parameters > > AUTHOR(S): > > Paul Martin > > OVERVIEW > > FEATURE SUMMARY: > > Named parameters allow a method or constructor caller to explicitly state > the parameter name of each parameter value passed to the method or > constructor. Without named parameters, only the order of the parameter > values is significant (and it may not be clear what each value represents). > > MAJOR ADVANTAGE: > > This is a relatively simple way of introducing named parameters to the Java > platform. > > MAJOR BENEFIT: > > Named parameters allow method calls with relatively long lists of parameters > (greater than 3) to be understood by developers. This can also facilitate > the direct use of constructors and factory methods to create immutable > objects, where otherwise Builders or mutable JavaBeans would be required. > > MAJOR DISADVANTAGE: > > The syntax for method calls would change to allow both named and unnamed > parameters to be used. > > Named parameters might be used too often, which could unnecessarily clutter > source files. > > Metadata to store the names of the parameters must be added to classfiles > (for example as annotations). > > The use of annotations to describe named parameters would mean that no > metadata would be stored about the parameter names used by the method > caller, and so no runtime checks to match the parameter names being used > could be made (only compile-time). If the parameter names change (but > otherwise the method signature does not), then the method caller would not > be aware of the changes until it was recompiled. Note that this is existing > behaviour for unnamed parameters, and would only be a problem if the meaning > of the parameters also changes (which should indicate that the caller would > need to change anyway, but this would not be detected automatically at > runtime). > > ALTERNATIVES: > > Unnamed parameters can make the same method calls as named parameters, but > if there are many parameters they are harder to understand and prone to > ordering-related bugs (particularly for primitive types or Strings). > > The Builder pattern can be used to simulate named parameters in > constructors/factory methods. For example the following class uses a > Builder to initialise itself (note that only two properties are used to > simplify the example): > > public final class MyClass { > > private final String name; > private final int age; > > private MyClass(Builder b) { > this.name = b.name; > this.age = b.age; > } > > public static class Builder { > > private String name; > private int age; > > /** > * Name to set. > */ > public Builder setName(String name) { > this.name = name; > return this; > } > > /** > * Age to set > */ > public Builder setAge(int age) { > this.age = age; > return this; > } > > public MyClass build() { > return new MyClass(this); > } > } > } > > Objects can then be constructed in the following manner: > > MyClass obj = new MyClass.Builder().setName("Fred").setAge(53).build(); > > However, the use of a builder requires additional code, and all parameters > are effectively optional from the perspective of the compiler (it cannot > easily check that all of the required setter methods have been called), so > bugs may occur where parameter values are not set. Note that runtime checks > can be made to ensure that all property values are set, but they involve > additional work and cannot be used by the compiler (though static analysis > of the code in conjunction with annotations might be able to repeat many of > these checks). > > There are also many ways to implement named parameters that are different to > the solution proposed here. These include: > > Implement optional named parameters on all methods: This avoids the need > for the @PublicParameterNames annotation, but may mean inconsistent usage of > named parameters - the annotation is also a suggestion for the use of named > parameters by the caller (which IDEs can also make use of). This will also > highlight the difference to classfiles compiled with earlier versions of > Java, where named parameters cannot be used at all (since it will then not > be obvious when named parameters can and cannot be used). > > Add parameter names to the classfile as 'fundamental' method metadata rather > than as annotations: This may allow closer integration of the named > parameters with the rest of the language, but its impact on the rest of the > language (and JVM) is much greater. The same inconsistencies and > incompatibilities described in the previous alternative would also apply. > In addition, the use of annotations should not preclude the subsequent > modification of classfiles in a later release - the annotations could still > remain (at a potential cost of some duplication). > > EXAMPLES > > SIMPLE EXAMPLE: > > Constructor declaration: > > @PublicParameterNames > public MyClass(String name, int age) { .... > > Constructor use: > > MyClass obj = new MyClass(name: "Fred", age: 53); > > ADVANCED EXAMPLE: Show advanced usage(s) of the feature. > > The full class definition from the simple example is shown below, as a > contrast to that provided in the Builder example. > > public final class MyClass { > > private final String name; > private final int age; > > /** > * @param name Name to set > * @param age Age to set > */ > > @PublicParameterNames > public MyClass(String name, int age) { > this.name = name; > this.age = age; > } > } > > DETAILS > > SPECIFICATION: > > The @PublicParameterNames annotation is used on a constructor or method to > allow named parameters to be used when calling it. It can also be applied > to a class or package to apply to all methods within. Similarly, a > @NoParameterNames annotation can be used on a constructor, method, or class > to override the use of @PublicParameterNames at a higher level. > > The compiler can then automatically generate a > @PublicParameterName(value="parameter-name") annotation for each affected > method. These can then be used by the compiler (and IDE) to validate the > parameter names used by callers of the method or constructor. > > The use of parameter names by callers is always optional (primarily for > backwards compatibility). However, parameter names cannot be used for some > parameters and not others (this would make the code harder to read). > > Parameters must always be specified in the same order regardless of whether > parameter names are used - parameter reordering by callers is not allowed > (reordering would make overloading difficult, and is not really necessary). > > Inheritance: Neither the @PublicParameterNames annotation (and > @NoParameterNames annotation), or the names of the parameters themselves, > need to be inherited. This is because only static evaluation of a caller's > parameter names will be applied (rather than at runtime), so the callers > parameter names only need to match those of the declared type of the > target. However, it would still be advisable to reuse the same parameter > names and annotations when overriding a method (IDEs could help with this). > > COMPILATION: > > The compiler must automatically generate a > @PublicParameterName(value="parameter-name") annotation for each method and > constructor annotated with @PublicParameterNames (or whose the parent class > or package is annotated with @PublicParameterNames and the child class or > method does not override it with @NoParameterNames). > > For example: > > int myMethod(int param1, String param2) > > Would effectively become: > > int myMethod(@PublicParameterName("param1") int param1, > @PublicParameterName("param2") String param2) > > Method-calling syntax would need to change, using a colon to separate the > parameter name and value where the are used. For example: > > MyClass obj = new MyClass(name: "Fred", age: 53); > > When a method caller uses parameter names, the compiler must check that > those parameter names exactly match the value of generated > @PublicParameterName annotations of the target method or constructor. It is > a compilation error if they do not match or the target method or constructor > does not have named parameters. > > IDEs can use the @PublicParameterNames and @NoParameterNames annotations (or > @PublicParameterName directly) to automatically insert the relevant > parameter names as part of code-completion. Additional refactoring support > would also be required to enable parameter names to be renamed, or added and > removed completely. > > Frameworks such as Spring can use the same annotations to allow objects to > be created from their configuration files using named parameters to > constructors and factory methods. Currently they only allow objects to be > created from configuration files as JavaBeans (with setter methods) or with > ordered (and unnamed) parameters. > > TESTING: > > The feature can be tested by compiling and running programs that exercise > the feature. > > LIBRARY SUPPORT: > > No. > > REFLECTIVE APIS: > > java.lang.reflect.Method and java.lang.reflect.Constructor could be enhanced > with new methods that return parameter names. However, that is not required > to successfully implement the proposal. > > OTHER CHANGES: > > No. The use of named parameters is always optional. The javadoc tool > already documents parameter names. Other tools/libraries might benefit from > these changes, but their use is not required. > > MIGRATION: > > The @PublicParameterNames annotation (and @NoParameterNames annotation) > simply needs to be added to the appropriate methods. IDEs could then > suggest the use of parameter names for the method's callers, and apply the > changes automatically. > > COMPATIBILITY > > BREAKING CHANGES: > > No. > > EXISTING PROGRAMS: > > The changes required by this feature should be transparent to existing > source and class files if annotations are used internally to describe the > named parameters. I am not sure what the impact would be otherwise. > > REFERENCES > > EXISTING BUGS: > > 4124331 (though it is set to 11-Closed, Will Not Fix, request for > enhancement, and from 1998) > > From Joe.Darcy at Sun.COM Tue Apr 21 08:36:56 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Tue, 21 Apr 2009 08:36:56 -0700 Subject: SUBMISSION : A second look on "named parameters" / Clarification on the scope In-Reply-To: References: <2dc3bd00904200118s35e085fdk6f4ef3cac83cd6e9@mail.gmail.com> Message-ID: <49EDE818.3060101@sun.com> A few notes on this topic. Support for retrieving parameter names was removed from the feature list of JDK 6; there was never any working code to implement this feature. Implementing this functionality would be nontrivial, for coordination reasons if no others. Names are stored in the class file at certain debugging levels. However, there is no Java-level API to return that information. A new (small) VM interface would need to be written to retrieve and pass on this information to the libraries. Unconditionally storing parameter names all the time is unattractive because the names would take up space. Yes, some people do care about the sizes of their jar files, (like rt.jar :-), and adding such information that in many cases would be little used or ignore is not desirable. A further technical wrinkle, the number of parameters in the source code and the number of parameters in the class file sometimes disagree, with the class file having more (outer this parameter for some nested class constructors, implicit ordinal parameters for enum constructors) and there is currently no reliable data in the class file to determine whether or not a parameter is synthetic. For example, constructors for anonymous classes appearing in a static context, like a static initializer block, do not need to have an enclosing instance parameter. These are certainly solvable technical problems, but someone needs to solve them. The parameter names are useful when interfacing Java to other language environments that like sql use nominal rather than position parameter passing. However, in terms of the overall Java elephant, I don't perceive this as a prevalent pattern. Additionally, exposing the parameters names introduces a de facto new behavioral compatibility constraint; that is, you can no long change the parameter names of your methods and constructors without regard for the compatibility consequences because users can be relying on the names. I encourage people interested in this feature to develop a prototype. -Joe Reinier Zwitserloot wrote: > Ah, now I understand. > > I've got a much simpler proposal to address this issue. > > NB: Joe, I know coin's long gone, but perhaps consider this one anyway > - it seems to me that some sort of named parameters proposal is likely > to be accepted in the future, and adding names now should ease > transition. As part of the effort I've listed all possibly > complication I can come up with, at the end. > > Proposal: > > > Starting from the new class file format introduced in java7 (due to > module support, the class format is definitely getting a version > bump), all compilers MUST put the names of the parameters in the class > file (javac -g style), and obfuscators/compressors/whatever MUST NOT > remove this; a class file with version v50 (or whatever number its > going to end up being) won't even pass the verifier without the names > in place. > > Add an API call on the java.lang.reflect.Method object to obtain the > names of the parameters (returns a String[], or 'null' if they aren't > there. Calling this on a param-less method returns an empty array, not > null). Having the names is an all-or-nothing situation: Either the > names are all there and this call works, or some/all are missing, and > then this call does not work. I'm not sure if you can even have just a > few names defined in the .class file format, but even if you can, that > situation should be so extremely rare, its not worth writing up a > complicated rule for). It is guaranteed that if the array exists (is > not null), then each array element is not null. > > Voila. No need to turn in a proposal that's more complicated than most > just to solve this simple problem. > > Complications: > > A) It would no longer be possible to rewrite a v49 and below class > without debug info into a v50 and up class file without having the > source file, but I don't actually know of any tools that attempt to do > this. > > B) Code that generates class files on the fly (like proxy generators > and the like) will need to consider the names of method parameters > if/when they update the class file format they generate to v50+. A > proxy generator has issues when it is trying to generate a v50+ proxy > where its input object's class spec AND the input interface to proxy > on are both v49- without debug info, for example. > > C) A (bad) quick-fix for either of the above issues is to just use > 'arg0', 'arg1', 'arg2', analogous to what e.g. eclipse does when > showing method signatures for methods in classes where there is no > source, no debug info and no javadoc. This is not at all the right > idea. A small risk that the class file format documentation should > mention as not being appropriate unless there is absolutely no other > option. > > D) Most code these days ships with source, or javadoc, or debug info, > so that auto-complete shows the proper names for each parameter, but > this certainly isn't true for /all/ java code out there. After this > change, method param names become visible to all. This may not be a > desired side-effect for programming shops that export libraries to > clients where their method parameter names are inappropriate (swear > words, or 'x', 'y', and 'z' and this creates deserved but nevertheless > unexpected ridicule for sucking at programming style). I think this is > an acceptable price to pay. Parameters are method-local which are > extremely easy to rename with your friendly neighbourhood IDE's > refactor tool. > > E) While technically the names are NOT part of API, and you CAN freely > change names around without breaking any code, old or new, the names > still do become a little more enshrined as at least almost part of the > public API. This is already the case to some extent (param names show > up in various tooling support such as javadoc and auto-completing > IDEs) but this change would move parameter names a little more towards > a complete member of public API. This is an issue, but its also the > point of this proposal: Move towards a java world where parameter > names are universally available and are meaningful. I don't think this > is a serious problem, because A) names already have a flavour of > importance right now, and B) While they become more important with > this proposal, they still aren't true public API, and changing names > even after this proposal is accepted is not backwards incompatible. > > F) Confusion may arise when these names are unintentionally taken as > being either part of public API, or being hierarchical; they are in > fact neither. For example, this proposal makes no attempt to harmonize > name conflicts; if interface A has void foo(int bar), and interface B > has void foo(int baz), you can still of course write a class that > implements both of these. You can even name your foo's parameter > 'floobargle', of course. The aim of this proposal does not involve > making parameter names inherit sensibly. > > > --Reinier Zwitserloot > > > > On Apr 20, 2009, at 10:18, Jean-Baptiste Bugeaud wrote: > >> Hello Reinier, Hello Joe, >> >> Thanks for your feedback. >> >> 2009/4/19 Reinier Zwitserloot : >>> Your proposal is very incomplete. Three major nits: >>> >>> A. Did I miss something, or did you totally forget to include an >>> example of >>> calling a method with named parameters? Something like: >>> >>> doLogin(user: "foobar", password: new char[] { 'a', 'b', 'c' }) >> >> Reiner, I think my submission name is misleading everybody. This is >> not the same thing you debate some times back. My mistake ... I should >> have clarified from the start : I do not look at adding direct call by >> parameter name into the language (say "? la" ObjectiveC). But simply a >> reliable way access to parameter name and name a parameter's name in >> static way thru time. See bug 6444738 for differences. >> >> Parameter names are very usefull information in most cases, and at >> this time, either implementers use duplicate annotation (dummy >> annotations storing again the same name) or they use tools such as ASM >> to workaround the lack of API in the JDK. >> >> At the begining, I thought this requirement did not required a small >> synthax language change : a new API would be enough. But soon I >> realized that introducing name parameter that are static thru time, >> introduce anyway a new paradigm in the language that developer should >> be able to control directly : do I want this parameter name to be >> static thu time ? or do I want to let the compiler decide as usual ? >> >> A compiler option is not the suitable tool for this. >> If this is a global switch, it will not offer the fine grain required. >> If this is a per class/per package option, it will clutter the >> command line. >> And in both cases, it will not offer paradigm separation with the >> legacy. Thus you can not rely on the parameter name because you never >> know if developper has stored the name accidentaly or for purpose. >> >>> B. Why static? You might as well have picked 'strictfp' - it's a total >>> non-sequitur choice. Re-use of existing keywords is not really a >>> panacea; it >>> waters down the anchoring ability of a keyword to virtually nothing. >>> I'm not >>> sure if context-sensitive keywords are any better, but java7 is already >>> going to have at least one ('module'), so don't beat around the bush >>> and >>> just call it 'named'). Could be just me, but introducing a change >>> which is >>> not backwards compatible IF you have a type that's called 'named' >>> (written >>> just like that, all-lower case), is not something I find troublesome >>> in the >>> least. That's very ugly code, and a migration tool can fix this easily. >> >> Because of the definition a dictionary gives of it : something like >> "showing little change" is exactly what I meant for this paradigm. And >> no "strictfp", as well as "const" and "goto" are not matching, you see >> ;-) >> >> If you think that this worth integrating a new keywork, then there is >> room for debate. I think static fits perfectly and is clear enough. >> AFAIK, we already have final that is contextual? why not static too ? >> final is already stretched between two things : do not overload member >> and do not reasign variable. >> >> With the proposed language changed static modifier will be stretched >> between static thru instances for members and static thru time for >> variables. >> >>> C. You don't mention having default values for parameters, which is >>> sort of >>> the point of this exercise (otherwise you really still need >>> builders ; any >>> method that has so many parameters that they need names probably >>> needs a >>> builder, and without defaults, not providing one and instead relying on >>> named params is just an inferior bandaid to your ugly API; to get it >>> right >>> you STILL need to provide a builder. If, however, parameters can have >>> defaults, then you no longer need to make builders at all). >> >> This is because I am not asking for named call of method ... simply >> for a way to access name of parameter. Just a completely different >> topic. >> I don't see why a parameter on an EJB is not meanfull for the external >> ? same for an webservice ? why a parameter name could not be meanfull >> ? I don't get your point. >> >> My design decision is the kind of decision that led to erasure based >> genericity : it has some drawback, loss of real parametrics instances >> that could be usefull while reflection. But was the right decision at >> the right time or either we would have lots binary compatibility or we >> would still be debating wether or not implementing generics. >> >> My proposition on parameter name is analog, it is just meant to be >> used ASAP but does it does not fully solve all the possible >> expectations from this topic scope. Namely, should we call "by >> parameter name" in the language ? and how ? >> >> Room is let for the coming decade ;-) But the propopsition does not >> close doors to anything. >> >>> I suggest you look over the coin-dev mailing list; I entered a rough >>> sketch >>> of a named parameters proposal near the end of coin. I never wrote >>> it up >>> because I thought of it far too close to the deadline, and it's >>> still of >>> such high impact that I doubt it would pass muster for coin. >> >> Yes I've followed the debate :) But, again its my mistake "call by >> parameter names" is a much more complex topic with lots of >> performance/plaform impact. This is not a small language change IMHO. >> Again, I do not look for calling a direct method call using named >> parameters .... just a way to retreive them. >> >> -- -- >> >> Joe, yes "late I am" ;-) >> >> FYI, I got this proposition cooking for several months I was not able >> to find time to write & post it to you (pittyfull isn't it). >> >> If we remove the "language change" part (static named parameter) and >> only keep the getParameterNames() API part (keep the regular parameter >> name), do you think this can be pushed to JDK7 even if out of scope of >> coin ? This is a very small change to the API and would solve lot of >> time from lot of people. >> >> I mean, this API (along with the rest of the named parameter spec) was >> removed from JDK6, skiping this in JDK7 means years again to wait for >> it ? I think we are too much getting dependent on tools such as ASM in >> lots of places (JavaEE implementation stacks for instance). And we >> have a good opportunity to remove the dependency for a clean/simple >> solution IMHO. >> >> Best Regards, >> JB > From Ulf.Zibis at gmx.de Tue Apr 21 08:47:56 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Tue, 21 Apr 2009 17:47:56 +0200 Subject: scripts and results (was Helping to find the usefulness of a proposal) In-Reply-To: <114ad93adfd2eb30f7ecd1388b69b1be.squirrel@wmail.gradsoft.ua> References: <60287e9e1530b3e1ae49976316e8dc57.squirrel@wmail.gradsoft.ua> <49E5F020.7060508@gmx.de> <114ad93adfd2eb30f7ecd1388b69b1be.squirrel@wmail.gradsoft.ua> Message-ID: <49EDEAAC.2040100@gmx.de> Am 16.04.2009 08:27, Ruslan Shevchenko schrieb: >> Hi Ruslan, >> >> I would like to see the results for >> >> "objects and expressions in switch" >> >> which includes: >> - string in switch >> - instanceof switch >> >> I guess a very big chunk of all if-else if-structures would be covered by: >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html >> >> > > Ok, I will alloc some time during next week-end for more patterns and > statistics and will try include this one. This will some 'near' refinemed > of proposal, becouse original proposal does not define what is 'leftPart' > and 'rightPart' of Java expression in formal way [this is not so trivial, > as expected. For example what left part will be in function expressions: > 'this' or nothing ?. How we split chained expressions on left and right ?] > For this reasons, I guess probability that this proposal will seen > seriously is very low. > > > (Second change which I plan: add statistics about relative number of > chainged construction/number of all such constructions). > > > Hi Ruslan, as I see, your didn't have time for more patterns. :-( Hopfully you will find time next days. :-) Regards, Ulf From neal at gafter.com Tue Apr 21 08:52:38 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 21 Apr 2009 08:52:38 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904210834l55f665d9w52613c792989abb0@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> <17b2302a0904210834l55f665d9w52613c792989abb0@mail.gmail.com> Message-ID: <15e8b9d20904210852t2b8aa5f7n77012ae7397b6eb1@mail.gmail.com> On Tue, Apr 21, 2009 at 8:34 AM, Joshua Bloch wrote: > Yes, this is the situation that Bruce Chapman pointed out earlier. As a > practical matter, I suspect that resources will have rather simple types, > but still the spec does have to cover this situation. If you have a good > solution, feel free to share. Otherwise, hang on, and we'll see what we can > come up with. > In the LocalVariableTypeTable, conjunctive types should be simple to add. Recursive types can be handled by introducing backreferences. You can probably avoid this mess by being explicit about the specification rather than attempting the "as-if" rewriting. If a construct like this is to be integrated into the JLS that would probably be required anyway, and a new set of issues is likely to be exposed by the attempt. It would be better to get the specification wrung out earlier rather than later (I don't think Alex will be eager to do it himself). From forax at univ-mlv.fr Tue Apr 21 09:12:07 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Tue, 21 Apr 2009 18:12:07 +0200 Subject: Automatic Resource Management, V.2 In-Reply-To: <15e8b9d20904210852t2b8aa5f7n77012ae7397b6eb1@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> <17b2302a0904210834l55f665d9w52613c792989abb0@mail.gmail.com> <15e8b9d20904210852t2b8aa5f7n77012ae7397b6eb1@mail.gmail.com> Message-ID: <49EDF057.3080906@univ-mlv.fr> Neal Gafter a ?crit : > On Tue, Apr 21, 2009 at 8:34 AM, Joshua Bloch wrote: > > >> Yes, this is the situation that Bruce Chapman pointed out earlier. As a >> practical matter, I suspect that resources will have rather simple types, >> but still the spec does have to cover this situation. If you have a good >> solution, feel free to share. Otherwise, hang on, and we'll see what we can >> come up with. >> >> > > In the LocalVariableTypeTable, conjunctive types should be simple to add. > Recursive types can be handled by introducing backreferences. > > You can probably avoid this mess by being explicit about the specification > rather than attempting the "as-if" rewriting. If a construct like this is > to be integrated into the JLS that would probably be required anyway, and a > new set of issues is likely to be exposed by the attempt. It would be > better to get the specification wrung out earlier rather than later (I don't > think Alex will be eager to do it himself). > > Why the local var need to be visible in these tables ? The compiler already introduced new local var , by example, in case of ++/-- and compound assignments on boxed type (using the hidden instruction LetExpr). In that case the local var is flagged SYNTHETIC and doesn't appear in local vars tables. R?mi From neal at gafter.com Tue Apr 21 09:48:06 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 21 Apr 2009 09:48:06 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <49EDF057.3080906@univ-mlv.fr> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> <17b2302a0904210834l55f665d9w52613c792989abb0@mail.gmail.com> <15e8b9d20904210852t2b8aa5f7n77012ae7397b6eb1@mail.gmail.com> <49EDF057.3080906@univ-mlv.fr> Message-ID: <15e8b9d20904210948s58366d7as4bcbd1cea653bc6@mail.gmail.com> On Tue, Apr 21, 2009 at 9:12 AM, R?mi Forax wrote: > >> You can probably avoid this mess by being explicit about the specification >> rather than attempting the "as-if" rewriting. If a construct like this is >> to be integrated into the JLS that would probably be required anyway, and >> a >> new set of issues is likely to be exposed by the attempt. It would be >> better to get the specification wrung out earlier rather than later (I >> don't >> think Alex will be eager to do it himself). >> >> >> > Why the local var need to be visible in these tables ? > > The compiler already introduced new local var , by example, in case of > ++/-- and > compound assignments on boxed type (using the hidden instruction LetExpr). > In that case the local var is flagged SYNTHETIC and doesn't appear in local > vars tables. Right: if the specification is spelled out, one can decide on a case-by-case basis how to handle the mapping to the class file. However, you can't avoid these variables appearing in the verifier tables at the very least. In that case the natural type based on the current spec is its erasure, which is not necessarily AutoCloseable. From tball at google.com Tue Apr 21 10:24:07 2009 From: tball at google.com (Tom Ball) Date: Tue, 21 Apr 2009 10:24:07 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <15e8b9d20904210948s58366d7as4bcbd1cea653bc6@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> <17b2302a0904210834l55f665d9w52613c792989abb0@mail.gmail.com> <15e8b9d20904210852t2b8aa5f7n77012ae7397b6eb1@mail.gmail.com> <49EDF057.3080906@univ-mlv.fr> <15e8b9d20904210948s58366d7as4bcbd1cea653bc6@mail.gmail.com> Message-ID: My "vote" (I realize this isn't a democracy :-) is to avoid adding any new rules, but instead keep it simple: resources in source code go into all tables like any other local variable currently does, while any compiler-generated temporary variables get flagged as synthetic and are included in any tables that include synthetic variables. In other words, a resource should be treated exactly like a local variable already is, synthetic or not. A resource is a local variable, after all, just one that has some automatic cleanup as it leaves scope. BTW, I like Bruce Chapman's suggestion that the type of a temporary variable be AutoCloseable. Since the only thing the compiler generated code will do with that object is call its close() method, there's no advantage to it having additional type information. Tom On Tue, Apr 21, 2009 at 9:48 AM, Neal Gafter wrote: > On Tue, Apr 21, 2009 at 9:12 AM, R?mi Forax wrote: > > > > >> You can probably avoid this mess by being explicit about the > specification > >> rather than attempting the "as-if" rewriting. If a construct like this > is > >> to be integrated into the JLS that would probably be required anyway, > and > >> a > >> new set of issues is likely to be exposed by the attempt. It would be > >> better to get the specification wrung out earlier rather than later (I > >> don't > >> think Alex will be eager to do it himself). > >> > >> > >> > > Why the local var need to be visible in these tables ? > > > > The compiler already introduced new local var , by example, in case of > > ++/-- and > > compound assignments on boxed type (using the hidden instruction > LetExpr). > > In that case the local var is flagged SYNTHETIC and doesn't appear in > local > > vars tables. > > > Right: if the specification is spelled out, one can decide on a > case-by-case > basis how to handle the mapping to the class file. However, you can't avoid > these variables appearing in the verifier tables at the very least. In > that > case the natural type based on the current spec is its erasure, which is > not > necessarily AutoCloseable. > > From forax at univ-mlv.fr Tue Apr 21 10:30:38 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Tue, 21 Apr 2009 19:30:38 +0200 Subject: Automatic Resource Management, V.2 In-Reply-To: <15e8b9d20904210948s58366d7as4bcbd1cea653bc6@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> <17b2302a0904210834l55f665d9w52613c792989abb0@mail.gmail.com> <15e8b9d20904210852t2b8aa5f7n77012ae7397b6eb1@mail.gmail.com> <49EDF057.3080906@univ-mlv.fr> <15e8b9d20904210948s58366d7as4bcbd1cea653bc6@mail.gmail.com> Message-ID: <49EE02BE.1010908@univ-mlv.fr> Neal Gafter a ?crit : > On Tue, Apr 21, 2009 at 9:12 AM, R?mi Forax > wrote: > > > You can probably avoid this mess by being explicit about the > specification > rather than attempting the "as-if" rewriting. If a construct > like this is > to be integrated into the JLS that would probably be required > anyway, and a > new set of issues is likely to be exposed by the attempt. It > would be > better to get the specification wrung out earlier rather than > later (I don't > think Alex will be eager to do it himself). > > > > Why the local var need to be visible in these tables ? > > The compiler already introduced new local var , by example, in > case of ++/-- and > compound assignments on boxed type (using the hidden instruction > LetExpr). > In that case the local var is flagged SYNTHETIC and doesn't appear > in local vars tables. > > > Right: if the specification is spelled out, one can decide on a > case-by-case basis how to handle the mapping to the class file. > However, you can't avoid these variables appearing in the verifier > tables at the very least. In that case the natural type based on the > current spec is its erasure, which is not necessarily AutoCloseable. If the type is not AutoCloseable, the compile emit a checkcast before calling close(), so it will work even if i agree that this checkcast can be avoided. R?mi From jjb at google.com Tue Apr 21 11:17:19 2009 From: jjb at google.com (Joshua Bloch) Date: Tue, 21 Apr 2009 11:17:19 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> <17b2302a0904210834l55f665d9w52613c792989abb0@mail.gmail.com> <15e8b9d20904210852t2b8aa5f7n77012ae7397b6eb1@mail.gmail.com> <49EDF057.3080906@univ-mlv.fr> <15e8b9d20904210948s58366d7as4bcbd1cea653bc6@mail.gmail.com> Message-ID: <17b2302a0904211117s71f2c748p712898e5b0346796@mail.gmail.com> Tom, Thanks! This seems like the obvious correct solution. I feel like a fool for not having done it that way in the first place. Josh On Tue, Apr 21, 2009 at 10:24 AM, Tom Ball wrote: > My "vote" (I realize this isn't a democracy :-) is to avoid adding any new > rules, but instead keep it simple: resources in source code go into all > tables like any other local variable currently does, while any > compiler-generated temporary variables get flagged as synthetic and are > included in any tables that include synthetic variables. In other words, a > resource should be treated exactly like a local variable already is, > synthetic or not. A resource is a local variable, after all, just one that > has some automatic cleanup as it leaves scope. > > BTW, I like Bruce Chapman's suggestion that the type of a temporary > variable > be AutoCloseable. Since the only thing the compiler generated code will do > with that object is call its close() method, there's no advantage to it > having additional type information. > > Tom > > On Tue, Apr 21, 2009 at 9:48 AM, Neal Gafter wrote: > > > On Tue, Apr 21, 2009 at 9:12 AM, R?mi Forax wrote: > > > > > > > >> You can probably avoid this mess by being explicit about the > > specification > > >> rather than attempting the "as-if" rewriting. If a construct like > this > > is > > >> to be integrated into the JLS that would probably be required anyway, > > and > > >> a > > >> new set of issues is likely to be exposed by the attempt. It would be > > >> better to get the specification wrung out earlier rather than later (I > > >> don't > > >> think Alex will be eager to do it himself). > > >> > > >> > > >> > > > Why the local var need to be visible in these tables ? > > > > > > The compiler already introduced new local var , by example, in case of > > > ++/-- and > > > compound assignments on boxed type (using the hidden instruction > > LetExpr). > > > In that case the local var is flagged SYNTHETIC and doesn't appear in > > local > > > vars tables. > > > > > > Right: if the specification is spelled out, one can decide on a > > case-by-case > > basis how to handle the mapping to the class file. However, you can't > avoid > > these variables appearing in the verifier tables at the very least. In > > that > > case the natural type based on the current spec is its erasure, which is > > not > > necessarily AutoCloseable. > > > > > > From tball at google.com Tue Apr 21 11:19:20 2009 From: tball at google.com (Tom Ball) Date: Tue, 21 Apr 2009 11:19:20 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904211117s71f2c748p712898e5b0346796@mail.gmail.com> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> <17b2302a0904210834l55f665d9w52613c792989abb0@mail.gmail.com> <15e8b9d20904210852t2b8aa5f7n77012ae7397b6eb1@mail.gmail.com> <49EDF057.3080906@univ-mlv.fr> <15e8b9d20904210948s58366d7as4bcbd1cea653bc6@mail.gmail.com> <17b2302a0904211117s71f2c748p712898e5b0346796@mail.gmail.com> Message-ID: Things language and compiler-related are only ever obvious in hindsight. :-) On Tue, Apr 21, 2009 at 11:17 AM, Joshua Bloch wrote: > Tom, > > Thanks! This seems like the obvious correct solution. I feel like a fool > for not having done it that way in the first place. > > Josh > > > On Tue, Apr 21, 2009 at 10:24 AM, Tom Ball wrote: > >> My "vote" (I realize this isn't a democracy :-) is to avoid adding any new >> rules, but instead keep it simple: resources in source code go into all >> tables like any other local variable currently does, while any >> compiler-generated temporary variables get flagged as synthetic and are >> included in any tables that include synthetic variables. In other words, >> a >> resource should be treated exactly like a local variable already is, >> synthetic or not. A resource is a local variable, after all, just one >> that >> has some automatic cleanup as it leaves scope. >> >> BTW, I like Bruce Chapman's suggestion that the type of a temporary >> variable >> be AutoCloseable. Since the only thing the compiler generated code will >> do >> with that object is call its close() method, there's no advantage to it >> having additional type information. >> >> Tom >> >> On Tue, Apr 21, 2009 at 9:48 AM, Neal Gafter wrote: >> >> > On Tue, Apr 21, 2009 at 9:12 AM, R?mi Forax wrote: >> > >> > > >> > >> You can probably avoid this mess by being explicit about the >> > specification >> > >> rather than attempting the "as-if" rewriting. If a construct like >> this >> > is >> > >> to be integrated into the JLS that would probably be required anyway, >> > and >> > >> a >> > >> new set of issues is likely to be exposed by the attempt. It would >> be >> > >> better to get the specification wrung out earlier rather than later >> (I >> > >> don't >> > >> think Alex will be eager to do it himself). >> > >> >> > >> >> > >> >> > > Why the local var need to be visible in these tables ? >> > > >> > > The compiler already introduced new local var , by example, in case of >> > > ++/-- and >> > > compound assignments on boxed type (using the hidden instruction >> > LetExpr). >> > > In that case the local var is flagged SYNTHETIC and doesn't appear in >> > local >> > > vars tables. >> > >> > >> > Right: if the specification is spelled out, one can decide on a >> > case-by-case >> > basis how to handle the mapping to the class file. However, you can't >> avoid >> > these variables appearing in the verifier tables at the very least. In >> > that >> > case the natural type based on the current spec is its erasure, which is >> > not >> > necessarily AutoCloseable. >> > >> > >> >> > From paul.martin at gmail.com Tue Apr 21 11:32:13 2009 From: paul.martin at gmail.com (Paul Martin) Date: Tue, 21 Apr 2009 19:32:13 +0100 Subject: PROPOSAL: Named method parameters In-Reply-To: <49EDE7E7.7040907@sun.com> References: <4ce75f920903210915pa2b27b3g38841e342a78de77@mail.gmail.com> <49EDE7E7.7040907@sun.com> Message-ID: <4ce75f920904211132n49386c7aj72ac044e82f6e0a2@mail.gmail.com> Hi, Thanks for your reply. (I've repeated the following request here, as well as at the end of my reply, since I would really appreciate any suggestions!) It would be very helpful/interesting to me if anyone could suggest workable alternatives to solve my immediate problem of creating immutable objects with required (and named) parameters (in Java code and/or Spring-style config). On Tue, Apr 21, 2009 at 4:36 PM, Joseph D. Darcy wrote: > Catching up on responses, as has been further discussed on the list > recently, requests in this general vein have been considered before in JDK > 6. ?While there are certainly use-cases this facility could clarify, I > remain unconvinced of the cost/benefit ratio of this proposal. I'm currently using Spring to write a threaded application, and believe that named method parameters could help in the following ways: 1. Creation of immutable objects by allowing parameter names to be specified in Java method calls It is good practice to have immutable objects where possible (or at least to reduce the mutability of objects) in concurrent applications (which avoids many publication and synchronization issues, as well as reducing the program state space). This means that member variables of Immutable objects must be marked as final, and so can only be assigned by the constructor. There are a number of alternatives: a. Pass parameter values to the constructor without parameter names. This is ok when there are very few parameters or they have very distinct and meaningful types, but not so good otherwise. It is true that the IDE can highlight the parameter names (usually as a pop-up or mouse-over-hover), but I think that it would be easy to miss errors. Comments after each value could help, but there would be no guarantee that they are ever correct or that they stay in sync with code refactoring. b. Use the Builder pattern (as in Effective Java item #2), which does allow immutable objects to be created with (effectively) named parameters, but has the following disadvantages: - It is more verbose (even in the simplified version that sets builder members directly in a subclass without using setters) - More importantly: there is no guarantee that all of the members are set (without a lot of additional validation code in the Builder) - effectively all of the members become optional. If a developer forgets to set a property in the builder, then the built object will just get the default value (though conversely, builders are therefore a reasonable way of getting default parameters). This also affects refactoring - if a member is added, then it would be difficult to ensure that all builders were updated to set a value. Note that it may be possible to enhance analysis tools (such as Findbugs) to detect cases where not all of a Builder's methods have been called (perhaps in conjunction with an annotation), but that may also be impossible in many cases (such as where the Builder is passed between methods). c. I also think that this use of the Builder pattern is not really in the spirit of the GoF book, which states (in its Applicability section): (begin quote) Use the Builder pattern when * the algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled. * the construction process must allow different representations for the object that's constructed. (end quote) Neither of these are involved in the case where a Builder is just being used to simulate named parameters (to aid comprehension/documentation). To summarise, my requirement for named parameters in Java code is motivated by the fact that I don't think that there is currently a nice way to create immutable objects such that the parameter/property names can be easily seen in the code and that ensures that all required parameters/properties are specified. 2. Adding parameter names to the classfiles/reflection system for dynamic object creation (This section is similar to Jean-Baptiste Bugeaud's proposal, and is effectively the same as bug 6444738) This is motivated by my use of Spring, but I think that it is applicable to other technologies (and maybe even other JVM languages). Currently in Spring you can define beans by specifying constructor argument values (anonymously), using and/or property values (via named setters). This has the same disadvantages to that shown in section 1: - Use anonymous constructor parameters, but then the code is harder to understand and maintain. - Use properties, which means that your bean cannot be immutable. - Use a Builder, which involves additional code. Note that Spring can check that @Required properties have been set (and also doesn't have first-class support for Builders, but could be extended to do so). The same kind of problems occur as in 1, though in this case the parameter names would need to be available at runtime, for Spring to interrogate. The result of this is that (from my experience) most Spring beans are unnecessarily mutable, since it is unnecessarily difficult to do otherwise. There are probably other benefits, but those are the ones that motivated my proposal; I just feel that the alternatives are unnecessarily difficult. What do you do in similar situations? > A few design notes, a single @PublicParameterNames annotation with a boolean > member could be used instead of a pair of "do it/don't do it" annotations. That is a better idea! How would this sit with the rule against annotations affecting program flow? Would it count here, because the annotation is only causing additional metadata to be generated by the compiler? > A full proposal for this facility would need to deal with the cases where > the number of parameters in the class file differs from the number of > parameters in the source code, a situation already mildly exposed when > calling toGenericString on some Method and Constructor objects. Yes, my proposal didn't have the required level of detail. If it were to proceed, then experience from projects such as Paranamer might help. > Not supporting parameter reordering greatly simplifies the proposal by > leaving method selection largely unaffected, but also seems to limit the > usefulness of the proposal. ?If the main benefit is just seeing the > parameter name in the program text; can't the IDE do that? > The goal of my proposal was just to get the simplest implementation of named parameters that I thought would work and be useful. Therefore I explicitly discounted: - Parameter reordering - I could only see disadvantages (from the references at the start of my proposal), without a major benefit. - Default parameters - This would be a large change to method resolution, and I thought that it could be addressed independently of named parameters. I also think that it is something that can be already achieved with overloaded methods and/or Builders, whereas named parameters let us do something new (readable creation of immutable objects). > I'd isn't clear to me how @PublicParameterNames would interact with > overridden methods in class hierarchies. Presumably the names of the static > type of the call site would need be match, even though the runtime type > could differ. If a subclass overrode a method and changed its parameter > names (which currently has no affect on compatibility), the subclass would > no longer be substitutable for the parent class, which would break a > fundamental design principle. I guess that could be argued either way: - Specifying @PublicParameterNames means that overridden methods must keep the same parameter names, or - overridden methods can change the parameter names (with the static type of the call site used as you suggested). I think that at least the first alternative could be argued for (though that would limit applicability to only new classes), since changing the names of getters and setters will break callers, and named parameters could be considered to be similar to those. > At least there is no binary compatibility impact since the names would only > be checked at compile time and binary compatibility is about preserving the > ability to link. Yes, that was one of my main goals. Is that helpful? It seems that there wasn't a lot of enthusiasm for my proposal (or Reinier's and Jean-Battiste's alternatives), but I think that there is some elsewhere (as shown by the blogs that I referenced, and the fact that it was at least considered for JDK 6). It would be very helpful/interesting to me if anyone could suggest workable alternatives to solve my immediate problem of creating immutable objects with required (and named) parameters (in Java code and/or Spring-style config). Regards, Paul > > -Joe > > Paul Martin wrote: >> >> I'd like to propose the implementation of optionally named method >> parameters, and suggest that they are particularly useful when creating >> immutable objects (which are important in our increasingly concurrent >> world). >> >> Note that this is a topic that seems to have been considered before (see >> the >> note in http://paulhammant.com/blog/announcing_paranamer.html which >> suggests >> that it was even considered for Java 6), but I can't see it in the current >> list of Java 7 changes or in the Project Coin mailing list archives >> (though >> others have also discussed it in relation to Java 7, such as Alex Miller >> in >> http://tech.puredanger.com/2007/08/15/dr-java7/ and >> http://tech.puredanger.com/2007/10/11/java7-roundup-32/). ?Therefore I am >> proposing it here - I think that it is an important change (unless anyone >> can suggest how I can reasonably create an immutable object with four or >> more properties without using a Builder or a list of unnamed parameters). >> >> Also note that other relevant references include: >> http://blogs.sun.com/abuckley/entry/named_parameters (which discusses why >> parameter reordering might be difficult), >> http://beust.com/weblog/archives/000096.html (which suggests that we do >> not >> need named parameters, but really just shows the use of the Builder >> pattern >> which has limitations). >> >> >> Named method parameters >> >> AUTHOR(S): >> >> Paul Martin >> >> OVERVIEW >> >> FEATURE SUMMARY: >> >> Named parameters allow a method or constructor caller to explicitly state >> the parameter name of each parameter value passed to the method or >> constructor. ?Without named parameters, only the order of the parameter >> values is significant (and it may not be clear what each value >> represents). >> >> MAJOR ADVANTAGE: >> >> This is a relatively simple way of introducing named parameters to the >> Java >> platform. >> >> MAJOR BENEFIT: >> >> Named parameters allow method calls with relatively long lists of >> parameters >> (greater than 3) to be understood by developers. ?This can also facilitate >> the direct use of constructors and factory methods to create immutable >> objects, where otherwise Builders or mutable JavaBeans would be required. >> >> MAJOR DISADVANTAGE: >> >> The syntax for method calls would change to allow both named and unnamed >> parameters to be used. >> >> Named parameters might be used too often, which could unnecessarily >> clutter >> source files. >> >> Metadata to store the names of the parameters must be added to classfiles >> (for example as annotations). >> >> The use of annotations to describe named parameters would mean that no >> metadata would be stored about the parameter names used by the method >> caller, and so no runtime checks to match the parameter names being used >> could be made (only compile-time). ?If the parameter names change (but >> otherwise the method signature does not), then the method caller would not >> be aware of the changes until it was recompiled. ?Note that this is >> existing >> behaviour for unnamed parameters, and would only be a problem if the >> meaning >> of the parameters also changes (which should indicate that the caller >> would >> need to change anyway, but this would not be detected automatically at >> runtime). >> >> ALTERNATIVES: >> >> Unnamed parameters can make the same method calls as named parameters, but >> if there are many parameters they are harder to understand and prone to >> ordering-related bugs (particularly for primitive types or Strings). >> >> The Builder pattern can be used to simulate named parameters in >> constructors/factory methods. ?For example the following class uses a >> Builder to initialise itself (note that only two properties are used to >> simplify the example): >> >> ? ?public final class MyClass { >> >> ? ? ? ?private final String name; >> ? ? ? ?private final int age; >> >> ? ? ? ?private MyClass(Builder b) { >> ? ? ? ? ? ?this.name = b.name; >> ? ? ? ? ? ?this.age = b.age; >> ? ? ? ?} >> >> ? ? ? ?public static class Builder { >> >> ? ? ? ? ? ?private String name; >> ? ? ? ? ? ?private int age; >> >> ? ? ? ? ? ?/** >> ? ? ? ? ? ? * Name to set. >> ? ? ? ? ? ? */ >> ? ? ? ? ? ?public Builder setName(String name) { >> ? ? ? ? ? ? ? this.name = name; >> ? ? ? ? ? ? ? return this; >> ? ? ? ? ? ?} >> >> ? ? ? ? ? ?/** >> ? ? ? ? ? ? * Age to set >> ? ? ? ? ? ?*/ >> ? ? ? ? ? ?public Builder setAge(int age) { >> ? ? ? ? ? ? ? ?this.age = age; >> ? ? ? ? ? ? ? ?return this; >> ? ? ? ? ? ?} >> >> ? ? ? ? ? ?public MyClass build() { >> ? ? ? ? ? ? ? return new MyClass(this); >> ? ? ? ? ? ?} >> ? ? ? ?} >> ? ?} >> >> Objects can then be constructed in the following manner: >> >> ? ?MyClass obj = new MyClass.Builder().setName("Fred").setAge(53).build(); >> >> However, the use of a builder requires additional code, and all parameters >> are effectively optional from the perspective of the compiler (it cannot >> easily check that all of the required setter methods have been called), so >> bugs may occur where parameter values are not set. ?Note that runtime >> checks >> can be made to ensure that all property values are set, but they involve >> additional work and cannot be used by the compiler (though static analysis >> of the code in conjunction with annotations might be able to repeat many >> of >> these checks). >> >> There are also many ways to implement named parameters that are different >> to >> the solution proposed here. ?These include: >> >> Implement optional named parameters on all methods: ?This avoids the need >> for the @PublicParameterNames annotation, but may mean inconsistent usage >> of >> named parameters - the annotation is also a suggestion for the use of >> named >> parameters by the caller (which IDEs can also make use of). ?This will >> also >> highlight the difference to classfiles compiled with earlier versions of >> Java, where named parameters cannot be used at all (since it will then not >> be obvious when named parameters can and cannot be used). >> >> Add parameter names to the classfile as 'fundamental' method metadata >> rather >> than as annotations: This may allow closer integration of the named >> parameters with the rest of the language, but its impact on the rest of >> the >> language (and JVM) is much greater. ?The same inconsistencies and >> incompatibilities described in the previous alternative would also apply. >> In addition, the use of annotations should not preclude the subsequent >> modification of classfiles in a later release - the annotations could >> still >> remain (at a potential cost of some duplication). >> >> EXAMPLES >> >> SIMPLE EXAMPLE: >> >> Constructor declaration: >> >> ? ?@PublicParameterNames >> ? ?public MyClass(String name, int age) { .... >> >> Constructor use: >> >> ? ?MyClass obj = new MyClass(name: "Fred", age: 53); >> >> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >> >> The full class definition from the simple example is shown below, as a >> contrast to that provided in the Builder example. >> >> ? ?public final class MyClass { >> >> ? ? ? ?private final String name; >> ? ? ? ?private final int age; >> >> ? ? ? ?/** >> ? ? ? ? * @param name Name to set >> ? ? ? ? * @param age Age to set >> ? ? ? ? */ >> >> ? ? ? ?@PublicParameterNames >> ? ? ? ?public MyClass(String name, int age) { >> ? ? ? ? ? ?this.name = name; >> ? ? ? ? ? ?this.age = age; >> ? ? ? ?} >> ? ?} >> >> DETAILS >> >> SPECIFICATION: >> >> The @PublicParameterNames annotation is used on a constructor or method to >> allow named parameters to be used when calling it. ?It can also be applied >> to a class or package to apply to all methods within. ?Similarly, a >> @NoParameterNames annotation can be used on a constructor, method, or >> class >> to override the use of @PublicParameterNames at a higher level. >> >> The compiler can then automatically generate a >> @PublicParameterName(value="parameter-name") annotation for each affected >> method. ?These can then be used by the compiler (and IDE) to validate the >> parameter names used by callers of the method or constructor. >> >> The use of parameter names by callers is always optional (primarily for >> backwards compatibility). ?However, parameter names cannot be used for >> some >> parameters and not others (this would make the code harder to read). >> >> Parameters must always be specified in the same order regardless of >> whether >> parameter names are used - parameter reordering by callers is not allowed >> (reordering would make overloading difficult, and is not really >> necessary). >> >> Inheritance: Neither the @PublicParameterNames annotation (and >> @NoParameterNames annotation), or the names of the parameters themselves, >> need to be inherited. ?This is because only static evaluation of a >> caller's >> parameter names will be applied (rather than at runtime), so the callers >> parameter names only need to match those of the declared type of the >> target. ?However, it would still be advisable to reuse the same parameter >> names and annotations when overriding a method (IDEs could help with >> this). >> >> COMPILATION: >> >> The compiler must automatically generate a >> @PublicParameterName(value="parameter-name") annotation for each method >> and >> constructor annotated with @PublicParameterNames (or whose the parent >> class >> or package is annotated with @PublicParameterNames and the child class or >> method does not override it with @NoParameterNames). >> >> For example: >> >> ? ?int myMethod(int param1, String param2) >> >> Would effectively become: >> >> ? ?int myMethod(@PublicParameterName("param1") int param1, >> @PublicParameterName("param2") String param2) >> >> Method-calling syntax would need to change, using a colon to separate the >> parameter name and value where the are used. ?For example: >> >> ? MyClass obj = new MyClass(name: "Fred", age: 53); >> >> When a method caller uses parameter names, the compiler must check that >> those parameter names exactly match the value of generated >> @PublicParameterName annotations of the target method or constructor. ?It >> is >> a compilation error if they do not match or the target method or >> constructor >> does not have named parameters. >> >> IDEs can use the @PublicParameterNames and @NoParameterNames annotations >> (or >> @PublicParameterName directly) to automatically insert the relevant >> parameter names as part of code-completion. ?Additional refactoring >> support >> would also be required to enable parameter names to be renamed, or added >> and >> removed completely. >> >> Frameworks such as Spring can use the same annotations to allow objects to >> be created from their configuration files using named parameters to >> constructors and factory methods. ?Currently they only allow objects to be >> created from configuration files as JavaBeans (with setter methods) or >> with >> ordered (and unnamed) parameters. >> >> TESTING: >> >> The feature can be tested by compiling and running programs that exercise >> the feature. >> >> LIBRARY SUPPORT: >> >> No. >> >> REFLECTIVE APIS: >> >> java.lang.reflect.Method and java.lang.reflect.Constructor could be >> enhanced >> with new methods that return parameter names. ?However, that is not >> required >> to successfully implement the proposal. >> >> OTHER CHANGES: >> >> No. ?The use of named parameters is always optional. ?The javadoc tool >> already documents parameter names. ?Other tools/libraries might benefit >> from >> these changes, but their use is not required. >> >> MIGRATION: >> >> The @PublicParameterNames annotation (and @NoParameterNames annotation) >> simply needs to be added to the appropriate methods. ?IDEs could then >> suggest the use of parameter names for the method's callers, and apply the >> changes automatically. >> >> COMPATIBILITY >> >> BREAKING CHANGES: >> >> No. >> >> EXISTING PROGRAMS: >> >> The changes required by this feature should be transparent to existing >> source and class files if annotations are used internally to describe the >> named parameters. ?I am not sure what the impact would be otherwise. >> >> REFERENCES >> >> EXISTING BUGS: >> >> 4124331 (though it is set to 11-Closed, Will Not Fix, request for >> enhancement, and from 1998) >> >> > > From howard.lovatt at gmail.com Mon Apr 20 20:22:51 2009 From: howard.lovatt at gmail.com (howard.lovatt at gmail.com) Date: Tue, 21 Apr 2009 03:22:51 +0000 Subject: Automatic Resource Management, V.2 Message-ID: <0016364574ac6f02420468082926@google.com> I have a couple of reservations: 1. The use of try does not seem natural; it is too tied in my mind to Exceptions, can another keyword be used? 2. If we are using the specific block approach, eg try (...) {...}, then it does not seem natural that for each or similar closes the resource. If the approach used automatic closure of a resource at the end of the block that the resource was declared in, then for each etc. closing the resource would seem natural. I prefer that the resource is automatically closed at the end of the block and therefore for each etc. would naturally close at the end of their block also; but if the majority thinks a dedicated block structure is better, then I suggest that for each etc. are left out. Having stated my reservations I would rather see the proposal, as is, included, rather than nothing at all. Also thanks to Josh for putting so much effort into this. -- Howard. From jjb at google.com Tue Apr 21 12:44:56 2009 From: jjb at google.com (Joshua Bloch) Date: Tue, 21 Apr 2009 12:44:56 -0700 Subject: Automatic Resource Management, V.2 In-Reply-To: <0016364574ac6f02420468082926@google.com> References: <0016364574ac6f02420468082926@google.com> Message-ID: <17b2302a0904211244h5bf95c6by597996827d4c80e2@mail.gmail.com> Howard, On Mon, Apr 20, 2009 at 8:22 PM, wrote: > I have a couple of reservations: > > 1. The use of try does not seem natural; it is too tied in my mind to > Exceptions, But there are exceptions involved here! A main point of the construct is that it closes resources, even in the presence of exceptions. I think that's why others find it so natural. > can another keyword be used? There's no technical reason not to, but we have to decide what's best from a language-design standpoint. > > > 2. If we are using the specific block approach, eg try (...) {...}, then it > does not seem natural that for each or similar closes the resource. If the > approach used automatic closure of a resource at the end of the block that > the resource was declared in, then for each etc. closing the resource would > seem natural. I prefer that the resource is automatically closed at the end > of the block and therefore for each etc. would naturally close at the end > of their block also; but if the majority thinks a dedicated block structure > is better, then I suggest that for each etc. are left out. Yeah, this could go either way. > > Having stated my reservations I would rather see the proposal, as is, > included, rather than nothing at all. > > Also thanks to Josh for putting so much effort into this. And thanks so much for your encouragement! Josh From Joe.Darcy at Sun.COM Tue Apr 21 13:55:26 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 21 Apr 2009 13:55:26 -0700 Subject: Non-proposal: Final Interfaces In-Reply-To: <212322090904201549h73d23c82t728ef2f4b15a45ac@mail.gmail.com> References: <212322090904201449u4e19e48apc93722035555a317@mail.gmail.com> <212322090904201549h73d23c82t728ef2f4b15a45ac@mail.gmail.com> Message-ID: <49EE32BE.6060906@sun.com> Yes, the proposal is out of date for consideration and the modularity language features for JSR 294 may support this kind of capability. -Joe On 04/20/09 03:49 PM, Paulo Levi wrote: > Actually the > "All methods that are deprecated can be deleted on the interface and all > implementations (since they are controlled completly.)" > > Doesn't apply since clients use the methods, but methods can be added > "(since they are controlled completly.)". > > On Mon, Apr 20, 2009 at 10:49 PM, Paulo Levi wrote: > > >> *I know this is much out of date for consideration, but i think that this >> is a idea that would really help library evolution, and i did not see any of >> this kind of strategy floating around in the other proposals. >> * >> >> * >> * >> >> *AUTHOR(S):* Paulo Levi Martins Faria, a student at FCUL, faculdade de >> ciencias da universidade de lisboa at Lisbon, Portugal. >> >> *OVERVIEW* >> >> A way for interfaces to be used as references outside a package, but the >> only implementations of them to exist on a package, to allow the evolution >> (adding) of methods to interfaces and all their implementations. >> >> FEATURE SUMMARY: >> >> insted of declaring interfaces as: >> >> package xyz; >> >> public interface A{ >> >> } or >> >> package xyz; >> >> interface A{ >> >> } >> >> declare them as : >> >> package xyz; >> >> public final interface A{ >> >> } >> >> And all implementations or extensions of A must be in the package xyz >> >> >> MAJOR ADVANTAGE: What makes the proposal a favorable change? >> >> This would allow library authors to control the evolution of the >> implementations of a common interface, deprecating old methods, while at the >> same time allowing clients to program to the interfaces. The prohibition of >> implementation/extension outside of package allows the library author to >> control the package evolution completly. I have personally seen cases where >> performance reasons lead to dangerous downcasts or using the raw type, >> and/or subclassing of various classes, to implement something more >> efficiently than the library core can, because of public interfaces. >> >> MAJOR BENEFIT: >> >> The jdk can decide if certain interfaces are not likely to be extended >> outside of the library, and thus control api evolution more completly. >> >> All methods that are deprecated can be deleted on the interface and all >> implementations (since they are controlled completly.) >> >> MAJOR DISADVANTAGE: >> >> Can not be retrofitted to existing api's (easily). >> >> Somewhat overlapping with abstract classes, but more powerfull. >> >> Losses flexibility of extension for clients, a risk i am well disposed >> towards. >> >> ALTERNATIVES: Can the benefits and advantages be had some way without a >> language change? >> >> Can think of a way how. >> >> *EXAMPLES* >> >> Show us the code! >> >> SIMPLE EXAMPLE: Show the simplest possible program utilizing the new >> feature. >> >> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >> >> *DETAILS* >> >> SPECIFICATION: Describe how the proposal affects the grammar, type system, >> and meaning of expressions and statements in the Java Programming Language >> as well as any other known impacts. >> >> COMPILATION: How would the feature be compiled to class files? Show how the >> simple and advanced examples would be compiled. Compilation can be expressed >> as at least one of a desugaring to existing source constructs and a >> translation down to bytecode. If a new bytecode is used or the semantics of >> an existing bytecode are changed, describe those changes, including how they >> impact verification. Also discuss any new class file attributes that are >> introduced. Note that there are many downstream tools that consume class >> files and that they may to be updated to support the proposal! >> >> I don't think that this changes compilation beyond the type checj >> >> TESTING: How can the feature be tested? >> >> Try to implement extend a final interface outside its package. >> >> LIBRARY SUPPORT: Are any supporting libraries needed for the feature? >> >> No. >> >> REFLECTIVE APIS: Do any of the various and sundry reflection APIs need to >> be updated? This list of reflective APIs includes but is not limited to core >> reflection (java.lang.Class and java.lang.reflect.*), javax.lang.model.*, >> the doclet API, and JPDA. >> >> Don't think so. >> >> OTHER CHANGES: Do any other parts of the platform need be updated too? >> Possibilities include but are not limited to JNI, serialization, and output >> of the javadoc tool. >> >> No. >> >> MIGRATION: >> >> Create a new final sub interface to public one on the api, deplicate >> methods taking that interface to use the new one. Deprecate the old methods >> and interfaces. Wait for the pichforks. >> >> *COMPATIBILITY* >> >> BREAKING CHANGES: Are any previously valid programs now invalid? If so, >> list one. >> >> None >> >> EXISTING PROGRAMS: How do source and class files of earlier platform >> versions interact with the feature? Can any new overloadings occur? Can any >> new overriding occur? >> >> No >> >> *REFERENCES* >> >> >> > > From i30817 at gmail.com Tue Apr 21 16:40:16 2009 From: i30817 at gmail.com (Paulo Levi) Date: Wed, 22 Apr 2009 00:40:16 +0100 Subject: Non-proposal: Final Interfaces In-Reply-To: <49EE32BE.6060906@sun.com> References: <212322090904201449u4e19e48apc93722035555a317@mail.gmail.com> <212322090904201549h73d23c82t728ef2f4b15a45ac@mail.gmail.com> <49EE32BE.6060906@sun.com> Message-ID: <212322090904211640r1e534c57l66dd983d19980548@mail.gmail.com> On Tue, Apr 21, 2009 at 9:55 PM, Joe Darcy wrote: > Yes, the proposal is out of date for consideration and the modularity > language features for JSR 294 may support this kind of capability. > > -Joe > How? I've not been following the super packages debate. Notice that unlike Abstract classes (that can add methods too) this would forbid extensions. Besides i like that it is the topmost abstraction in the type system that does this, so reference values can be nicely generic. From howard.lovatt at gmail.com Tue Apr 21 17:27:44 2009 From: howard.lovatt at gmail.com (howard.lovatt at gmail.com) Date: Wed, 22 Apr 2009 00:27:44 +0000 Subject: Automatic Resource Management, V.2 In-Reply-To: <17b2302a0904211244h5bf95c6by597996827d4c80e2@mail.gmail.com> Message-ID: <0016e64aeb44094311046819d57b@google.com> Hi Josh, On Apr 22, 2009 5:44am, Joshua Bloch wrote: [snip] > 1. The use of try does not seem natural; it is too tied in my mind to > Exceptions, > But there are exceptions involved here! A main point of the construct is > that it closes resources, > even in the presence of exceptions. I think that's why others find it so > natural. None of these decisions are ever easy, if they were we wouldn't be discussing them! I can see the exception argument; but on balance I would find another approach better, ie either a different keyword or better still closing based on variable scope. At the end of the day I find all of these three solutions, try, other keyword, or scope, better than what we currently have and therefore support any of the variations. -- Howard. From howard.lovatt at gmail.com Tue Apr 21 17:52:59 2009 From: howard.lovatt at gmail.com (howard.lovatt at gmail.com) Date: Wed, 22 Apr 2009 00:52:59 +0000 Subject: PROPOSAL: Named method parameters Message-ID: <001636458a864f71e304681a2fb7@google.com> I use the builder pattern successfully via my enhanced compiler ( pet project :) ): https://pec.dev.java.net/nonav/compile/index.html and in particular: https://pec.dev.java.net/nonav/compile/javadoc/pec/compile/immutable/ImmutableValueConversions.html The enhanced compiler enforces the pattern, ie if you get it wrong the compiler gives you an error message. You can also use a simple structure like class, eg: class Point { static class Args { int x = 0; int y = 0; } final int x; final iny y; Point( Args args ) { x = args.x; y = args.y; } ... } Which is used like: Point p = new Point( new Point.Args() {{ x = 1; }} ); As the original post said you would only use this if there were a lot of arguments, therefore the overhead of typing "new Point.Args() {{ }}" is negligible. -- Howard. From brucechapman at paradise.net.nz Tue Apr 21 19:51:40 2009 From: brucechapman at paradise.net.nz (brucechapman at paradise.net.nz) Date: Wed, 22 Apr 2009 14:51:40 +1200 (NZST) Subject: Automatic Resource Management, V.2 In-Reply-To: References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> <17b2302a0904210834l55f665d9w52613c792989abb0@mail.gmail.com> <15e8b9d20904210852t2b8aa5f7n77012ae7397b6eb1@mail.gmail.com> <49EDF057.3080906@univ-mlv.fr> <15e8b9d20904210948s58366d7as4bcbd1cea653bc6@mail.gmail.com> Message-ID: <1240368700.49ee863cac96e@www.paradise.net.nz> Quoting Tom Ball : > My "vote" (I realize this isn't a democracy :-) is to avoid adding any > new > rules, but instead keep it simple: resources in source code go into all > tables like any other local variable currently does, while any > compiler-generated temporary variables get flagged as synthetic and are > included in any tables that include synthetic variables. In other words, > a > resource should be treated exactly like a local variable already is, > synthetic or not. A resource is a local variable, after all, just one > that > has some automatic cleanup as it leaves scope. > > BTW, I like Bruce Chapman's suggestion that the type of a temporary > variable > be AutoCloseable. Since the only thing the compiler generated code will > do > with that object is call its close() method, there's no advantage to it > having additional type information. And I think (despite Josh's explanation for why the source code desugaring can't be AutoClosable) that the fact that AutoClosable.close() throws Exception instead of something specific (or nothing), doesn't matter in the class file format because the compiler will have already dealt with the specific (if any) possible exceptions on the actual (possible intersection or recursive) type of the resource expression by either ensuring that they are caught, or declared thrown in the enclosing method. The only nit here would be if the verifier did Exception checking and complained that Exception was not caught, but I don't think that is the case (from a quick browse of the verifier spec, tho I am in NO WAY AT ALL knowledgable about such things). -anyone know for sure?? Bruce > > Tom > > On Tue, Apr 21, 2009 at 9:48 AM, Neal Gafter wrote: > > > On Tue, Apr 21, 2009 at 9:12 AM, R?mi Forax > wrote: > > > > > > > >> You can probably avoid this mess by being explicit about the > > specification > > >> rather than attempting the "as-if" rewriting. If a construct like > this > > is > > >> to be integrated into the JLS that would probably be required > anyway, > > and > > >> a > > >> new set of issues is likely to be exposed by the attempt. It would > be > > >> better to get the specification wrung out earlier rather than later > (I > > >> don't > > >> think Alex will be eager to do it himself). > > >> > > >> > > >> > > > Why the local var need to be visible in these tables ? > > > > > > The compiler already introduced new local var , by example, in case > of > > > ++/-- and > > > compound assignments on boxed type (using the hidden instruction > > LetExpr). > > > In that case the local var is flagged SYNTHETIC and doesn't appear > in > > local > > > vars tables. > > > > > > Right: if the specification is spelled out, one can decide on a > > case-by-case > > basis how to handle the mapping to the class file. However, you can't > avoid > > these variables appearing in the verifier tables at the very least. > In > > that > > case the natural type based on the current spec is its erasure, which > is > > not > > necessarily AutoCloseable. > > > > > From markmahieu at googlemail.com Tue Apr 21 20:44:42 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 22 Apr 2009 04:44:42 +0100 Subject: Automatic Resource Management, V.2 In-Reply-To: <1240368700.49ee863cac96e@www.paradise.net.nz> References: <17b2302a0904192345t29997036oc08a81068e7b5829@mail.gmail.com> <15e8b9d20904210800v762e39a4t5ba75d660780e2@mail.gmail.com> <17b2302a0904210834l55f665d9w52613c792989abb0@mail.gmail.com> <15e8b9d20904210852t2b8aa5f7n77012ae7397b6eb1@mail.gmail.com> <49EDF057.3080906@univ-mlv.fr> <15e8b9d20904210948s58366d7as4bcbd1cea653bc6@mail.gmail.com> <1240368700.49ee863cac96e@www.paradise.net.nz> Message-ID: 2009/4/22 > > The only nit here would be if the verifier did > Exception checking and complained that Exception was not caught, but I > don't > think that is the case (from a quick browse of the verifier spec, tho I am > in NO > WAY AT ALL knowledgable about such things). > > -anyone know for sure?? > > Bruce > If I understand you correctly then no, the verifier wouldn't care; checked exceptions are a language-level feature. Mark From brucechapman at paradise.net.nz Tue Apr 21 20:54:25 2009 From: brucechapman at paradise.net.nz (brucechapman at paradise.net.nz) Date: Wed, 22 Apr 2009 15:54:25 +1200 (NZST) Subject: Automatic Resource Management, V.2 In-Reply-To: <0016e64aeb44094311046819d57b@google.com> References: <0016e64aeb44094311046819d57b@google.com> Message-ID: <1240372465.49ee94f1976fc@www.paradise.net.nz> > At the end of the day I find all of > these > three solutions, try, other keyword, or scope, better than what we > currently have and therefore support any of the variations. > > -- Howard. > If language design decisions were based on accepting anything that was better rather than best, then you'd incrementally get way off course, because you cannot rework previous errors of judgement. As we all know, its hard enough to keep roughly on course when all practical effort is made to be "best" at each increment. It's called entropy and it never decreases, and the more you have, the harder it is to do more work. The wise thing to do is minimise the entropy of every change in order to maximise the opportunities for future change. Bruce From markmahieu at googlemail.com Tue Apr 21 21:16:52 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 22 Apr 2009 05:16:52 +0100 Subject: Automatic Resource Management, V.2 In-Reply-To: <1240372465.49ee94f1976fc@www.paradise.net.nz> References: <0016e64aeb44094311046819d57b@google.com> <1240372465.49ee94f1976fc@www.paradise.net.nz> Message-ID: 2009/4/22 > > At the end of the day I find all of > > these > > three solutions, try, other keyword, or scope, better than what we > > currently have and therefore support any of the variations. > > > > -- Howard. > > > > If language design decisions were based on accepting anything that was > better > rather than best, then you'd incrementally get way off course, because you > cannot rework previous errors of judgement. As we all know, its hard enough > to > keep roughly on course when all practical effort is made to be "best" at > each > increment. > > It's called entropy and it never decreases, and the more you have, the > harder it > is to do more work. The wise thing to do is minimise the entropy of every > change > in order to maximise the opportunities for future change. > > > Bruce > > Indeed. There are clearly many factors, but I think much of the debate around ARM (and some of the other proposals) is interesting to look at from the perspective of one particular hypothetical question: "If the aim of Project Coin had been to identify just *one* proposal, but to then allocate the same resources to it as are currently earmarked for the entire project (in order to 'do that one thing right', so to speak), would the proposal still be the same?" Or, "just how big is this elephant anyway?" ;) Mark From Ruslan at Shevchenko.Kiev.UA Tue Apr 21 21:40:58 2009 From: Ruslan at Shevchenko.Kiev.UA (Ruslan Shevchenko) Date: Wed, 22 Apr 2009 07:40:58 +0300 (EEST) Subject: object switch: Re: scripts and results (was Helping to find the usefulness of a proposal) In-Reply-To: <49EDEAAC.2040100@gmx.de> References: <60287e9e1530b3e1ae49976316e8dc57.squirrel@wmail.gradsoft.ua> <49E5F020.7060508@gmx.de> <114ad93adfd2eb30f7ecd1388b69b1be.squirrel@wmail.gradsoft.ua> <49EDEAAC.2040100@gmx.de> Message-ID: <45f61be4417d9d2c8b24f3a2257c87c6.squirrel@wmail.gradsoft.ua> > Hi, Ulf You pattern was included in statistics as 'object switch'. P.S. 1) Looking now: I forgot add splitting of 'RelationExpression' in it - this will be added, sorry. 2) May be you overseen mention of 'object switch' because all switch patterns (string, instanceof, object) where not in list of patterns, for which is possible count percentage among simular language constructs. It's because such pattern change 'if' to 'switch' and I have not idea how to find simple one-number metric to show effects of such change. > Hopfully you will find time next days. :-) > > Regards, > > Ulf > > > From vapor1 at teleport.com Tue Apr 21 21:47:06 2009 From: vapor1 at teleport.com (Derek Foster) Date: Tue, 21 Apr 2009 21:47:06 -0700 (GMT-07:00) Subject: Proposal: Indexing access syntax for Lists and Maps Message-ID: <22913460.1240375626476.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> I like your idea of including Set as well. I think it makes intuitive sense with regards to a set as a quality of its members. (e.g. the set "blue" has members which are blue, and thus "blue[x]" represents "is x blue?" However, if we were to do so, I think that "bool foo = (set[y] = bar)" should always result in 'foo' being equal to 'bar', not in it getting the assigned the return value of set.add() or set.remove() as your desugaring implies. Derek -----Original Message----- >From: Tim Keith >Sent: Mar 29, 2009 10:40 PM >To: coin-dev at openjdk.java.net >Subject: Re: Proposal: Indexing access syntax for Lists and Maps > >Is it possible to include Set as well? > >E.g. "bool = set[x]" meaning "bool = set.contains(x)" >and "set[x] = bool" meaning "bool ? set.add(x) : set.remove(x)" > >-- Tim > >On Sun, Mar 29, 2009 at 5:12 PM, Shams Mahmood wrote: > >> Indexing access syntax for Lists and Maps >> >> VERSION >> This is version 1.0. >> >> AUTHOR(S): >> Shams Mahmood Imam >> >> OVERVIEW >> >> FEATURE SUMMARY: >> Collection classes are among the most frequently used in the Java SDK. >> Currently Lists and Maps do not provide any additional language >> feature to access individual elements unlike Arrays. This proposal >> aims to provide these Collection citizens of java additional >> language support to access elements like Arrays have currently. >> >> MAJOR ADVANTAGE: >> Will provide a consistent syntax for accessing elements of Arrays, >> Lists and Maps. In addition, the language grammar will not change >> much since the subscript operator is already supported for Arrays. >> >> MAJOR BENEFIT: >> Apart from the consistency mentioned above, implementation fo this >> feature will result in fewer characters needed to be typed to achieve >> simple access to elements in Maps/Lists. >> >> MAJOR DISADVANTAGE: >> Like the for-each loop construct, it will expose the client to >> NullPointerException(NPE)s when used with a null List/Map. However, >> this shouldn't be such a major issue as NPEs are also generated >> by arrays when the operator is used in a null array. >> >> ALTERNATIVES: >> The comparatively more verbose get/set methods for Lists and get/put >> methods for Maps. >> >> EXAMPLES >> >> SIMPLE EXAMPLE: >> >> public class Main { >> public static void main(String[] arguments) { >> List l1 = Arrays.asList(new String[] {"a", "b", "c"}); >> String firstElement = l1[0]; >> Map m1 = new HashMap(4); >> m1[Integer.valueOf(1)] = "One"; >> } >> } >> >> ADVANCED EXAMPLE: >> >> public class Main { >> public static void main(String[] arguments) { >> List l1 = Arrays.asList(new String[] {"a", "b", "c"}); >> Map m1 = new HashMap(4); >> Map m2 = new HashMap(4); >> >> m2[l1[2]] = m2[m1[1]] = 4; // same as m2.put(l1.get(2), >> m2.put(m1.get(1), 4)); >> } >> } >> >> DETAILS >> >> SPECIFICATION: >> Java Language Specification changes: >> >> 15.29 (NEW CHAPTER): Collection Access Expressions >> A collection access expression contains two subexpressions, the List/Map >> reference expression (before the left bracket) and the index expression >> (within the brackets). Note that the List/Map reference expression may be a >> name or any expression that evaluates to a List/Map. The index experssion is >> expected to evaluate to an int for Lists and a valid key type for Maps. >> >> CollectionAccess: >> Expression [ Expression ] >> >> 15.8 Primary Expressions >> original: >> --------- >> PrimaryNoNewArray: >> Literal >> Type . class >> void . class >> this >> ClassName.this >> ( Expression ) >> ClassInstanceCreationExpression >> FieldAccess >> MethodInvocation >> ArrayAccess >> >> replaced with: >> -------------- >> PrimaryNoNewArray: >> Literal >> Type . class >> void . class >> this >> ClassName.this >> ( Expression ) >> ClassInstanceCreationExpression >> FieldAccess >> MethodInvocation >> ArrayAccess >> CollectionAccess >> >> 15.26 Assignment Operators >> original: >> --------- >> LeftHandSide: >> ExpressionName >> FieldAccess >> ArrayAccess >> >> replaced with: >> -------------- >> LeftHandSide: >> ExpressionName >> FieldAccess >> ArrayAccess >> CollectionAccess >> >> >> COMPILATION: >> >> After successful creation of the AST handling the additional grammar for >> Collection Access expressions, the syntactic sugar will be replaced by >> JDK1.4 compatible code during the Code Generation phase. This is consistent >> with how JDK5.0 constructs like the for-each loop is handled by the >> compiler. >> >> e.g. >> public class TestConcise { >> public static void main(String[] args) { >> java.util.Map m1 = new java.util.HashMap> String>(); >> m1[2] = "two"; >> >> java.util.LinkedList l1 = java.util.Arrays.asList( new String[] >> {"a", "b", "c" }); >> m1[3] = l1[2]; >> l1[0] = m1[0]; >> l1[1] = "one"; >> } >> } >> >> is converted to >> public class TestConcise { >> public TestConcise() { >> super(); >> } >> >> public static void main(String[] args) { >> java.util.Map m1 = new java.util.HashMap> String>(); >> m1.put(Integer.valueOf(2), "two"); >> >> java.util.LinkedList l1 = java.util.Arrays.asList( new String[] >> {"a", "b", "c" }); >> m1.put(Integer.valueOf(3), l1.get(2)); >> l1.set(0, m1.get(Integer.valueOf(0))); >> l1.set(1, "one"); >> } >> } >> >> >> TESTING: >> >> LIBRARY SUPPORT: >> No additional library support is needed. >> >> REFLECTIVE APIS: >> This proposal does not require any reflective API changes. >> >> OTHER CHANGES: >> No changes required. >> >> MIGRATION: >> No migration is needed. >> >> COMPATIBILITY >> >> BREAKING CHANGES: >> No breaking changes. >> >> EXISTING PROGRAMS: >> Existing programs are not affected by this change. >> >> REFERENCES >> My Java7 Wishlist regarding Collections, >> http://shamsmi.blogspot.com/2008/04/my-java7-wishlist-regarding-collections.html >> Implementation of My Java7 Wishlist, >> http://shamsmi.blogspot.com/2008/05/implementation-of-my-java7-wishlist.html >> >> EXISTING BUGS: >> None. >> >> URL FOR PROTOTYPE (optional): >> Projects kijaro's concisecollections branch: >> https://kijaro.dev.java.net/source/browse/kijaro/branches/concisecollections/ >> >> >> >> >> > From vapor1 at teleport.com Tue Apr 21 21:55:11 2009 From: vapor1 at teleport.com (Derek Foster) Date: Tue, 21 Apr 2009 21:55:11 -0700 (GMT-07:00) Subject: Submission: switch (...) instanceof feature Message-ID: <11471303.1240376112054.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> Like Gabriel, I have severe reservations about this proposal. I am concerned that it will encourage people to avoid the common OOP "best practice" of using virtual method dispatch in favor of doing an explicit "switch" on each subtype of a type, in cases where doing so is not necessary. I concede that there are a few (FEW!) places where doing the equivalent of a switch on instances of a type is necessary (for instance, if the type is in a library you don't have the ability to change). I can see some value in this proposal for that purpose. However, I would very much not like to see use of this construct become commonplace. I already see too many instances of people doing the equivalent of "if (object.type == FOO) {doThis(); } else if (object.type == BAR) { doThat(); }" instead of writing "object.doSomething();" Derek -----Original Message----- >From: Gabriel Belingueres >Sent: Mar 30, 2009 7:31 AM >To: Jeroen van Maanen >Cc: coin-dev at openjdk.java.net >Subject: Re: Submission: switch (...) instanceof feature > >IMO I'm against this. > >First, it is against current best practices for the design of >object-oriented software to make easier to code something with a case >statement on types/classes. > >Second: > void log(Object object) { > switch (object) instanceof { > case String: > logger.debug("'" + object + "'"); > case Date: > logger.debug(object.getTime()); > case void: > logger.debug("null"); > default: > logger.debug("<" + object.toString() + ">"); > } > } > >It think it is clearer (when possible) writing it with several >overloaded methods and double dispatching. > >Third: > } catch (Exception exception) { > switch (exception.getCause()) instanceof { > case ParseException: > log.warn("Could not get status for '" + id + ": " + >exception.getCause()); > default: > log.warn("Could not get status for '" + id + ", exception); > } >} > >in the case you intentionally left out the break statement, then the >switch statement is not any clearer than doing an if. >in the case that you wanted the break statement on the ParseException >case, it is even clearer to use two catch blocks (one for >ParseException and other for Throwable. > > >2009/3/29 Jeroen van Maanen : >> I'd like to coin a switch (...) instanceof statement as a new feature of the >> Java language. Please accept the attached proposal for review. >> >> Regards, Jeroen >> >> PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 >> >> AUTHOR(S): Jeroen van Maanen >> >> OVERVIEW >> >> FEATURE SUMMARY: The instanceof switch statement allows for clear and >> concise >> handling of alternatives that depend on the type of a given object. >> >> MAJOR ADVANTAGE: The instanceof switch statement removes the need for >> different >> names for the same object with different types and the extra declarations >> and >> casts to define those names. >> >> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? >> >> MAJOR DISADVANTAGE: Coders, reviewers, and IDE's need to be able to read the >> new statement and interpret and treat it correclty. >> >> ALTERNATIVES: There are no alternatives. >> >> EXAMPLES >> >> SIMPLE EXAMPLE: >> >> ?void log(Object object) { >> ? ?switch (object) instanceof { >> ? ?case String: >> ? ? ?logger.debug("'" + object + "'"); >> ? ?case Date: >> ? ? ?logger.debug(object.getTime()); >> ? ?case void: >> ? ? ?logger.debug("null"); >> ? ?default: >> ? ? ?logger.debug("<" + object.toString() + ">"); >> ? ?} >> ?} >> >> ADVANCED EXAMPLE: >> >> ?public StatusEnum getStatus(String id) { >> ? ?StatusEnum result; >> ? ?try { >> ? ? ?result = internalGetStatus(id); >> ? ?} catch (Exception exception) { >> ? ? ?switch (exception.getCause()) instanceof { >> ? ? ?case ParseException: >> ? ? ? ?log.warn("Could not get status for '" + id + ": " + >> exception.getCause()); >> ? ? ?default: >> ? ? ? ?log.warn("Could not get status for '" + id + ", exception); >> ? ? ?} >> ? ?} >> ?} >> >> public class PrettyPrinter { >> ?private Writer writer; >> >> ?public PrettyPrinter(Writer writer) { >> ? ?this.writer = writer; >> ?} >> >> ?public write(Object object) { >> ? ?switch (object) instanceof { >> ? ? ?case String: >> ? ? ? ?writer.write(stringDenotation(object)); >> ? ? ?case Collection: >> ? ? ? ?writer.write(object.getClass().getSimpleName() + ": ["); >> ? ? ? ?for (Object element : object) { >> ? ? ? ? ?write(element); >> ? ? ? ? ?writer.write(","); >> ? ? ? ?} >> ? ? ? ?writer.write("]"); >> ? ? ?case Map: >> ? ? ? ?write(object.entrySet()); >> ? ? ?case Map.Entry: >> ? ? ? ?write(object.getKey()); >> ? ? ? ?writer.write(":"); >> ? ? ? ?write(object.getValue()); >> ? ? ?case void: >> ? ? ? ?writer.write("null"); >> ? ? ?default: >> ? ? ? ?// TODO: deal with arrays of unknown base type >> ? ? ? ?writer.write("<" + object.toString() + ">"); >> ? ?} >> ?} >> >> ?private stringDenotation(String str) { >> ? ?... >> ?} >> >> } >> >> DETAILS >> >> SPECIFICATION: The switch instanceof feature adds an alternative to the >> switch >> statement to the grammar. >> >> ?SwitchStatement: >> ? ?switch ( Expression ) SwitchBlock >> ? ?switch ( Identifier ) instanceof TypeSwitchBlock >> >> ?TypeSwitchBlock: >> ? ?{ TypeSwitchBlockStatementGroups? TypeSwitchLabels? } >> >> ?TypeSwitchBlockStatementGroups: >> ? ?TypeSwitchBlockStatementGroup >> ? ?TypeSwitchBlockStatementGroups TypeSwitchBlockStatementGroup >> >> ?TypeSwitchBlockStatementGroup: >> ? ?TypeSwitchLabel BlockStatements >> >> ?TypeSwitchLabel: >> ? ?case Type : >> ? ?case void : >> ? ?default : >> >> COMPILATION: The statement >> >> ?switch (<>) instanceof { >> ?case <>: >> ? ?<> >> ?case <>: >> ? ?<> >> ?... >> ?case void: >> ? ?<> >> ?... >> ?default: >> ? ?<> >> ?} >> >> Would be compiled by desugaring it to >> >> ?if (<> instanceof <>) { >> ? ?<> <> = (<>) <>; >> ? ?<> >> ?} >> ?else if (<> instanceof <>) { >> ? ?<> <> = (<>) <>; >> ? ?<> >> ?} >> ?... >> ?else if (<> == null) { >> ? ?<> >> ?} >> ?... >> ?else { >> ? ?<> >> ?} >> >> TESTING: The feature can be tested by compiling and running the examples and >> comparing the results with the had coded expected desugared versions. >> >> LIBRARY SUPPORT: The feature needs no additional library support. >> >> REFLECTIVE APIS: The feature does not affect reflective api's. >> >> OTHER CHANGES: The feature does not need other changes. >> >> MIGRATION: This feature does not invalidate existing code. An existing code >> base could be scanned for type casts. Occurrences of type casts should be >> manually evaluated and, if desired, recoded using the new feature. >> >> COMPATIBILITY >> >> BREAKING CHANGES: This feature does not invalidate existing code. >> >> EXISTING PROGRAMS: This feature has no impact on existing code. >> >> REFERENCES >> >> EXISTING BUGS: There are no existing Sun bug ids related to this proposal. >> >> URL FOR PROTOTYPE: Not available. >> >> >> >> > From vapor1 at teleport.com Tue Apr 21 22:07:23 2009 From: vapor1 at teleport.com (Derek Foster) Date: Tue, 21 Apr 2009 22:07:23 -0700 (GMT-07:00) Subject: DISCUSSION: Bean/Data classes Message-ID: <15002000.1240376843205.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> I just wanted to voice some agreement to this sentiment. (And I REALLY want closures, so saying that some form of property support is more important is saying something!). Mostly, I want to never have to write a simple getter again. The are just clutter, and wasted time to maintain. (Setters, I can generally do without, since I prefer immutable classes.) I am amazed that after six revisions of the Java language that we still don't have support for some form of automatic generation of getters for simple properties. Derek -----Original Message----- >From: Stephen Colebourne >Sent: Mar 25, 2009 3:33 PM >To: coin-dev at openjdk.java.net >Subject: DISCUSSION: Bean/Data classes > >Finally, I should say that of all the things Java lacks, I think >properties is the biggest - bigger than closures. The sheer amount of >wasted effort, lines of code, lack of consistency and sheer focus on the >low level detail rather than the high level abstraction is staggering. >It is IMO a far bigger hole in writing good Java apps today than >closures (or any other language proposal). > >Stephen From Ruslan at Shevchenko.Kiev.UA Tue Apr 21 22:23:22 2009 From: Ruslan at Shevchenko.Kiev.UA (Ruslan Shevchenko) Date: Wed, 22 Apr 2009 08:23:22 +0300 (EEST) Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <49EDE7B4.2090006@sun.com> References: <49C56020.2070207@joda.org> <49EDE7B4.2090006@sun.com> Message-ID: > Catching up on proposal commenting, while I find the design generally > acceptable, I remain unconvinced that the inability to replace all > pre-JDK 5 for loops with some newer, improved for loop is a serious > enough problem to justify further language changes beyond the enhanced > for loop in JDK 5. > > Some data on how often such a new construct would be applicable would > help here. > Partially it was RemoveInLoop (which count access to remove within while operator) in http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001496.html Number was quite low (for example 62 in JDK) I will try to add count for remove-in-for and index-access during next iteration in my set of coin syntax-patterns. (during next week-end if we have no time constraints) > -Joe > > Stephen Colebourne wrote: >> Enhanced for each loop iteration control >> >> (re-sent with correct subject line) >> >> This proposal extends the for each loop to allow access to meta data >> including the index and the remove method. >> >> (This proposal doesn't really go into enough detail - with JSR-310 my >> time here is limited. I'd hope that there is just about enough >> though....) >> >> ----------------------------------------------------------------------------------- >> Enhanced for each loop iteration control >> >> AUTHOR(S): >> Stephen Colebourne >> >> *OVERVIEW* >> >> FEATURE SUMMARY: >> Extends the Java 5 for-each loop to allow access to the loop index, >> whether this is the first or last iteration, and to remove the current >> item. >> >> MAJOR ADVANTAGE: >> The for-each loop is almost certainly the most new popular feature from >> Java 5. It works because it increases the abstraction level - instead of >> having to express the low-level details of how to loop around a list or >> array (with an index or iterator), the developer simply states that they >> want to loop and the language takes care of the rest. However, all the >> benefit is lost as soon as the developer needs to access the index or to >> remove an item. >> >> The original Java 5 for each work took a relatively conservative stance >> on a number of issues aiming to tackle the 80% case. However, loops are >> such a common form in coding that the remaining 20% that was not tackled >> represents a significant body of code. >> >> The process of converting the loop back from the for each to be index or >> iterator based is painful. This is because the old loop style if >> significantly lower-level, more verbose and less clear. It is also >> painful as most IDEs don't support this kind of 'de-refactoring'. >> >> MAJOR BENEFIT: >> A common coding idiom is expressed at a higher abstraction than at >> present. This aids readability and clarity. >> >> Accessing the index currently requires using an int based loop, or >> placing a separate int counter outside the loop (which then remains in >> scope after the loop). The proposed solution doesn't result in manual >> manipulation of the index. >> >> Accessing the iterator remove requires using an iterator based loop. >> With generics this is remarkably verbose. The proposed solution is >> significantly shorter and cleaner. >> >> MAJOR DISADVANTAGE: >> The enhanced for each loop is complicated with additional functionality. >> (This is mitigated by being easy and obvious to use) >> >> More code is generated magically by the compiler. (This is mitigated by >> a simple desugaring) >> >> ALTERNATIVES: >> Use the existing language constructs, typically the standard for loop. >> >> Use BGGA/JCA style closures, with control statements. It should be noted >> that these are consistently the most controversial parts of the closure >> debate, making the 'let's wait for closures' argument against this >> proposal weaker (as any final closures implementation may not include >> control statements). >> >> >> *EXAMPLES* >> >> SIMPLE EXAMPLE: >> >> StringBuilder buf = new StringBuilder(); >> for (String str : list : it) { >> if (str == null) { >> it.remove(); >> } >> } >> >> whereas, today we write: >> >> StringBuilder buf = new StringBuilder(); >> for (Iterator it = list.iterator(); it.hasNext();) { >> String str = it.next(); >> if (str == null) { >> it.remove(); >> } >> } >> >> ADVANCED EXAMPLE: >> >> Example1: >> >> for (String str : list : it) { >> System.out.println("Row " + it.index() + " has the value " + str); >> } >> >> whereas, today we might write: >> >> int index = 0; >> for (String str : list) { >> System.out.println("Row " + index + " has the value " + str); >> index++; >> } >> >> or >> >> for (int i = 0; i < list.size(); i++) { >> String str = list.get(i); >> System.out.println("Row " + index + " has the value " + str); >> } >> >> Example 2: >> >> StringBuilder buf = new StringBuilder(); >> for (String str : list : it) { >> if (it.isFirst()) { >> buf.append(str); >> } else { >> buf.append(", ").append(str); >> } >> } >> >> StringBuilder buf = new StringBuilder(); >> for (String str : list : it) { >> if (it.isLast()) { >> buf.append(str); >> } else { >> buf.append(str).append(", "); >> } >> } >> >> >> *DETAILS* >> >> SPECIFICATION: >> >> Lexical: >> No new tokens are added. The colon token is reused in the extended >> enhanced for each statement. >> >> Syntax: >> >> EnhancedForStatement: >> for ( VariableModifiersopt Type Identifier : Expression) Statement >> for ( VariableModifiersopt Type Identifier : Expression : Ident) >> Statement >> >> Semantics: >> >> The first enhanced for each statement (the current form) will compile as >> it does today. >> >> The extended enhanced for each statement will operate as follows. >> The iterator control variable is a standard variable declared to be >> final. It will never be null. The type is dependent on whether the >> expression is an array or an Iterable. It will either be >> ArrayIterationControl or IterableIterationControl. The type is not >> specified as it is redundent information, ie. the type is inferred. It >> is scoped for the life of the loop. >> >> public final class IterableIterationControlIterator { >> public IterableIterationControlIterator(Iterable iterable) { >> this.control = new IterableIterationControl(iterable.iterator()); >> } >> public boolean hasNext() { return control.hasNext() } >> public T next() { return control.next() } >> public IterableIterationControl control() { return control } >> } >> public final class IterableIterationControl { >> public IterableIterationControl(Iterator iteratorToWrap) { >> this.it = iteratorToWrap; >> } >> boolean hasNext() { return it.hasNext() } >> T next() { originalIndex++; if (lastWasRemoved) { lastWasRemoved = >> false } else { index++ } return it.next() } >> public T remove() { removed++; lastWasRemoved = true; return >> it.remove() } >> public int index() { return index } >> public int originalIndex() { return originalIndex } >> public boolean isFirst() { return index == 1 } >> public boolean isLast() { return it.hasNext() == false } >> } >> >> public final class ArrayIterationControlIterator { >> public ArrayIterationControlIterator(T[] array) { >> this.control = new ArrayIterationControl(array); >> } >> public boolean hasNext() { return control.hasNext() } >> public T next() { return control.next() } >> public ArrayIterationControl control() { return control } >> } >> public final class ArrayIterationControl { >> public ArrayIterationControl(T[] array) { this.array = array; } >> boolean hasNext() { return index < array.length; } >> T next() { return array[++index]; } >> public int index() { return index - 1; } >> public boolean isFirst() { return index == 1; } >> public boolean isLast() { return index == array.length; } >> } >> >> Exception analysis: >> The method remove() on the iteration control variable can throw an >> UnsuportedOperationException. However, this is no different from any >> other method call. >> >> Definite assignment: >> The new variable iteration control variable is a final variable that is >> definitely assigned from creation. >> >> COMPILATION: >> The extended enhanced for each loop is implemented by wrapping the two >> control classes around the Iterable or the array. >> >> The Iterable design is desugared from: >> >> for (T item : iterable : control) { ... } >> >> to: >> { >> IterableIterationControlIterator $it = new >> IterableIterationControlIterator(iterable); >> IterableIterationControl control = $it.control(); >> while ($it.hasNext()) { >> T item = $it.next(); >> ... >> } >> } >> >> The array design is desugared similarly: >> >> { >> ArrayIterationControlIterator $it = new >> ArrayIterationControlIterator(iterable); >> ArrayIterationControl control = $it.control(); >> while ($it.hasNext()) { >> T item = $it.next(); >> ... >> } >> } >> >> There is the option to optimise this if the iteration control variable >> is not assigned to any other variable or passed to any other method. >> However, that is out of scope for now. >> >> TESTING: >> Testing will be similar to the enhanced for loop. Arrays and Iterables >> of various types and sizes will be used. The null expression will also >> be tested. >> >> LIBRARY SUPPORT: >> Yes, as detailed above. >> >> REFLECTIVE APIS: >> No. >> >> OTHER CHANGES: >> The javac tree API would need to be updated to model the change. >> >> MIGRATION: >> Migration is not required. However, an IDE refactoring could now convert >> more int and Iterator based for loops than it does at present. >> >> >> *COMPATIBILITY* >> >> BREAKING CHANGES: >> No breaking changes are known using this conversion scheme. >> >> EXISTING PROGRAMS: >> This conversion is pure syntax sugar, so there are no known interactions >> with existing programs. >> >> >> *REFERENCES* >> >> EXISTING BUGS: >> I searched the bug database, but nothing came up (which is surprising). >> >> URL FOR PROTOTYPE: >> None >> >> DOCUMENTS: >> [1] Stephen Colebourne's blog: >> http://www.jroller.com/scolebourne/entry/java_7_for_each_loop >> [2] Stephen Colebourne's original writeup: >> http://docs.google.com/Edit?docID=dfn5297z_15ck7x5ghr >> >> >> *DESIGN ISSUES* >> There are numerous alternative ways in which this feature can be added. >> These include: >> - using the keyword: >> for (String str : list) { >> for.remove(); // problem is nested for loops >> } >> - using a label as a psuedo-variable: >> it: for (String str : list) { >> it:remove(); // note colon and not dot >> } >> - using an additional clause before the for each colon: >> for (String str, int index : list) { >> // no access to remove, and conflicts for for each for maps >> } >> >> The chosen solution involves simple Java classes, and a simple desugar. >> The downside of the chosen solution is performance, as it involves >> creating two wrapping objects and routing hasNext() and next() via >> additional layers of method calls. A possible extension would be for the >> compiler to identify if the iteration control variable is not passed to >> another method. If so, then the code could be all be generated inline. >> >> >> >> >> >> > > > From rssh at gradsoft.com.ua Tue Apr 21 22:29:35 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Wed, 22 Apr 2009 08:29:35 +0300 (EEST) Subject: [Fwd: object switch: Re: scripts and results (was Helping to find the usefulness of a proposal)] Message-ID: // look's like we have bug in mail-list software: replies from email- //address other, than given during registrations, sometimes come to // /dev/null. So this is second attempt. > Hi, Ulf You pattern was included in statistics as 'object switch'. P.S. 1) Looking now: I forgot add splitting of 'RelationExpression' in it - this will be added, sorry. 2) May be you overseen mention of 'object switch' because all switch patterns (string, instanceof, object) where not in list of patterns, for which is possible count percentage among simular language constructs. It's because such pattern change 'if' to 'switch' and I have not idea how to find simple one-number metric to show effects of such change. > Hopfully you will find time next days. :-) > > Regards, > > Ulf > > > From Ulf.Zibis at gmx.de Wed Apr 22 02:17:12 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Wed, 22 Apr 2009 11:17:12 +0200 Subject: Submission: switch (...) instanceof feature In-Reply-To: <11471303.1240376112054.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> References: <11471303.1240376112054.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> Message-ID: <49EEE098.3050302@gmx.de> Am 22.04.2009 06:55, Derek Foster schrieb: > Like Gabriel, I have severe reservations about this proposal. I am concerned that it will encourage people to avoid the common OOP "best practice" of using virtual method dispatch in favor of doing an explicit "switch" on each subtype of a type, in cases where doing so is not necessary. > > I concede that there are a few (FEW!) places where doing the equivalent of a switch on instances of a type is necessary (for instance, if the type is in a library you don't have the ability to change). I can see some value in this proposal for that purpose. However, I would very much not like to see use of this construct become commonplace. I already see too many instances of people doing the equivalent of "if (object.type == FOO) {doThis(); } else if (object.type == BAR) { doThat(); }" instead of writing "object.doSomething();" > > I like to provide an example where "object.doSomething();" doesn't work: synchronized Charset lookup(String lowCanonical) { // cache is initialized with available Charset classes names Object o = cache.get(lowCanonical); // Check cache first if (o instanceof String) { // Instantiate new charset Charset cs = newCharset((String)o, lowCanonical); // Cache it if (cs != null) cache.put(lowCanonical, cs); return cs; } return (Charset)o; } This would look much nicer, as it avoids casting: synchronized Charset lookup(String lowCanonical) { // cache is initialized with available Charset classes names switch (Object o = cache.get(lowCanonical) instanceof ?) { case String : // Instantiate new charset Charset cs = newCharset(o, lowCanonical); // Cache it if (cs != null) cache.put(lowCanonical, cs); return cs; case Charset : return o; } } Refer: https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/tags/milestone4/src/sun/nio/cs/FastCharsetProvider.java?rev=684&view=markup http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6790402 http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html - My example could also be smartly coded without switch..case statement, if we would enhance if statement accordingly - I also would like to have possibility to declare variables in if clause, like it's possible in for clause: if ((Object o = cache.get(lowCanonical)) instanceof String) ... ; else if (o instanceof Charset) ... ; -Ulf > Derek > > -----Original Message----- > >> From: Gabriel Belingueres >> Sent: Mar 30, 2009 7:31 AM >> To: Jeroen van Maanen >> Cc: coin-dev at openjdk.java.net >> Subject: Re: Submission: switch (...) instanceof feature >> >> IMO I'm against this. >> >> First, it is against current best practices for the design of >> object-oriented software to make easier to code something with a case >> statement on types/classes. >> >> Second: >> void log(Object object) { >> switch (object) instanceof { >> case String: >> logger.debug("'" + object + "'"); >> case Date: >> logger.debug(object.getTime()); >> case void: >> logger.debug("null"); >> default: >> logger.debug("<" + object.toString() + ">"); >> } >> } >> >> It think it is clearer (when possible) writing it with several >> overloaded methods and double dispatching. >> >> .... >> From howard.lovatt at gmail.com Wed Apr 22 02:54:28 2009 From: howard.lovatt at gmail.com (howard.lovatt at gmail.com) Date: Wed, 22 Apr 2009 09:54:28 +0000 Subject: Submission: switch (...) instanceof feature Message-ID: <001636458a86d99996046821bf78@google.com> Another example would be: class MyClass { private int x; public boolean equals( final Object other ) { if ( other == null ) { return false; } switch ( other ) instanceof { case MyClass: return x == other.x; } return false; } } You can also use the construct like case statements in functional languages, eg how Scala uses its case classes. If this, switch on instanceof, is done for switch it should probably be done for if as well, ie: public boolean equals( final Object other ) { if ( other == null ) { return false; } if ( other instanceof MyClass ) { return x == other.x; } return false; } and probably, but might be too hard, on equality tests of class as well as instanceof test, eg: public boolean equals( final Object other ) { if ( other == null ) { return false; } if ( other.getClass() == MyClass.class ) { return x == other.x; } // equality, rather than instanceof return false; } and: public boolean equals( final Object other ) { if ( other == null ) { return false; } switch ( other.getClass() ) { // equality, rather than instanceof case MyClass: return x == other.x; } return false; } These features, as described above, are in the language Nice where it was claimed they eliminated the need for casts completely. Eliminating casts would be a good result! From brucechapman at paradise.net.nz Wed Apr 22 03:04:06 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Wed, 22 Apr 2009 22:04:06 +1200 Subject: Syntax patterns: more statistics. In-Reply-To: <0d48edf00d3533cd9adab8ce7edc7fa6.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904201524q3d1660e8l3d02ef7b07fe29fe@mail.gmail.com> <0d48edf00d3533cd9adab8ce7edc7fa6.squirrel@wmail.gradsoft.ua> Message-ID: <49EEEB96.2050801@paradise.net.nz> Ruslan, I downloaded your tool and read through the documentation but it was not obvious to me how to look for my pattern, can I add one more request since you seem to be planning another "run" for coin please? For the "PROPOSAL: Unsigned Integer Widening Operator" http://docs.google.com/Doc?id=dcvp3mkv_2k39wt5gf&hl could you please look for these patterns (bitwise integer and expressions) $x & 0xff and 0xFF & $x where $x is an expression of type byte. (I would expect around 90% or more of the matches to be where $x is a byte array access expression, and most of the remainder to be byte variables, with most also being with the int literal on right hand side. I would not expecting you to distinguish 0xff from 255, but the pattern definately ONLY matches when anding with this value. thanks Bruce From rssh at gradsoft.com.ua Wed Apr 22 04:16:43 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Wed, 22 Apr 2009 14:16:43 +0300 (EEST) Subject: Syntax patterns: more statistics. In-Reply-To: <49EEEB96.2050801@paradise.net.nz> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904201524q3d1660e8l3d02ef7b07fe29fe@mail.gmail.com> <0d48edf00d3533cd9adab8ce7edc7fa6.squirrel@wmail.gradsoft.ua> <49EEEB96.2050801@paradise.net.nz> Message-ID: <64614c327c243a5dafaf74f4377f63e9.squirrel@wmail.gradsoft.ua> > Ruslan, > > I downloaded your tool and read through the documentation but it was not > obvious to me how to look for my pattern, can I add one more request > since you seem to be planning another "run" for coin please? > Hi, Bruce. Will be included in result of next run. Sorry for providing such 'row' matherial: I will plan to write description of AST anf Model representation, but this is quite slow process. For now, too see how language construct is represented in AST or Model the best way is: - write some test java example (in subdirectory testdata) - add test to CoinTest (see http://redmine.gradsoft.ua/repositories/entry/javachecker/trunk/JavaChecker/jtests/ua/gradsoft/javachecker/CoinTest.java), call main.setDump(true) and look at test output. From Ulf.Zibis at gmx.de Wed Apr 22 04:44:41 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Wed, 22 Apr 2009 13:44:41 +0200 Subject: [Fwd: object switch: Re: scripts and results (was Helping to find the usefulness of a proposal)] In-Reply-To: References: Message-ID: <49EF0329.3010604@gmx.de> Ruslan, indeed I've overseen your post, as you had changed the subject line. :-( -Ulf Am 22.04.2009 07:29, Ruslan Shevchenko schrieb: > > Hi, Ulf > > You pattern was included in statistics as 'object switch'. > > P.S. > 1) Looking now: I forgot add splitting of 'RelationExpression' in it - > this will be added, sorry. > > 2) May be you overseen mention of 'object switch' because all switch > patterns (string, instanceof, object) where not in list of patterns, for > which is possible count percentage among simular language constructs. > It's because such pattern change 'if' to 'switch' and I have not idea > how to find simple one-number metric to show effects of such change. > > From Ulf.Zibis at gmx.de Wed Apr 22 05:19:07 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Wed, 22 Apr 2009 14:19:07 +0200 Subject: Syntax patterns: more statistics. In-Reply-To: <49EEEB96.2050801@paradise.net.nz> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904201524q3d1660e8l3d02ef7b07fe29fe@mail.gmail.com> <0d48edf00d3533cd9adab8ce7edc7fa6.squirrel@wmail.gradsoft.ua> <49EEEB96.2050801@paradise.net.nz> Message-ID: <49EF0B3B.2020805@gmx.de> These cases are just resolved by HotSpot compiler. See: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6797305 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6814842 http://mail.openjdk.java.net/pipermail/hotspot-dev/2009-January/001100.html http://mail.openjdk.java.net/pipermail/hotspot-dev/2009-January/001025.html http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2009-February/000725.html http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2009-March/000769.html -Ulf Am 22.04.2009 12:04, Bruce Chapman schrieb: > Ruslan, > > I downloaded your tool and read through the documentation but it was not > obvious to me how to look for my pattern, can I add one more request > since you seem to be planning another "run" for coin please? > > For the "PROPOSAL: Unsigned Integer Widening Operator" > http://docs.google.com/Doc?id=dcvp3mkv_2k39wt5gf&hl > > could you please look for these patterns (bitwise integer and expressions) > > $x & 0xff > > and > > 0xFF & $x > > > where $x is an expression of type byte. (I would expect around 90% or > more of the matches to be where $x is a byte array access expression, > and most of the remainder to be byte variables, with most also being > with the int literal on right hand side. I would not expecting you to > distinguish 0xff from 255, but the pattern definately ONLY matches when > anding with this value. > > thanks > > Bruce > > > From Ulf.Zibis at gmx.de Wed Apr 22 05:40:06 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Wed, 22 Apr 2009 14:40:06 +0200 Subject: Syntax patterns: more statistics. In-Reply-To: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> Message-ID: <49EF1026.4000105@gmx.de> Am 20.04.2009 16:58, Ruslan Shevchenko schrieb: > openjdk7 (standard java library) > all catchs : 8404 > all ifs : 28494 > all integer literals : 124356 > big integer literals(undescores) : 4066 > byte literal : 1454 > catch in finally : 103 > elvis : 877 > instanceof switch : 318 > loop with remove : 62 > multi catch : 411 > object switch : 1363 > rethrow clause : 3264 > string in switch : 445 > Files:9252 > > Hope, this data will be useful in some cases. > Regards ! > Yes, it definitely is. Great to see the results for "object switch". 3 times more matches than "string in switch". This is why I'm against widening switch statement to equals-semantics, see: http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html I guess, widening to "expressioned object switch" would increase the statistics even more. Ruslan, thanks for including my proposal. BTW: Have you also parsed JDK's private sun.* classes? I guess, there are plenty of byte literals. -Ulf From belingueres at gmail.com Wed Apr 22 06:39:09 2009 From: belingueres at gmail.com (Gabriel Belingueres) Date: Wed, 22 Apr 2009 10:39:09 -0300 Subject: Submission: switch (...) instanceof feature In-Reply-To: <49EEE098.3050302@gmx.de> References: <11471303.1240376112054.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> <49EEE098.3050302@gmx.de> Message-ID: You may try to get rid of the instanceof by using "another level of indirection". For example in this case, with a Strategy as the cache value: interface ValueStrategy { CharSet lookup(); } class CharSetContentStrategy implements ValueStrategy { CharSet value; public Charset lookup() { .... } } class StringContentStrategy implements ValueStrategy { String value; public Charset lookup() { .... } } declare: final Map cache; then the lookup method would be: synchronized Charset lookup(String lowCanonical) { ValueStrategy v = cache.get(lowCanonical); return v.lookup(); } Please note that in some point the above code may require that you make an instanceof to know which strategy to create, but this code can be isolated in a unique method, instead of in many methods as you have now. (For example, creating a factory class of strategies.) (Of course, another different question is if this will perform faster than using instanceof everywhere.) 2009/4/22, Ulf Zibis : > Am 22.04.2009 06:55, Derek Foster schrieb: > > Like Gabriel, I have severe reservations about this proposal. I am > concerned that it will encourage people to avoid the common OOP "best > practice" of using virtual method dispatch in favor of doing an explicit > "switch" on each subtype of a type, in cases where doing so is not > necessary. > > > > I concede that there are a few (FEW!) places where doing the equivalent of > a switch on instances of a type is necessary (for instance, if the type is > in a library you don't have the ability to change). I can see some value in > this proposal for that purpose. However, I would very much not like to see > use of this construct become commonplace. I already see too many instances > of people doing the equivalent of "if (object.type == FOO) {doThis(); } else > if (object.type == BAR) { doThat(); }" instead of writing > "object.doSomething();" > > > > > > > > I like to provide an example where > > "object.doSomething();" > > doesn't work: > > synchronized Charset lookup(String lowCanonical) { > // cache is initialized with available Charset classes names > Object o = cache.get(lowCanonical); > // Check cache first > if (o instanceof String) { > // Instantiate new charset > Charset cs = newCharset((String)o, lowCanonical); > // Cache it > if (cs != null) > cache.put(lowCanonical, cs); > return cs; > } > return (Charset)o; > } > > > This would look much nicer, as it avoids casting: > > synchronized Charset lookup(String lowCanonical) { > // cache is initialized with available Charset classes names > switch (Object o = cache.get(lowCanonical) instanceof ?) { > case String : > // Instantiate new charset > Charset cs = newCharset(o, lowCanonical); > // Cache it > if (cs != null) > cache.put(lowCanonical, cs); > return cs; > case Charset : > return o; > } > } > > > Refer: > https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/tags/milestone4/src/sun/nio/cs/FastCharsetProvider.java?rev=684&view=markup > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6790402 > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html > http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html > > - My example could also be smartly coded without switch..case statement, if > we would enhance if statement accordingly > - I also would like to have possibility to declare variables in if clause, > like it's possible in for clause: > > if ((Object o = cache.get(lowCanonical)) instanceof String) > ... ; > else if (o instanceof Charset) > ... ; > > -Ulf > > > > Derek > > > > -----Original Message----- > > > > > > > From: Gabriel Belingueres > > > Sent: Mar 30, 2009 7:31 AM > > > To: Jeroen van Maanen > > > Cc: coin-dev at openjdk.java.net > > > Subject: Re: Submission: switch (...) instanceof feature > > > > > > IMO I'm against this. > > > > > > First, it is against current best practices for the design of > > > object-oriented software to make easier to code something with a case > > > statement on types/classes. > > > > > > Second: > > > void log(Object object) { > > > switch (object) instanceof { > > > case String: > > > logger.debug("'" + object + "'"); > > > case Date: > > > logger.debug(object.getTime()); > > > case void: > > > logger.debug("null"); > > > default: > > > logger.debug("<" + object.toString() + ">"); > > > } > > > } > > > > > > It think it is clearer (when possible) writing it with several > > > overloaded methods and double dispatching. > > > > > > .... > > > > > > > > > > From rssh at gradsoft.com.ua Wed Apr 22 07:03:27 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Wed, 22 Apr 2009 17:03:27 +0300 (EEST) Subject: Syntax patterns: more statistics. In-Reply-To: <49EF1026.4000105@gmx.de> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <49EF1026.4000105@gmx.de> Message-ID: <2de340aaf6f07fd7c6ddfda939f1b487.squirrel@wmail.gradsoft.ua> > > BTW: Have you also parsed JDK's private sun.* classes? I guess, there > are plenty of byte literals. > Yes. Most of byte literals are in encoding-handling classes, like src/share/classes/sun/io/ByteToCharISO2022JP.java Note, that counter shows not number of byte literals, but number of byte literals on distinct source lines. (i. e. all byte literals in one line counted once). > -Ulf > > > From Ulf.Zibis at gmx.de Wed Apr 22 07:07:09 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Wed, 22 Apr 2009 16:07:09 +0200 Subject: Submission: switch (...) instanceof feature In-Reply-To: References: <11471303.1240376112054.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> <49EEE098.3050302@gmx.de> Message-ID: <49EF248D.3010904@gmx.de> Interesting recipe! Thanks. See my comment below... Am 22.04.2009 15:39, Gabriel Belingueres schrieb: > You may try to get rid of the instanceof by using "another level of > indirection". For example in this case, with a Strategy as the cache > value: > > interface ValueStrategy { > CharSet lookup(); > } > > class CharSetContentStrategy implements ValueStrategy { > CharSet value; > public Charset lookup() { > .... > } > } > > class StringContentStrategy implements ValueStrategy { > String value; > public Charset lookup() { > .... > } > } > > declare: > final Map cache; > > then the lookup method would be: > > synchronized Charset lookup(String lowCanonical) { > ValueStrategy v = cache.get(lowCanonical); > return v.lookup(); > } > > Please note that in some point the above code may require that you > make an instanceof to know which strategy to create, but this code can > be isolated in a unique method, instead of in many methods as you have > now. (For example, creating a factory class of strategies.) > > (Of course, another different question is if this will perform faster > than using instanceof everywhere.) > > .. another different questions: - if strategies like this will be reasonable regarding footprint of whole application. - readability of code for externals - isolating the instanceof code to *additional* unique method will not really solve the issue. In my case, the lookup method *is* the unique method. -Ulf From belingueres at gmail.com Wed Apr 22 09:06:44 2009 From: belingueres at gmail.com (Gabriel Belingueres) Date: Wed, 22 Apr 2009 13:06:44 -0300 Subject: Submission: switch (...) instanceof feature In-Reply-To: <49EF248D.3010904@gmx.de> References: <11471303.1240376112054.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> <49EEE098.3050302@gmx.de> <49EF248D.3010904@gmx.de> Message-ID: > .. another different questions: > - if strategies like this will be reasonable regarding footprint of whole > application. Do you mean memory footprint? You may implement those Strategies as Singletons if you know they do not store any state, or even as a Flyweights if the different instances are limited. I would keep it as simple as possible. > - readability of code for externals IMO, readability is not important very important if the application life cycle will be short. I would apply the KISS principle again. > - isolating the instanceof code to *additional* unique method will not > really solve the issue. In my case, the lookup method *is* the unique > method. If the lookup method is the only place you do the instanceof test, then it seems reasonable to keep it that way, instead of creating all that strategy pattern code. However, I can not see how changing the instanceof by a switch statement would improve the code, UNLESS the switch statement adds some value, for example that it would perform far better than an if-elseif-else chain AND do some checks, like throwing a compiler error when I write something like this: class A {} class B extends A {} ... switch(o) instanceof { case A: // do something with this A instance break; case B: // never enter this branch if it's a B because it is always catched by the // previous case break; ... } From Ulf.Zibis at gmx.de Wed Apr 22 09:27:10 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Wed, 22 Apr 2009 18:27:10 +0200 Subject: Submission: switch (...) instanceof feature In-Reply-To: References: <11471303.1240376112054.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> <49EEE098.3050302@gmx.de> <49EF248D.3010904@gmx.de> Message-ID: <49EF455E.9060507@gmx.de> Am 22.04.2009 18:06, Gabriel Belingueres schrieb: > > Do you mean memory footprint? You may implement those Strategies as > Singletons if you know they do not store any state, or even as a > Flyweights if the different instances are limited. I would keep it as > simple as possible. > 1st I mean jar-footprint, but 2nd I also mean memory footprint and not to forget class loading, object initialization and indirection time. > > IMO, readability is not important very important if the application > life cycle will be short. I would apply the KISS principle again. > Do you think, sun.nio.cs.FastCharsetProvider is kind of short life cycle ? ;-) > > If the lookup method is the only place you do the instanceof test, > then it seems reasonable to keep it that way, instead of creating all > that strategy pattern code. > However, I can not see how changing the instanceof by a switch > statement would improve the code, Think about READABILITY, READABILITY and READABILITY. if..else is good for 2-way fork, but IMHO switch..case is better for n-way fork. See: http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html In case of instanceof additionally casting could be omitted. > UNLESS the switch statement adds > some value, for example that it would perform far better than an > if-elseif-else chain AND do some checks, like throwing a compiler > error when I write something like this: > +1 > class A {} > class B extends A {} > > ... > switch(o) instanceof { > case A: > // do something with this A instance > break; > case B: > // never enter this branch if it's a B because it is always catched by the > // previous case > break; > ... > } > > > From tball at google.com Wed Apr 22 09:36:45 2009 From: tball at google.com (Tom Ball) Date: Wed, 22 Apr 2009 09:36:45 -0700 Subject: Submission: switch (...) instanceof feature In-Reply-To: <11471303.1240376112054.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> References: <11471303.1240376112054.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> Message-ID: In general I agree with your concern, but remember that those of us on this alias have the ability to modify most of the code we use. That's not true in the Java community at large, where using existing code, such as frameworks or libraries, is much more prevalent. It's often not practical to "write object.doSomething()" when working with external code, and that's where this proposal helps. Tom On Tue, Apr 21, 2009 at 9:55 PM, Derek Foster wrote: > Like Gabriel, I have severe reservations about this proposal. I am > concerned that it will encourage people to avoid the common OOP "best > practice" of using virtual method dispatch in favor of doing an explicit > "switch" on each subtype of a type, in cases where doing so is not > necessary. > > I concede that there are a few (FEW!) places where doing the equivalent of > a switch on instances of a type is necessary (for instance, if the type is > in a library you don't have the ability to change). I can see some value in > this proposal for that purpose. However, I would very much not like to see > use of this construct become commonplace. I already see too many instances > of people doing the equivalent of "if (object.type == FOO) {doThis(); } else > if (object.type == BAR) { doThat(); }" instead of writing > "object.doSomething();" > > Derek > > -----Original Message----- > >From: Gabriel Belingueres > >Sent: Mar 30, 2009 7:31 AM > >To: Jeroen van Maanen > >Cc: coin-dev at openjdk.java.net > >Subject: Re: Submission: switch (...) instanceof feature > > > >IMO I'm against this. > > > >First, it is against current best practices for the design of > >object-oriented software to make easier to code something with a case > >statement on types/classes. > > > >Second: > > void log(Object object) { > > switch (object) instanceof { > > case String: > > logger.debug("'" + object + "'"); > > case Date: > > logger.debug(object.getTime()); > > case void: > > logger.debug("null"); > > default: > > logger.debug("<" + object.toString() + ">"); > > } > > } > > > >It think it is clearer (when possible) writing it with several > >overloaded methods and double dispatching. > > > >Third: > > } catch (Exception exception) { > > switch (exception.getCause()) instanceof { > > case ParseException: > > log.warn("Could not get status for '" + id + ": " + > >exception.getCause()); > > default: > > log.warn("Could not get status for '" + id + ", exception); > > } > >} > > > >in the case you intentionally left out the break statement, then the > >switch statement is not any clearer than doing an if. > >in the case that you wanted the break statement on the ParseException > >case, it is even clearer to use two catch blocks (one for > >ParseException and other for Throwable. > > > > > >2009/3/29 Jeroen van Maanen : > >> I'd like to coin a switch (...) instanceof statement as a new feature of > the > >> Java language. Please accept the attached proposal for review. > >> > >> Regards, Jeroen > >> > >> PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 > >> > >> AUTHOR(S): Jeroen van Maanen > >> > >> OVERVIEW > >> > >> FEATURE SUMMARY: The instanceof switch statement allows for clear and > >> concise > >> handling of alternatives that depend on the type of a given object. > >> > >> MAJOR ADVANTAGE: The instanceof switch statement removes the need for > >> different > >> names for the same object with different types and the extra > declarations > >> and > >> casts to define those names. > >> > >> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? > >> > >> MAJOR DISADVANTAGE: Coders, reviewers, and IDE's need to be able to read > the > >> new statement and interpret and treat it correclty. > >> > >> ALTERNATIVES: There are no alternatives. > >> > >> EXAMPLES > >> > >> SIMPLE EXAMPLE: > >> > >> void log(Object object) { > >> switch (object) instanceof { > >> case String: > >> logger.debug("'" + object + "'"); > >> case Date: > >> logger.debug(object.getTime()); > >> case void: > >> logger.debug("null"); > >> default: > >> logger.debug("<" + object.toString() + ">"); > >> } > >> } > >> > >> ADVANCED EXAMPLE: > >> > >> public StatusEnum getStatus(String id) { > >> StatusEnum result; > >> try { > >> result = internalGetStatus(id); > >> } catch (Exception exception) { > >> switch (exception.getCause()) instanceof { > >> case ParseException: > >> log.warn("Could not get status for '" + id + ": " + > >> exception.getCause()); > >> default: > >> log.warn("Could not get status for '" + id + ", exception); > >> } > >> } > >> } > >> > >> public class PrettyPrinter { > >> private Writer writer; > >> > >> public PrettyPrinter(Writer writer) { > >> this.writer = writer; > >> } > >> > >> public write(Object object) { > >> switch (object) instanceof { > >> case String: > >> writer.write(stringDenotation(object)); > >> case Collection: > >> writer.write(object.getClass().getSimpleName() + ": ["); > >> for (Object element : object) { > >> write(element); > >> writer.write(","); > >> } > >> writer.write("]"); > >> case Map: > >> write(object.entrySet()); > >> case Map.Entry: > >> write(object.getKey()); > >> writer.write(":"); > >> write(object.getValue()); > >> case void: > >> writer.write("null"); > >> default: > >> // TODO: deal with arrays of unknown base type > >> writer.write("<" + object.toString() + ">"); > >> } > >> } > >> > >> private stringDenotation(String str) { > >> ... > >> } > >> > >> } > >> > >> DETAILS > >> > >> SPECIFICATION: The switch instanceof feature adds an alternative to the > >> switch > >> statement to the grammar. > >> > >> SwitchStatement: > >> switch ( Expression ) SwitchBlock > >> switch ( Identifier ) instanceof TypeSwitchBlock > >> > >> TypeSwitchBlock: > >> { TypeSwitchBlockStatementGroups? TypeSwitchLabels? } > >> > >> TypeSwitchBlockStatementGroups: > >> TypeSwitchBlockStatementGroup > >> TypeSwitchBlockStatementGroups TypeSwitchBlockStatementGroup > >> > >> TypeSwitchBlockStatementGroup: > >> TypeSwitchLabel BlockStatements > >> > >> TypeSwitchLabel: > >> case Type : > >> case void : > >> default : > >> > >> COMPILATION: The statement > >> > >> switch (<>) instanceof { > >> case <>: > >> <> > >> case <>: > >> <> > >> ... > >> case void: > >> <> > >> ... > >> default: > >> <> > >> } > >> > >> Would be compiled by desugaring it to > >> > >> if (<> instanceof <>) { > >> <> <> = (<>) <>; > >> <> > >> } > >> else if (<> instanceof <>) { > >> <> <> = (<>) <>; > >> <> > >> } > >> ... > >> else if (<> == null) { > >> <> > >> } > >> ... > >> else { > >> <> > >> } > >> > >> TESTING: The feature can be tested by compiling and running the examples > and > >> comparing the results with the had coded expected desugared versions. > >> > >> LIBRARY SUPPORT: The feature needs no additional library support. > >> > >> REFLECTIVE APIS: The feature does not affect reflective api's. > >> > >> OTHER CHANGES: The feature does not need other changes. > >> > >> MIGRATION: This feature does not invalidate existing code. An existing > code > >> base could be scanned for type casts. Occurrences of type casts should > be > >> manually evaluated and, if desired, recoded using the new feature. > >> > >> COMPATIBILITY > >> > >> BREAKING CHANGES: This feature does not invalidate existing code. > >> > >> EXISTING PROGRAMS: This feature has no impact on existing code. > >> > >> REFERENCES > >> > >> EXISTING BUGS: There are no existing Sun bug ids related to this > proposal. > >> > >> URL FOR PROTOTYPE: Not available. > >> > >> > >> > >> > > > > > From reinier at zwitserloot.com Wed Apr 22 16:57:00 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 23 Apr 2009 01:57:00 +0200 Subject: Proposal: Indexing access syntax for Lists and Maps In-Reply-To: <22913460.1240375626476.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> References: <22913460.1240375626476.JavaMail.root@elwamui-karabash.atl.sa.earthlink.net> Message-ID: Letting 'foo[x]', where foo is a set, have the asribed specification is exactly the kind of circus trick I expect some well-intended bad library to use, in languages that support operator overloading. Hard-coding it into the JLS: Please, don't do that. Here's the golden rule for doing ANYTHING at all with operators: If it's not crystal clear for everybody who is going to read your code, then, don't do it. Also, someList[10] = true; someMap[10] = true; someSet[10] = true; would all have entirely different meanings. Overloading [] for lists and maps is an acceptable evil because people in general are quite used to it (e.g. due to javascript, python, and many other languages). This list is certainly reinforcing the idea that operator overloading accessible to library builders is a bad idea. --Reinier Zwitserloot Like it? Tip it! http://tipit.to On Apr 22, 2009, at 06:47, Derek Foster wrote: > I like your idea of including Set as well. I think it makes > intuitive sense with regards to a set as a quality of its members. > (e.g. the set "blue" has members which are blue, and thus "blue[x]" > represents "is x blue?" > > However, if we were to do so, I think that "bool foo = (set[y] = > bar)" should always result in 'foo' being equal to 'bar', not in it > getting the assigned the return value of set.add() or set.remove() > as your desugaring implies. > > Derek > > > > -----Original Message----- >> From: Tim Keith >> Sent: Mar 29, 2009 10:40 PM >> To: coin-dev at openjdk.java.net >> Subject: Re: Proposal: Indexing access syntax for Lists and Maps >> >> Is it possible to include Set as well? >> >> E.g. "bool = set[x]" meaning "bool = set.contains(x)" >> and "set[x] = bool" meaning "bool ? set.add(x) : set.remove(x)" >> >> -- Tim >> >> On Sun, Mar 29, 2009 at 5:12 PM, Shams Mahmood > >wrote: >> >>> Indexing access syntax for Lists and Maps >>> >>> VERSION >>> This is version 1.0. >>> >>> AUTHOR(S): >>> Shams Mahmood Imam >>> >>> OVERVIEW >>> >>> FEATURE SUMMARY: >>> Collection classes are among the most frequently used in the Java >>> SDK. >>> Currently Lists and Maps do not provide any additional language >>> feature to access individual elements unlike Arrays. This proposal >>> aims to provide these Collection citizens of java additional >>> language support to access elements like Arrays have currently. >>> >>> MAJOR ADVANTAGE: >>> Will provide a consistent syntax for accessing elements of Arrays, >>> Lists and Maps. In addition, the language grammar will not change >>> much since the subscript operator is already supported for Arrays. >>> >>> MAJOR BENEFIT: >>> Apart from the consistency mentioned above, implementation fo this >>> feature will result in fewer characters needed to be typed to >>> achieve >>> simple access to elements in Maps/Lists. >>> >>> MAJOR DISADVANTAGE: >>> Like the for-each loop construct, it will expose the client to >>> NullPointerException(NPE)s when used with a null List/Map. However, >>> this shouldn't be such a major issue as NPEs are also generated >>> by arrays when the operator is used in a null array. >>> >>> ALTERNATIVES: >>> The comparatively more verbose get/set methods for Lists and get/put >>> methods for Maps. >>> >>> EXAMPLES >>> >>> SIMPLE EXAMPLE: >>> >>> public class Main { >>> public static void main(String[] arguments) { >>> List l1 = Arrays.asList(new String[] {"a", "b", "c"}); >>> String firstElement = l1[0]; >>> Map m1 = new HashMap(4); >>> m1[Integer.valueOf(1)] = "One"; >>> } >>> } >>> >>> ADVANCED EXAMPLE: >>> >>> public class Main { >>> public static void main(String[] arguments) { >>> List l1 = Arrays.asList(new String[] {"a", "b", "c"}); >>> Map m1 = new HashMap(4); >>> Map m2 = new HashMap(4); >>> >>> m2[l1[2]] = m2[m1[1]] = 4; // same as m2.put(l1.get(2), >>> m2.put(m1.get(1), 4)); >>> } >>> } >>> >>> DETAILS >>> >>> SPECIFICATION: >>> Java Language Specification changes: >>> >>> 15.29 (NEW CHAPTER): Collection Access Expressions >>> A collection access expression contains two subexpressions, the >>> List/Map >>> reference expression (before the left bracket) and the index >>> expression >>> (within the brackets). Note that the List/Map reference expression >>> may be a >>> name or any expression that evaluates to a List/Map. The index >>> experssion is >>> expected to evaluate to an int for Lists and a valid key type for >>> Maps. >>> >>> CollectionAccess: >>> Expression [ Expression ] >>> >>> 15.8 Primary Expressions >>> original: >>> --------- >>> PrimaryNoNewArray: >>> Literal >>> Type . class >>> void . class >>> this >>> ClassName.this >>> ( Expression ) >>> ClassInstanceCreationExpression >>> FieldAccess >>> MethodInvocation >>> ArrayAccess >>> >>> replaced with: >>> -------------- >>> PrimaryNoNewArray: >>> Literal >>> Type . class >>> void . class >>> this >>> ClassName.this >>> ( Expression ) >>> ClassInstanceCreationExpression >>> FieldAccess >>> MethodInvocation >>> ArrayAccess >>> CollectionAccess >>> >>> 15.26 Assignment Operators >>> original: >>> --------- >>> LeftHandSide: >>> ExpressionName >>> FieldAccess >>> ArrayAccess >>> >>> replaced with: >>> -------------- >>> LeftHandSide: >>> ExpressionName >>> FieldAccess >>> ArrayAccess >>> CollectionAccess >>> >>> >>> COMPILATION: >>> >>> After successful creation of the AST handling the additional >>> grammar for >>> Collection Access expressions, the syntactic sugar will be >>> replaced by >>> JDK1.4 compatible code during the Code Generation phase. This is >>> consistent >>> with how JDK5.0 constructs like the for-each loop is handled by the >>> compiler. >>> >>> e.g. >>> public class TestConcise { >>> public static void main(String[] args) { >>> java.util.Map m1 = new java.util.HashMap>> String>(); >>> m1[2] = "two"; >>> >>> java.util.LinkedList l1 = java.util.Arrays.asList( new >>> String[] >>> {"a", "b", "c" }); >>> m1[3] = l1[2]; >>> l1[0] = m1[0]; >>> l1[1] = "one"; >>> } >>> } >>> >>> is converted to >>> public class TestConcise { >>> public TestConcise() { >>> super(); >>> } >>> >>> public static void main(String[] args) { >>> java.util.Map m1 = new java.util.HashMap>> String>(); >>> m1.put(Integer.valueOf(2), "two"); >>> >>> java.util.LinkedList l1 = java.util.Arrays.asList( new >>> String[] >>> {"a", "b", "c" }); >>> m1.put(Integer.valueOf(3), l1.get(2)); >>> l1.set(0, m1.get(Integer.valueOf(0))); >>> l1.set(1, "one"); >>> } >>> } >>> >>> >>> TESTING: >>> >>> LIBRARY SUPPORT: >>> No additional library support is needed. >>> >>> REFLECTIVE APIS: >>> This proposal does not require any reflective API changes. >>> >>> OTHER CHANGES: >>> No changes required. >>> >>> MIGRATION: >>> No migration is needed. >>> >>> COMPATIBILITY >>> >>> BREAKING CHANGES: >>> No breaking changes. >>> >>> EXISTING PROGRAMS: >>> Existing programs are not affected by this change. >>> >>> REFERENCES >>> My Java7 Wishlist regarding Collections, >>> http://shamsmi.blogspot.com/2008/04/my-java7-wishlist-regarding-collections.html >>> Implementation of My Java7 Wishlist, >>> http://shamsmi.blogspot.com/2008/05/implementation-of-my-java7-wishlist.html >>> >>> EXISTING BUGS: >>> None. >>> >>> URL FOR PROTOTYPE (optional): >>> Projects kijaro's concisecollections branch: >>> https://kijaro.dev.java.net/source/browse/kijaro/branches/concisecollections/ >>> >>> >>> >>> >>> >> > > From reinier at zwitserloot.com Wed Apr 22 16:58:07 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 23 Apr 2009 01:58:07 +0200 Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <49EDE7B4.2090006@sun.com> References: <49C56020.2070207@joda.org> <49EDE7B4.2090006@sun.com> Message-ID: <3BBAA5CF-247E-430F-A271-A10C79642FF7@zwitserloot.com> If the proposal was just about making the iterator available, I'd agree with you, but the proposal adds methods like .first(), which are /very/ useful indeed. It's right up there with ARM, and easily beats string switching, in how applicable that would be. Adding a .join() method to String or List (depending on taste) would solve over half of the use-cases for the extended forloop, though. --Reinier Zwitserloot Like it? Tip it! http://tipit.to On Apr 21, 2009, at 17:35, Joseph D. Darcy wrote: > Catching up on proposal commenting, while I find the design generally > acceptable, I remain unconvinced that the inability to replace all > pre-JDK 5 for loops with some newer, improved for loop is a serious > enough problem to justify further language changes beyond the enhanced > for loop in JDK 5. > > Some data on how often such a new construct would be applicable would > help here. > > -Joe > > Stephen Colebourne wrote: >> Enhanced for each loop iteration control >> >> (re-sent with correct subject line) >> >> This proposal extends the for each loop to allow access to meta data >> including the index and the remove method. >> >> (This proposal doesn't really go into enough detail - with JSR-310 my >> time here is limited. I'd hope that there is just about enough >> though....) >> >> ----------------------------------------------------------------------------------- >> Enhanced for each loop iteration control >> >> AUTHOR(S): >> Stephen Colebourne >> >> *OVERVIEW* >> >> FEATURE SUMMARY: >> Extends the Java 5 for-each loop to allow access to the loop index, >> whether this is the first or last iteration, and to remove the >> current item. >> >> MAJOR ADVANTAGE: >> The for-each loop is almost certainly the most new popular feature >> from >> Java 5. It works because it increases the abstraction level - >> instead of >> having to express the low-level details of how to loop around a >> list or >> array (with an index or iterator), the developer simply states that >> they >> want to loop and the language takes care of the rest. However, all >> the >> benefit is lost as soon as the developer needs to access the index >> or to >> remove an item. >> >> The original Java 5 for each work took a relatively conservative >> stance >> on a number of issues aiming to tackle the 80% case. However, loops >> are >> such a common form in coding that the remaining 20% that was not >> tackled >> represents a significant body of code. >> >> The process of converting the loop back from the for each to be >> index or >> iterator based is painful. This is because the old loop style if >> significantly lower-level, more verbose and less clear. It is also >> painful as most IDEs don't support this kind of 'de-refactoring'. >> >> MAJOR BENEFIT: >> A common coding idiom is expressed at a higher abstraction than at >> present. This aids readability and clarity. >> >> Accessing the index currently requires using an int based loop, or >> placing a separate int counter outside the loop (which then remains >> in >> scope after the loop). The proposed solution doesn't result in manual >> manipulation of the index. >> >> Accessing the iterator remove requires using an iterator based loop. >> With generics this is remarkably verbose. The proposed solution is >> significantly shorter and cleaner. >> >> MAJOR DISADVANTAGE: >> The enhanced for each loop is complicated with additional >> functionality. >> (This is mitigated by being easy and obvious to use) >> >> More code is generated magically by the compiler. (This is >> mitigated by >> a simple desugaring) >> >> ALTERNATIVES: >> Use the existing language constructs, typically the standard for >> loop. >> >> Use BGGA/JCA style closures, with control statements. It should be >> noted >> that these are consistently the most controversial parts of the >> closure >> debate, making the 'let's wait for closures' argument against this >> proposal weaker (as any final closures implementation may not include >> control statements). >> >> >> *EXAMPLES* >> >> SIMPLE EXAMPLE: >> >> StringBuilder buf = new StringBuilder(); >> for (String str : list : it) { >> if (str == null) { >> it.remove(); >> } >> } >> >> whereas, today we write: >> >> StringBuilder buf = new StringBuilder(); >> for (Iterator it = list.iterator(); it.hasNext();) { >> String str = it.next(); >> if (str == null) { >> it.remove(); >> } >> } >> >> ADVANCED EXAMPLE: >> >> Example1: >> >> for (String str : list : it) { >> System.out.println("Row " + it.index() + " has the value " + >> str); >> } >> >> whereas, today we might write: >> >> int index = 0; >> for (String str : list) { >> System.out.println("Row " + index + " has the value " + str); >> index++; >> } >> >> or >> >> for (int i = 0; i < list.size(); i++) { >> String str = list.get(i); >> System.out.println("Row " + index + " has the value " + str); >> } >> >> Example 2: >> >> StringBuilder buf = new StringBuilder(); >> for (String str : list : it) { >> if (it.isFirst()) { >> buf.append(str); >> } else { >> buf.append(", ").append(str); >> } >> } >> >> StringBuilder buf = new StringBuilder(); >> for (String str : list : it) { >> if (it.isLast()) { >> buf.append(str); >> } else { >> buf.append(str).append(", "); >> } >> } >> >> >> *DETAILS* >> >> SPECIFICATION: >> >> Lexical: >> No new tokens are added. The colon token is reused in the extended >> enhanced for each statement. >> >> Syntax: >> >> EnhancedForStatement: >> for ( VariableModifiersopt Type Identifier : Expression) >> Statement >> for ( VariableModifiersopt Type Identifier : Expression : Ident) >> Statement >> >> Semantics: >> >> The first enhanced for each statement (the current form) will >> compile as >> it does today. >> >> The extended enhanced for each statement will operate as follows. >> The iterator control variable is a standard variable declared to be >> final. It will never be null. The type is dependent on whether the >> expression is an array or an Iterable. It will either be >> ArrayIterationControl or IterableIterationControl. The type >> is not >> specified as it is redundent information, ie. the type is inferred. >> It >> is scoped for the life of the loop. >> >> public final class IterableIterationControlIterator { >> public IterableIterationControlIterator(Iterable iterable) { >> this.control = new >> IterableIterationControl(iterable.iterator()); >> } >> public boolean hasNext() { return control.hasNext() } >> public T next() { return control.next() } >> public IterableIterationControl control() { return control } >> } >> public final class IterableIterationControl { >> public IterableIterationControl(Iterator iteratorToWrap) { >> this.it = iteratorToWrap; >> } >> boolean hasNext() { return it.hasNext() } >> T next() { originalIndex++; if (lastWasRemoved) { lastWasRemoved = >> false } else { index++ } return it.next() } >> public T remove() { removed++; lastWasRemoved = true; return >> it.remove() } >> public int index() { return index } >> public int originalIndex() { return originalIndex } >> public boolean isFirst() { return index == 1 } >> public boolean isLast() { return it.hasNext() == false } >> } >> >> public final class ArrayIterationControlIterator { >> public ArrayIterationControlIterator(T[] array) { >> this.control = new ArrayIterationControl(array); >> } >> public boolean hasNext() { return control.hasNext() } >> public T next() { return control.next() } >> public ArrayIterationControl control() { return control } >> } >> public final class ArrayIterationControl { >> public ArrayIterationControl(T[] array) { this.array = array; } >> boolean hasNext() { return index < array.length; } >> T next() { return array[++index]; } >> public int index() { return index - 1; } >> public boolean isFirst() { return index == 1; } >> public boolean isLast() { return index == array.length; } >> } >> >> Exception analysis: >> The method remove() on the iteration control variable can throw an >> UnsuportedOperationException. However, this is no different from any >> other method call. >> >> Definite assignment: >> The new variable iteration control variable is a final variable >> that is >> definitely assigned from creation. >> >> COMPILATION: >> The extended enhanced for each loop is implemented by wrapping the >> two >> control classes around the Iterable or the array. >> >> The Iterable design is desugared from: >> >> for (T item : iterable : control) { ... } >> >> to: >> { >> IterableIterationControlIterator $it = new >> IterableIterationControlIterator(iterable); >> IterableIterationControl control = $it.control(); >> while ($it.hasNext()) { >> T item = $it.next(); >> ... >> } >> } >> >> The array design is desugared similarly: >> >> { >> ArrayIterationControlIterator $it = new >> ArrayIterationControlIterator(iterable); >> ArrayIterationControl control = $it.control(); >> while ($it.hasNext()) { >> T item = $it.next(); >> ... >> } >> } >> >> There is the option to optimise this if the iteration control >> variable >> is not assigned to any other variable or passed to any other method. >> However, that is out of scope for now. >> >> TESTING: >> Testing will be similar to the enhanced for loop. Arrays and >> Iterables >> of various types and sizes will be used. The null expression will >> also >> be tested. >> >> LIBRARY SUPPORT: >> Yes, as detailed above. >> >> REFLECTIVE APIS: >> No. >> >> OTHER CHANGES: >> The javac tree API would need to be updated to model the change. >> >> MIGRATION: >> Migration is not required. However, an IDE refactoring could now >> convert >> more int and Iterator based for loops than it does at present. >> >> >> *COMPATIBILITY* >> >> BREAKING CHANGES: >> No breaking changes are known using this conversion scheme. >> >> EXISTING PROGRAMS: >> This conversion is pure syntax sugar, so there are no known >> interactions >> with existing programs. >> >> >> *REFERENCES* >> >> EXISTING BUGS: >> I searched the bug database, but nothing came up (which is >> surprising). >> >> URL FOR PROTOTYPE: >> None >> >> DOCUMENTS: >> [1] Stephen Colebourne's blog: >> http://www.jroller.com/scolebourne/entry/java_7_for_each_loop >> [2] Stephen Colebourne's original writeup: >> http://docs.google.com/Edit?docID=dfn5297z_15ck7x5ghr >> >> >> *DESIGN ISSUES* >> There are numerous alternative ways in which this feature can be >> added. >> These include: >> - using the keyword: >> for (String str : list) { >> for.remove(); // problem is nested for loops >> } >> - using a label as a psuedo-variable: >> it: for (String str : list) { >> it:remove(); // note colon and not dot >> } >> - using an additional clause before the for each colon: >> for (String str, int index : list) { >> // no access to remove, and conflicts for for each for maps >> } >> >> The chosen solution involves simple Java classes, and a simple >> desugar. >> The downside of the chosen solution is performance, as it involves >> creating two wrapping objects and routing hasNext() and next() via >> additional layers of method calls. A possible extension would be >> for the >> compiler to identify if the iteration control variable is not >> passed to >> another method. If so, then the code could be all be generated >> inline. >> >> >> >> >> >> > > From reinier at zwitserloot.com Wed Apr 22 17:39:51 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 23 Apr 2009 02:39:51 +0200 Subject: PROPOSAL: Named method parameters In-Reply-To: <49EDE7E7.7040907@sun.com> References: <4ce75f920903210915pa2b27b3g38841e342a78de77@mail.gmail.com> <49EDE7E7.7040907@sun.com> Message-ID: <4CEAFE97-F979-4B3D-9688-2DFE570E4D93@zwitserloot.com> rt.jar indeed does not include paramnames. Compiling and jarring all of it gives you 13MB without any debug info, and 15MB when including all local variables (there's no easy way to compile with just argnames (or, better yet, argnames for non-private methods), stil, that's quite a change, so consider the semi-proposal revoked. (Though, it does help support my earlier pre-proposal where source files explicitly declare a method to be accessible via named parameter call). --Reinier Zwitserloot Like it? Tip it! http://tipit.to On Apr 21, 2009, at 17:36, Joseph D. Darcy wrote: > Catching up on responses, as has been further discussed on the list > recently, requests in this general vein have been considered before in > JDK 6. While there are certainly use-cases this facility could > clarify, > I remain unconvinced of the cost/benefit ratio of this proposal. > > A few design notes, a single @PublicParameterNames annotation with a > boolean member could be used instead of a pair of "do it/don't do it" > annotations. > > A full proposal for this facility would need to deal with the cases > where the number of parameters in the class file differs from the > number > of parameters in the source code, a situation already mildly exposed > when calling toGenericString on some Method and Constructor objects. > > Not supporting parameter reordering greatly simplifies the proposal by > leaving method selection largely unaffected, but also seems to limit > the > usefulness of the proposal. If the main benefit is just seeing the > parameter name in the program text; can't the IDE do that? > > I'd isn't clear to me how @PublicParameterNames would interact with > overridden methods in class hierarchies. Presumably the names of the > static type of the call site would need be match, even though the > runtime type could differ. If a subclass overrode a method and > changed > its parameter names (which currently has no affect on compatibility), > the subclass would no longer be substitutable for the parent class, > which would break a fundamental design principle. > > At least there is no binary compatibility impact since the names would > only be checked at compile time and binary compatibility is about > preserving the ability to link. > > -Joe > > Paul Martin wrote: >> I'd like to propose the implementation of optionally named method >> parameters, and suggest that they are particularly useful when >> creating >> immutable objects (which are important in our increasingly concurrent >> world). >> >> Note that this is a topic that seems to have been considered before >> (see the >> note in http://paulhammant.com/blog/announcing_paranamer.html which >> suggests >> that it was even considered for Java 6), but I can't see it in the >> current >> list of Java 7 changes or in the Project Coin mailing list archives >> (though >> others have also discussed it in relation to Java 7, such as Alex >> Miller in >> http://tech.puredanger.com/2007/08/15/dr-java7/ and >> http://tech.puredanger.com/2007/10/11/java7-roundup-32/). >> Therefore I am >> proposing it here - I think that it is an important change (unless >> anyone >> can suggest how I can reasonably create an immutable object with >> four or >> more properties without using a Builder or a list of unnamed >> parameters). >> >> Also note that other relevant references include: >> http://blogs.sun.com/abuckley/entry/named_parameters (which >> discusses why >> parameter reordering might be difficult), >> http://beust.com/weblog/archives/000096.html (which suggests that >> we do not >> need named parameters, but really just shows the use of the Builder >> pattern >> which has limitations). >> >> >> Named method parameters >> >> AUTHOR(S): >> >> Paul Martin >> >> OVERVIEW >> >> FEATURE SUMMARY: >> >> Named parameters allow a method or constructor caller to explicitly >> state >> the parameter name of each parameter value passed to the method or >> constructor. Without named parameters, only the order of the >> parameter >> values is significant (and it may not be clear what each value >> represents). >> >> MAJOR ADVANTAGE: >> >> This is a relatively simple way of introducing named parameters to >> the Java >> platform. >> >> MAJOR BENEFIT: >> >> Named parameters allow method calls with relatively long lists of >> parameters >> (greater than 3) to be understood by developers. This can also >> facilitate >> the direct use of constructors and factory methods to create >> immutable >> objects, where otherwise Builders or mutable JavaBeans would be >> required. >> >> MAJOR DISADVANTAGE: >> >> The syntax for method calls would change to allow both named and >> unnamed >> parameters to be used. >> >> Named parameters might be used too often, which could unnecessarily >> clutter >> source files. >> >> Metadata to store the names of the parameters must be added to >> classfiles >> (for example as annotations). >> >> The use of annotations to describe named parameters would mean that >> no >> metadata would be stored about the parameter names used by the method >> caller, and so no runtime checks to match the parameter names being >> used >> could be made (only compile-time). If the parameter names change >> (but >> otherwise the method signature does not), then the method caller >> would not >> be aware of the changes until it was recompiled. Note that this is >> existing >> behaviour for unnamed parameters, and would only be a problem if >> the meaning >> of the parameters also changes (which should indicate that the >> caller would >> need to change anyway, but this would not be detected automatically >> at >> runtime). >> >> ALTERNATIVES: >> >> Unnamed parameters can make the same method calls as named >> parameters, but >> if there are many parameters they are harder to understand and >> prone to >> ordering-related bugs (particularly for primitive types or Strings). >> >> The Builder pattern can be used to simulate named parameters in >> constructors/factory methods. For example the following class uses a >> Builder to initialise itself (note that only two properties are >> used to >> simplify the example): >> >> public final class MyClass { >> >> private final String name; >> private final int age; >> >> private MyClass(Builder b) { >> this.name = b.name; >> this.age = b.age; >> } >> >> public static class Builder { >> >> private String name; >> private int age; >> >> /** >> * Name to set. >> */ >> public Builder setName(String name) { >> this.name = name; >> return this; >> } >> >> /** >> * Age to set >> */ >> public Builder setAge(int age) { >> this.age = age; >> return this; >> } >> >> public MyClass build() { >> return new MyClass(this); >> } >> } >> } >> >> Objects can then be constructed in the following manner: >> >> MyClass obj = new >> MyClass.Builder().setName("Fred").setAge(53).build(); >> >> However, the use of a builder requires additional code, and all >> parameters >> are effectively optional from the perspective of the compiler (it >> cannot >> easily check that all of the required setter methods have been >> called), so >> bugs may occur where parameter values are not set. Note that >> runtime checks >> can be made to ensure that all property values are set, but they >> involve >> additional work and cannot be used by the compiler (though static >> analysis >> of the code in conjunction with annotations might be able to repeat >> many of >> these checks). >> >> There are also many ways to implement named parameters that are >> different to >> the solution proposed here. These include: >> >> Implement optional named parameters on all methods: This avoids >> the need >> for the @PublicParameterNames annotation, but may mean inconsistent >> usage of >> named parameters - the annotation is also a suggestion for the use >> of named >> parameters by the caller (which IDEs can also make use of). This >> will also >> highlight the difference to classfiles compiled with earlier >> versions of >> Java, where named parameters cannot be used at all (since it will >> then not >> be obvious when named parameters can and cannot be used). >> >> Add parameter names to the classfile as 'fundamental' method >> metadata rather >> than as annotations: This may allow closer integration of the named >> parameters with the rest of the language, but its impact on the >> rest of the >> language (and JVM) is much greater. The same inconsistencies and >> incompatibilities described in the previous alternative would also >> apply. >> In addition, the use of annotations should not preclude the >> subsequent >> modification of classfiles in a later release - the annotations >> could still >> remain (at a potential cost of some duplication). >> >> EXAMPLES >> >> SIMPLE EXAMPLE: >> >> Constructor declaration: >> >> @PublicParameterNames >> public MyClass(String name, int age) { .... >> >> Constructor use: >> >> MyClass obj = new MyClass(name: "Fred", age: 53); >> >> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >> >> The full class definition from the simple example is shown below, >> as a >> contrast to that provided in the Builder example. >> >> public final class MyClass { >> >> private final String name; >> private final int age; >> >> /** >> * @param name Name to set >> * @param age Age to set >> */ >> >> @PublicParameterNames >> public MyClass(String name, int age) { >> this.name = name; >> this.age = age; >> } >> } >> >> DETAILS >> >> SPECIFICATION: >> >> The @PublicParameterNames annotation is used on a constructor or >> method to >> allow named parameters to be used when calling it. It can also be >> applied >> to a class or package to apply to all methods within. Similarly, a >> @NoParameterNames annotation can be used on a constructor, method, >> or class >> to override the use of @PublicParameterNames at a higher level. >> >> The compiler can then automatically generate a >> @PublicParameterName(value="parameter-name") annotation for each >> affected >> method. These can then be used by the compiler (and IDE) to >> validate the >> parameter names used by callers of the method or constructor. >> >> The use of parameter names by callers is always optional (primarily >> for >> backwards compatibility). However, parameter names cannot be used >> for some >> parameters and not others (this would make the code harder to read). >> >> Parameters must always be specified in the same order regardless of >> whether >> parameter names are used - parameter reordering by callers is not >> allowed >> (reordering would make overloading difficult, and is not really >> necessary). >> >> Inheritance: Neither the @PublicParameterNames annotation (and >> @NoParameterNames annotation), or the names of the parameters >> themselves, >> need to be inherited. This is because only static evaluation of a >> caller's >> parameter names will be applied (rather than at runtime), so the >> callers >> parameter names only need to match those of the declared type of the >> target. However, it would still be advisable to reuse the same >> parameter >> names and annotations when overriding a method (IDEs could help >> with this). >> >> COMPILATION: >> >> The compiler must automatically generate a >> @PublicParameterName(value="parameter-name") annotation for each >> method and >> constructor annotated with @PublicParameterNames (or whose the >> parent class >> or package is annotated with @PublicParameterNames and the child >> class or >> method does not override it with @NoParameterNames). >> >> For example: >> >> int myMethod(int param1, String param2) >> >> Would effectively become: >> >> int myMethod(@PublicParameterName("param1") int param1, >> @PublicParameterName("param2") String param2) >> >> Method-calling syntax would need to change, using a colon to >> separate the >> parameter name and value where the are used. For example: >> >> MyClass obj = new MyClass(name: "Fred", age: 53); >> >> When a method caller uses parameter names, the compiler must check >> that >> those parameter names exactly match the value of generated >> @PublicParameterName annotations of the target method or >> constructor. It is >> a compilation error if they do not match or the target method or >> constructor >> does not have named parameters. >> >> IDEs can use the @PublicParameterNames and @NoParameterNames >> annotations (or >> @PublicParameterName directly) to automatically insert the relevant >> parameter names as part of code-completion. Additional refactoring >> support >> would also be required to enable parameter names to be renamed, or >> added and >> removed completely. >> >> Frameworks such as Spring can use the same annotations to allow >> objects to >> be created from their configuration files using named parameters to >> constructors and factory methods. Currently they only allow >> objects to be >> created from configuration files as JavaBeans (with setter methods) >> or with >> ordered (and unnamed) parameters. >> >> TESTING: >> >> The feature can be tested by compiling and running programs that >> exercise >> the feature. >> >> LIBRARY SUPPORT: >> >> No. >> >> REFLECTIVE APIS: >> >> java.lang.reflect.Method and java.lang.reflect.Constructor could be >> enhanced >> with new methods that return parameter names. However, that is not >> required >> to successfully implement the proposal. >> >> OTHER CHANGES: >> >> No. The use of named parameters is always optional. The javadoc >> tool >> already documents parameter names. Other tools/libraries might >> benefit from >> these changes, but their use is not required. >> >> MIGRATION: >> >> The @PublicParameterNames annotation (and @NoParameterNames >> annotation) >> simply needs to be added to the appropriate methods. IDEs could then >> suggest the use of parameter names for the method's callers, and >> apply the >> changes automatically. >> >> COMPATIBILITY >> >> BREAKING CHANGES: >> >> No. >> >> EXISTING PROGRAMS: >> >> The changes required by this feature should be transparent to >> existing >> source and class files if annotations are used internally to >> describe the >> named parameters. I am not sure what the impact would be otherwise. >> >> REFERENCES >> >> EXISTING BUGS: >> >> 4124331 (though it is set to 11-Closed, Will Not Fix, request for >> enhancement, and from 1998) >> >> > > From reinier at zwitserloot.com Wed Apr 22 17:41:31 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 23 Apr 2009 02:41:31 +0200 Subject: SUBMISSION : A second look on "named parameters" / Clarification on the scope In-Reply-To: <15e8b9d20904200852q70bf48bcm2c9beb8685902488@mail.gmail.com> References: <2dc3bd00904200118s35e085fdk6f4ef3cac83cd6e9@mail.gmail.com> <15e8b9d20904200852q70bf48bcm2c9beb8685902488@mail.gmail.com> Message-ID: Neal: No, this is not an API change. It's a change to the JVM spec (specifically, the section about class files). If it doesn't fit project coin, then what would it fit? Most certainly not the coin-but- for-API-updates. Where else would 'class files MUST include the names of method parameters' fit? Adding the ability to get this information via reflection would be an API change, but many coin proposals have a matching change to the reflection API. --Reinier Zwitserloot Like it? Tip it! http://tipit.to On Apr 20, 2009, at 17:52, Neal Gafter wrote: > Reiner- > > This is a library proposal, not a language proposal, so it doesn't > need to be done inside project Coin. > > -Neal > > On Mon, Apr 20, 2009 at 3:16 AM, Reinier Zwitserloot > wrote: > Ah, now I understand. > > I've got a much simpler proposal to address this issue. > > NB: Joe, I know coin's long gone, but perhaps consider this one anyway > - it seems to me that some sort of named parameters proposal is likely > to be accepted in the future, and adding names now should ease > transition. As part of the effort I've listed all possibly > complication I can come up with, at the end. > > Proposal: > > > Starting from the new class file format introduced in java7 (due to > module support, the class format is definitely getting a version > bump), all compilers MUST put the names of the parameters in the class > file (javac -g style), and obfuscators/compressors/whatever MUST NOT > remove this; a class file with version v50 (or whatever number its > going to end up being) won't even pass the verifier without the names > in place. > > Add an API call on the java.lang.reflect.Method object to obtain the > names of the parameters (returns a String[], or 'null' if they aren't > there. Calling this on a param-less method returns an empty array, not > null). Having the names is an all-or-nothing situation: Either the > names are all there and this call works, or some/all are missing, and > then this call does not work. I'm not sure if you can even have just a > few names defined in the .class file format, but even if you can, that > situation should be so extremely rare, its not worth writing up a > complicated rule for). It is guaranteed that if the array exists (is > not null), then each array element is not null. > > Voila. No need to turn in a proposal that's more complicated than most > just to solve this simple problem. > > Complications: > > A) It would no longer be possible to rewrite a v49 and below class > without debug info into a v50 and up class file without having the > source file, but I don't actually know of any tools that attempt to do > this. > > B) Code that generates class files on the fly (like proxy generators > and the like) will need to consider the names of method parameters if/ > when they update the class file format they generate to v50+. A proxy > generator has issues when it is trying to generate a v50+ proxy where > its input object's class spec AND the input interface to proxy on are > both v49- without debug info, for example. > > C) A (bad) quick-fix for either of the above issues is to just use > 'arg0', 'arg1', 'arg2', analogous to what e.g. eclipse does when > showing method signatures for methods in classes where there is no > source, no debug info and no javadoc. This is not at all the right > idea. A small risk that the class file format documentation should > mention as not being appropriate unless there is absolutely no other > option. > > D) Most code these days ships with source, or javadoc, or debug info, > so that auto-complete shows the proper names for each parameter, but > this certainly isn't true for /all/ java code out there. After this > change, method param names become visible to all. This may not be a > desired side-effect for programming shops that export libraries to > clients where their method parameter names are inappropriate (swear > words, or 'x', 'y', and 'z' and this creates deserved but nevertheless > unexpected ridicule for sucking at programming style). I think this is > an acceptable price to pay. Parameters are method-local which are > extremely easy to rename with your friendly neighbourhood IDE's > refactor tool. > > E) While technically the names are NOT part of API, and you CAN freely > change names around without breaking any code, old or new, the names > still do become a little more enshrined as at least almost part of the > public API. This is already the case to some extent (param names show > up in various tooling support such as javadoc and auto-completing > IDEs) but this change would move parameter names a little more towards > a complete member of public API. This is an issue, but its also the > point of this proposal: Move towards a java world where parameter > names are universally available and are meaningful. I don't think this > is a serious problem, because A) names already have a flavour of > importance right now, and B) While they become more important with > this proposal, they still aren't true public API, and changing names > even after this proposal is accepted is not backwards incompatible. > > F) Confusion may arise when these names are unintentionally taken as > being either part of public API, or being hierarchical; they are in > fact neither. For example, this proposal makes no attempt to harmonize > name conflicts; if interface A has void foo(int bar), and interface B > has void foo(int baz), you can still of course write a class that > implements both of these. You can even name your foo's parameter > 'floobargle', of course. The aim of this proposal does not involve > making parameter names inherit sensibly. > > > --Reinier Zwitserloot > > > > On Apr 20, 2009, at 10:18, Jean-Baptiste Bugeaud wrote: > > > Hello Reinier, Hello Joe, > > > > Thanks for your feedback. > > > > 2009/4/19 Reinier Zwitserloot : > >> Your proposal is very incomplete. Three major nits: > >> > >> A. Did I miss something, or did you totally forget to include an > >> example of > >> calling a method with named parameters? Something like: > >> > >> doLogin(user: "foobar", password: new char[] { 'a', 'b', 'c' }) > > > > Reiner, I think my submission name is misleading everybody. This is > > not the same thing you debate some times back. My mistake ... I > should > > have clarified from the start : I do not look at adding direct > call by > > parameter name into the language (say "? la" ObjectiveC). But > simply a > > reliable way access to parameter name and name a parameter's name in > > static way thru time. See bug 6444738 for differences. > > > > Parameter names are very usefull information in most cases, and at > > this time, either implementers use duplicate annotation (dummy > > annotations storing again the same name) or they use tools such as > ASM > > to workaround the lack of API in the JDK. > > > > At the begining, I thought this requirement did not required a small > > synthax language change : a new API would be enough. But soon I > > realized that introducing name parameter that are static thru time, > > introduce anyway a new paradigm in the language that developer > should > > be able to control directly : do I want this parameter name to be > > static thu time ? or do I want to let the compiler decide as usual ? > > > > A compiler option is not the suitable tool for this. > > If this is a global switch, it will not offer the fine grain > required. > > If this is a per class/per package option, it will clutter the > > command line. > > And in both cases, it will not offer paradigm separation with the > > legacy. Thus you can not rely on the parameter name because you > never > > know if developper has stored the name accidentaly or for purpose. > > > >> B. Why static? You might as well have picked 'strictfp' - it's a > >> total > >> non-sequitur choice. Re-use of existing keywords is not really a > >> panacea; it > >> waters down the anchoring ability of a keyword to virtually > >> nothing. I'm not > >> sure if context-sensitive keywords are any better, but java7 is > >> already > >> going to have at least one ('module'), so don't beat around the > >> bush and > >> just call it 'named'). Could be just me, but introducing a change > >> which is > >> not backwards compatible IF you have a type that's called > >> 'named' (written > >> just like that, all-lower case), is not something I find > >> troublesome in the > >> least. That's very ugly code, and a migration tool can fix this > >> easily. > > > > Because of the definition a dictionary gives of it : something like > > "showing little change" is exactly what I meant for this paradigm. > And > > no "strictfp", as well as "const" and "goto" are not matching, you > see > > ;-) > > > > If you think that this worth integrating a new keywork, then there > is > > room for debate. I think static fits perfectly and is clear enough. > > AFAIK, we already have final that is contextual? why not static > too ? > > final is already stretched between two things : do not overload > member > > and do not reasign variable. > > > > With the proposed language changed static modifier will be stretched > > between static thru instances for members and static thru time for > > variables. > > > >> C. You don't mention having default values for parameters, which is > >> sort of > >> the point of this exercise (otherwise you really still need > >> builders ; any > >> method that has so many parameters that they need names probably > >> needs a > >> builder, and without defaults, not providing one and instead > >> relying on > >> named params is just an inferior bandaid to your ugly API; to get > >> it right > >> you STILL need to provide a builder. If, however, parameters can > have > >> defaults, then you no longer need to make builders at all). > > > > This is because I am not asking for named call of method ... simply > > for a way to access name of parameter. Just a completely different > > topic. > > I don't see why a parameter on an EJB is not meanfull for the > external > > ? same for an webservice ? why a parameter name could not be > meanfull > > ? I don't get your point. > > > > My design decision is the kind of decision that led to erasure based > > genericity : it has some drawback, loss of real parametrics > instances > > that could be usefull while reflection. But was the right decision > at > > the right time or either we would have lots binary compatibility > or we > > would still be debating wether or not implementing generics. > > > > My proposition on parameter name is analog, it is just meant to be > > used ASAP but does it does not fully solve all the possible > > expectations from this topic scope. Namely, should we call "by > > parameter name" in the language ? and how ? > > > > Room is let for the coming decade ;-) But the propopsition does not > > close doors to anything. > > > >> I suggest you look over the coin-dev mailing list; I entered a > >> rough sketch > >> of a named parameters proposal near the end of coin. I never wrote > >> it up > >> because I thought of it far too close to the deadline, and it's > >> still of > >> such high impact that I doubt it would pass muster for coin. > > > > Yes I've followed the debate :) But, again its my mistake "call by > > parameter names" is a much more complex topic with lots of > > performance/plaform impact. This is not a small language change > IMHO. > > Again, I do not look for calling a direct method call using named > > parameters .... just a way to retreive them. > > > > -- -- > > > > Joe, yes "late I am" ;-) > > > > FYI, I got this proposition cooking for several months I was not > able > > to find time to write & post it to you (pittyfull isn't it). > > > > If we remove the "language change" part (static named parameter) and > > only keep the getParameterNames() API part (keep the regular > parameter > > name), do you think this can be pushed to JDK7 even if out of > scope of > > coin ? This is a very small change to the API and would solve lot of > > time from lot of people. > > > > I mean, this API (along with the rest of the named parameter spec) > was > > removed from JDK6, skiping this in JDK7 means years again to wait > for > > it ? I think we are too much getting dependent on tools such as > ASM in > > lots of places (JavaEE implementation stacks for instance). And we > > have a good opportunity to remove the dependency for a clean/simple > > solution IMHO. > > > > Best Regards, > > JB > > > From neal at gafter.com Wed Apr 22 17:47:38 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 22 Apr 2009 17:47:38 -0700 Subject: SUBMISSION : A second look on "named parameters" / Clarification on the scope In-Reply-To: References: <2dc3bd00904200118s35e085fdk6f4ef3cac83cd6e9@mail.gmail.com> <15e8b9d20904200852q70bf48bcm2c9beb8685902488@mail.gmail.com> Message-ID: <15e8b9d20904221747y6d113ad3s5ed4dd380edbfe8c@mail.gmail.com> I'd suggest either jsr292 or a separate change fed into the underlying java 7 platform jsr (through the openjdk) On Wed, Apr 22, 2009 at 5:41 PM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > Neal: No, this is not an API change. It's a change to the JVM spec > (specifically, the section about class files). If it doesn't fit project > coin, then what would it fit? Most certainly not the > coin-but-for-API-updates. Where else would 'class files MUST include the > names of method parameters' fit? > > Adding the ability to get this information via reflection would be an API > change, but many coin proposals have a matching change to the reflection > API. > > --Reinier Zwitserloot > Like it? Tip it! > http://tipit.to > > > On Apr 20, 2009, at 17:52, Neal Gafter wrote: > > Reiner- > > This is a library proposal, not a language proposal, so it doesn't need to > be done inside project Coin. > > -Neal > > On Mon, Apr 20, 2009 at 3:16 AM, Reinier Zwitserloot < > reinier at zwitserloot.com> wrote: > >> Ah, now I understand. >> >> I've got a much simpler proposal to address this issue. >> >> NB: Joe, I know coin's long gone, but perhaps consider this one anyway >> - it seems to me that some sort of named parameters proposal is likely >> to be accepted in the future, and adding names now should ease >> transition. As part of the effort I've listed all possibly >> complication I can come up with, at the end. >> >> Proposal: >> >> >> Starting from the new class file format introduced in java7 (due to >> module support, the class format is definitely getting a version >> bump), all compilers MUST put the names of the parameters in the class >> file (javac -g style), and obfuscators/compressors/whatever MUST NOT >> remove this; a class file with version v50 (or whatever number its >> going to end up being) won't even pass the verifier without the names >> in place. >> >> Add an API call on the java.lang.reflect.Method object to obtain the >> names of the parameters (returns a String[], or 'null' if they aren't >> there. Calling this on a param-less method returns an empty array, not >> null). Having the names is an all-or-nothing situation: Either the >> names are all there and this call works, or some/all are missing, and >> then this call does not work. I'm not sure if you can even have just a >> few names defined in the .class file format, but even if you can, that >> situation should be so extremely rare, its not worth writing up a >> complicated rule for). It is guaranteed that if the array exists (is >> not null), then each array element is not null. >> >> Voila. No need to turn in a proposal that's more complicated than most >> just to solve this simple problem. >> >> Complications: >> >> A) It would no longer be possible to rewrite a v49 and below class >> without debug info into a v50 and up class file without having the >> source file, but I don't actually know of any tools that attempt to do >> this. >> >> B) Code that generates class files on the fly (like proxy generators >> and the like) will need to consider the names of method parameters if/ >> when they update the class file format they generate to v50+. A proxy >> generator has issues when it is trying to generate a v50+ proxy where >> its input object's class spec AND the input interface to proxy on are >> both v49- without debug info, for example. >> >> C) A (bad) quick-fix for either of the above issues is to just use >> 'arg0', 'arg1', 'arg2', analogous to what e.g. eclipse does when >> showing method signatures for methods in classes where there is no >> source, no debug info and no javadoc. This is not at all the right >> idea. A small risk that the class file format documentation should >> mention as not being appropriate unless there is absolutely no other >> option. >> >> D) Most code these days ships with source, or javadoc, or debug info, >> so that auto-complete shows the proper names for each parameter, but >> this certainly isn't true for /all/ java code out there. After this >> change, method param names become visible to all. This may not be a >> desired side-effect for programming shops that export libraries to >> clients where their method parameter names are inappropriate (swear >> words, or 'x', 'y', and 'z' and this creates deserved but nevertheless >> unexpected ridicule for sucking at programming style). I think this is >> an acceptable price to pay. Parameters are method-local which are >> extremely easy to rename with your friendly neighbourhood IDE's >> refactor tool. >> >> E) While technically the names are NOT part of API, and you CAN freely >> change names around without breaking any code, old or new, the names >> still do become a little more enshrined as at least almost part of the >> public API. This is already the case to some extent (param names show >> up in various tooling support such as javadoc and auto-completing >> IDEs) but this change would move parameter names a little more towards >> a complete member of public API. This is an issue, but its also the >> point of this proposal: Move towards a java world where parameter >> names are universally available and are meaningful. I don't think this >> is a serious problem, because A) names already have a flavour of >> importance right now, and B) While they become more important with >> this proposal, they still aren't true public API, and changing names >> even after this proposal is accepted is not backwards incompatible. >> >> F) Confusion may arise when these names are unintentionally taken as >> being either part of public API, or being hierarchical; they are in >> fact neither. For example, this proposal makes no attempt to harmonize >> name conflicts; if interface A has void foo(int bar), and interface B >> has void foo(int baz), you can still of course write a class that >> implements both of these. You can even name your foo's parameter >> 'floobargle', of course. The aim of this proposal does not involve >> making parameter names inherit sensibly. >> >> >> --Reinier Zwitserloot >> >> >> >> On Apr 20, 2009, at 10:18, Jean-Baptiste Bugeaud wrote: >> >> > Hello Reinier, Hello Joe, >> > >> > Thanks for your feedback. >> > >> > 2009/4/19 Reinier Zwitserloot : >> >> Your proposal is very incomplete. Three major nits: >> >> >> >> A. Did I miss something, or did you totally forget to include an >> >> example of >> >> calling a method with named parameters? Something like: >> >> >> >> doLogin(user: "foobar", password: new char[] { 'a', 'b', 'c' }) >> > >> > Reiner, I think my submission name is misleading everybody. This is >> > not the same thing you debate some times back. My mistake ... I should >> > have clarified from the start : I do not look at adding direct call by >> > parameter name into the language (say "? la" ObjectiveC). But simply a >> > reliable way access to parameter name and name a parameter's name in >> > static way thru time. See bug 6444738 for differences. >> > >> > Parameter names are very usefull information in most cases, and at >> > this time, either implementers use duplicate annotation (dummy >> > annotations storing again the same name) or they use tools such as ASM >> > to workaround the lack of API in the JDK. >> > >> > At the begining, I thought this requirement did not required a small >> > synthax language change : a new API would be enough. But soon I >> > realized that introducing name parameter that are static thru time, >> > introduce anyway a new paradigm in the language that developer should >> > be able to control directly : do I want this parameter name to be >> > static thu time ? or do I want to let the compiler decide as usual ? >> > >> > A compiler option is not the suitable tool for this. >> > If this is a global switch, it will not offer the fine grain required. >> > If this is a per class/per package option, it will clutter the >> > command line. >> > And in both cases, it will not offer paradigm separation with the >> > legacy. Thus you can not rely on the parameter name because you never >> > know if developper has stored the name accidentaly or for purpose. >> > >> >> B. Why static? You might as well have picked 'strictfp' - it's a >> >> total >> >> non-sequitur choice. Re-use of existing keywords is not really a >> >> panacea; it >> >> waters down the anchoring ability of a keyword to virtually >> >> nothing. I'm not >> >> sure if context-sensitive keywords are any better, but java7 is >> >> already >> >> going to have at least one ('module'), so don't beat around the >> >> bush and >> >> just call it 'named'). Could be just me, but introducing a change >> >> which is >> >> not backwards compatible IF you have a type that's called >> >> 'named' (written >> >> just like that, all-lower case), is not something I find >> >> troublesome in the >> >> least. That's very ugly code, and a migration tool can fix this >> >> easily. >> > >> > Because of the definition a dictionary gives of it : something like >> > "showing little change" is exactly what I meant for this paradigm. And >> > no "strictfp", as well as "const" and "goto" are not matching, you see >> > ;-) >> > >> > If you think that this worth integrating a new keywork, then there is >> > room for debate. I think static fits perfectly and is clear enough. >> > AFAIK, we already have final that is contextual? why not static too ? >> > final is already stretched between two things : do not overload member >> > and do not reasign variable. >> > >> > With the proposed language changed static modifier will be stretched >> > between static thru instances for members and static thru time for >> > variables. >> > >> >> C. You don't mention having default values for parameters, which is >> >> sort of >> >> the point of this exercise (otherwise you really still need >> >> builders ; any >> >> method that has so many parameters that they need names probably >> >> needs a >> >> builder, and without defaults, not providing one and instead >> >> relying on >> >> named params is just an inferior bandaid to your ugly API; to get >> >> it right >> >> you STILL need to provide a builder. If, however, parameters can have >> >> defaults, then you no longer need to make builders at all). >> > >> > This is because I am not asking for named call of method ... simply >> > for a way to access name of parameter. Just a completely different >> > topic. >> > I don't see why a parameter on an EJB is not meanfull for the external >> > ? same for an webservice ? why a parameter name could not be meanfull >> > ? I don't get your point. >> > >> > My design decision is the kind of decision that led to erasure based >> > genericity : it has some drawback, loss of real parametrics instances >> > that could be usefull while reflection. But was the right decision at >> > the right time or either we would have lots binary compatibility or we >> > would still be debating wether or not implementing generics. >> > >> > My proposition on parameter name is analog, it is just meant to be >> > used ASAP but does it does not fully solve all the possible >> > expectations from this topic scope. Namely, should we call "by >> > parameter name" in the language ? and how ? >> > >> > Room is let for the coming decade ;-) But the propopsition does not >> > close doors to anything. >> > >> >> I suggest you look over the coin-dev mailing list; I entered a >> >> rough sketch >> >> of a named parameters proposal near the end of coin. I never wrote >> >> it up >> >> because I thought of it far too close to the deadline, and it's >> >> still of >> >> such high impact that I doubt it would pass muster for coin. >> > >> > Yes I've followed the debate :) But, again its my mistake "call by >> > parameter names" is a much more complex topic with lots of >> > performance/plaform impact. This is not a small language change IMHO. >> > Again, I do not look for calling a direct method call using named >> > parameters .... just a way to retreive them. >> > >> > -- -- >> > >> > Joe, yes "late I am" ;-) >> > >> > FYI, I got this proposition cooking for several months I was not able >> > to find time to write & post it to you (pittyfull isn't it). >> > >> > If we remove the "language change" part (static named parameter) and >> > only keep the getParameterNames() API part (keep the regular parameter >> > name), do you think this can be pushed to JDK7 even if out of scope of >> > coin ? This is a very small change to the API and would solve lot of >> > time from lot of people. >> > >> > I mean, this API (along with the rest of the named parameter spec) was >> > removed from JDK6, skiping this in JDK7 means years again to wait for >> > it ? I think we are too much getting dependent on tools such as ASM in >> > lots of places (JavaEE implementation stacks for instance). And we >> > have a good opportunity to remove the dependency for a clean/simple >> > solution IMHO. >> > >> > Best Regards, >> > JB >> >> >> > > From Joe.Darcy at Sun.COM Wed Apr 22 21:08:15 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Wed, 22 Apr 2009 21:08:15 -0700 Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <3BBAA5CF-247E-430F-A271-A10C79642FF7@zwitserloot.com> References: <49C56020.2070207@joda.org> <49EDE7B4.2090006@sun.com> <3BBAA5CF-247E-430F-A271-A10C79642FF7@zwitserloot.com> Message-ID: <49EFE9AF.90909@sun.com> Reinier Zwitserloot wrote: > If the proposal was just about making the iterator available, I'd > agree with you, but the proposal adds methods like .first(), which are > /very/ useful indeed. It's right up there with ARM, and easily beats > string switching, in how applicable that would be. A library to implement the utility wrapper around an Iterator could be added without the language change. > > Adding a .join() method to String or List (depending on taste) would > solve over half of the use-cases for the extended forloop, though. Adding one method to string is preferable to a language change! -Joe From genman at noderunner.net Thu Apr 23 10:44:46 2009 From: genman at noderunner.net (Elias Ross) Date: Thu, 23 Apr 2009 10:44:46 -0700 Subject: Proposal: Allow a single-parameter method to be used as an infix operator Message-ID: AUTHOR(S): Elias Ross OVERVIEW FEATURE SUMMARY: Allow a single-parameter method to be used as an infix operator. Expressions like "object1.method(object2)" could be replaced with an easier-to-read expression "object1 method object2". This allows for easier to read code such as "a equals b" instead of "a.equals(b)". This idea borrows from Scala, although this proposal limits the complexity. MAJOR ADVANTAGE: Since Java does not allow for operators or operator overloading, all idiomatic expressions, such as "a.equals(b)", or "a.contains(b)" must be written using dots and parenthesis. MAJOR BENEFIT: Improvement in clarity for many idioms. MAJOR DISADVANTAGE: Obviously, code with this feature would look quite different than code without. Thus, I imagine it would look quite inconsistent to have both used in the same codebase. Also, it's not clear why, in the case of "object1 equals object2", when "object1" was null, a NullPointerException should be thrown. It also may seemingly collide with the "instanceof" operator. It would potentially encourage increased use of single parameter methods. ALTERNATIVES: None. EXAMPLES SIMPLE EXAMPLE: boolean eq = "a" equals "b"; ADVANCED EXAMPLE: Show advanced usage(s) of the feature. "abc" substring 1 matches "b."; // true (new BigInteger(10) divide new BigDecimal(2)).longValue(); // 5 // The following would not compile "abc" substring(1,2) equals "b"; DETAILS SPECIFICATION: Modification to http://java.sun.com/docs/books/jls/second_edition/html/syntax.doc.html Expression2Rest: {Infixop Expression3} + {Identifier Expression} Expression3 instanceof Type The "Identifier" refers to a single parameter method belonging to a class or instance, and "Expression" here evaluates to the argument passed to this method. COMPILATION: The compiler would treat the expression as a method call. TESTING: Testing would be done to validate the grammar and conflict with the "instanceof" operator. LIBRARY SUPPORT: None. REFLECTIVE APIS: None. OTHER CHANGES: None. MIGRATION: Code needs no migration. However, it might be nice to have a tool to "clean up" existing code. COMPATIBILITY BREAKING CHANGES: None. EXISTING PROGRAMS: Should continue to work. REFERENCES EXISTING BUGS: Unknown. URL FOR PROTOTYPE (optional): From Joe.Darcy at Sun.COM Thu Apr 23 10:55:44 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 23 Apr 2009 10:55:44 -0700 Subject: Proposal: Allow a single-parameter method to be used as an infix operator In-Reply-To: References: Message-ID: <49F0ABA0.2020400@sun.com> The call for proposals period ended several weeks ago; this proposal is thus overdue and will not be considered. -Joe Elias Ross wrote: > AUTHOR(S): Elias Ross > > OVERVIEW > > FEATURE SUMMARY: Allow a single-parameter method to be used as an > infix operator. Expressions like "object1.method(object2)" could be > replaced with an easier-to-read expression "object1 method object2". > This allows for easier to read code such as "a equals b" instead of > "a.equals(b)". This idea borrows from Scala, although this proposal > limits the complexity. > > MAJOR ADVANTAGE: Since Java does not allow for operators or operator > overloading, all idiomatic expressions, such as "a.equals(b)", or > "a.contains(b)" must be written using dots and parenthesis. > > MAJOR BENEFIT: Improvement in clarity for many idioms. > > MAJOR DISADVANTAGE: Obviously, code with this feature would look quite > different than code without. Thus, I imagine it would look quite > inconsistent to have both used in the same codebase. Also, it's not > clear why, in the case of "object1 equals object2", when "object1" was > null, a NullPointerException should be thrown. It also may seemingly > collide with the "instanceof" operator. > > It would potentially encourage increased use of single parameter methods. > > ALTERNATIVES: None. > > EXAMPLES > > SIMPLE EXAMPLE: > > boolean eq = "a" equals "b"; > > ADVANCED EXAMPLE: Show advanced usage(s) of the feature. > > "abc" substring 1 matches "b."; // true > (new BigInteger(10) divide new BigDecimal(2)).longValue(); // 5 > > // The following would not compile > "abc" substring(1,2) equals "b"; > > DETAILS > > SPECIFICATION: > > Modification to > http://java.sun.com/docs/books/jls/second_edition/html/syntax.doc.html > > Expression2Rest: > {Infixop Expression3} > + {Identifier Expression} > Expression3 instanceof Type > > The "Identifier" refers to a single parameter method belonging to a > class or instance, and "Expression" here evaluates to the argument > passed to this method. > > COMPILATION: The compiler would treat the expression as a method call. > > TESTING: Testing would be done to validate the grammar and conflict > with the "instanceof" operator. > > LIBRARY SUPPORT: None. > > REFLECTIVE APIS: None. > > OTHER CHANGES: None. > > MIGRATION: Code needs no migration. However, it might be nice to have > a tool to "clean up" existing code. > > COMPATIBILITY > > BREAKING CHANGES: None. > > EXISTING PROGRAMS: Should continue to work. > > REFERENCES > > EXISTING BUGS: Unknown. > > URL FOR PROTOTYPE (optional): > > From rssh at gradsoft.com.ua Thu Apr 23 15:34:37 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 24 Apr 2009 01:34:37 +0300 (EEST) Subject: Integer widening operators: some preliminary statistics. Message-ID: <4f30e61b8c0c456c06ca18996e3299e9.squirrel@wmail.gradsoft.ua> Good day, Bruce. Some data about integer widening operator: http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000906.html 3 checks was implemented: 1. model check for expression like ($x && 0xff) or (0xff & $x) where $x must have a type byte (original request). This check named as "widening operator (semantics)" 2. syntax check for expression like ($x && 0xff) or (0xff & $x) where $x can have any type. This check named as "widening operator (syntax)" Example of second but not first:
  public static short reverseBytes(short s) {
    return (short) (((s & 0xff) << 8) | ((s & 0xff00) >> 8));
  }
       byte[] nounce = new byte[24];
        for (int i=0;i<8;i++)
        {
            nounce[i]=(byte)(ts&0xff);
            ts=ts>>8;
            nounce[8+i]=(byte)(sk&0xff);
            sk=sk>>8;
        }
3. count of all expressions with bitwise and. (names as all bit ands) Than, results for jetty was: all bit ands : 121 widening operator (semantics) : 10 widening operator (syntax) : 20 // some other counts, to compare with: rethrow clause : 34 string in switch : 19 hibernate does not use bitwise and at all. gwt-users have 2 entries of syntax pattern (actually this is reverseBytes function). Result for jdk I will publish tomorrow, when ones will be ready. It was preliminary data (one from 3 packages use 'bitwise and') more statistics and some analysis will be available throught few days (with data about for-s and ERP in dataset). Best Regards ! From j16sdiz at gmail.com Thu Apr 23 18:18:00 2009 From: j16sdiz at gmail.com (Daniel Cheng) Date: Fri, 24 Apr 2009 09:18:00 +0800 Subject: Integer widening operators: some preliminary statistics. In-Reply-To: <4f30e61b8c0c456c06ca18996e3299e9.squirrel@wmail.gradsoft.ua> References: <4f30e61b8c0c456c06ca18996e3299e9.squirrel@wmail.gradsoft.ua> Message-ID: On Fri, Apr 24, 2009 at 6:34 AM, Ruslan Shevchenko wrote: > > Good day, Bruce. > > Some data about integer widening operator: > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000906.html > > 3 checks was implemented: > ?1. model check for expression like ?($x && 0xff) or (0xff & ?$x) where $x > must have a type byte (original request). This check named as "widening > operator (semantics)" > > 2. syntax check for expression like ?($x && 0xff) or (0xff & ?$x) where $x > can have any type. This check named as "widening operator (syntax)" > > ?Example of second but not first: >
> ?public static short reverseBytes(short s) {
> ? ?return (short) (((s & 0xff) << 8) | ((s & 0xff00) >> 8));
> ?}
> 
>
> ? ? ? byte[] nounce = new byte[24];
> ? ? ? ?for (int i=0;i<8;i++)
> ? ? ? ?{
> ? ? ? ? ? ?nounce[i]=(byte)(ts&0xff);
> ? ? ? ? ? ?ts=ts>>8;
> ? ? ? ? ? ?nounce[8+i]=(byte)(sk&0xff);
> ? ? ? ? ? ?sk=sk>>8;
> ? ? ? ?}
> 
> > 3. count of all expressions with bitwise and. (names as all bit ands) > > Than, results for jetty was: > > all bit ands ? ?: ? ? ? 121 > widening operator (semantics) ? : ? ? ? 10 > widening operator (syntax) ? ? ?: ? ? ? 20 > > // some other counts, to compare with: > rethrow clause ?: ? ? ? 34 > string in switch ? ? ? ?: ? ? ? 19 > > hibernate does not use bitwise and at all. > gwt-users have 2 entries of syntax pattern (actually this is reverseBytes > function). > > Result for jdk I will publish tomorrow, when ones will be ready. I expect this kind of usage are more common in low level formats. Try MINA SSH, OpenDS, etc.. > It was preliminary data (one from 3 packages use 'bitwise and') more > statistics and some analysis will be available throught few days (with > data about for-s and ERP in dataset). > > ?Best Regards ! > > > > > > > From rssh at gradsoft.com.ua Thu Apr 23 22:42:56 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 24 Apr 2009 08:42:56 +0300 (EEST) Subject: Integer widening operators: some preliminary statistics. In-Reply-To: <4f30e61b8c0c456c06ca18996e3299e9.squirrel@wmail.gradsoft.ua> References: <4f30e61b8c0c456c06ca18996e3299e9.squirrel@wmail.gradsoft.ua> Message-ID: > Results for open JDK: all bit ands : 6853 widening operator (semantics) : 1098 widening operator (syntax) : 1959 (i.e. near 1/6 or 1/7 of all bit-ands) all catchs : 8404 all ifs : 28494 all integer literals : 124355 big integer literals(undescores) : 4066 byte literal : 1454 catch in finally : 103 elvis : 877 instanceof switch : 318 loop with remove : 62 multi catch : 411 object switch : 1363 rethrow clause : 3264 string in switch : 445 > Good day, Bruce. > > Some data about integer widening operator: > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000906.html > > 3 checks was implemented: > 1. model check for expression like ($x && 0xff) or (0xff & $x) where $x > must have a type byte (original request). This check named as "widening > operator (semantics)" > > 2. syntax check for expression like ($x && 0xff) or (0xff & $x) where $x > can have any type. This check named as "widening operator (syntax)" > > Example of second but not first: >
>   public static short reverseBytes(short s) {
>     return (short) (((s & 0xff) << 8) | ((s & 0xff00) >> 8));
>   }
> 
>
>        byte[] nounce = new byte[24];
>         for (int i=0;i<8;i++)
>         {
>             nounce[i]=(byte)(ts&0xff);
>             ts=ts>>8;
>             nounce[8+i]=(byte)(sk&0xff);
>             sk=sk>>8;
>         }
> 
> > 3. count of all expressions with bitwise and. (names as all bit ands) > > Than, results for jetty was: > > all bit ands : 121 > widening operator (semantics) : 10 > widening operator (syntax) : 20 > > // some other counts, to compare with: > rethrow clause : 34 > string in switch : 19 > > hibernate does not use bitwise and at all. > gwt-users have 2 entries of syntax pattern (actually this is reverseBytes > function). > > Result for jdk I will publish tomorrow, when ones will be ready. > > It was preliminary data (one from 3 packages use 'bitwise and') more > statistics and some analysis will be available throught few days (with > data about for-s and ERP in dataset). > > Best Regards ! > > > > > > > From rssh at gradsoft.com.ua Thu Apr 23 22:44:35 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 24 Apr 2009 08:44:35 +0300 (EEST) Subject: Integer widening operators: some preliminary statistics. In-Reply-To: References: <4f30e61b8c0c456c06ca18996e3299e9.squirrel@wmail.gradsoft.ua> Message-ID: <074c557a3206ff6565d1ed857c4c4491.squirrel@wmail.gradsoft.ua> > I expect this kind of usage are more common in low level formats. > Try MINA SSH, OpenDS, etc.. > Or, adding ME ssh is a good idea: it small and more or less representative. Thanks. From scolebourne at joda.org Fri Apr 24 07:39:02 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Fri, 24 Apr 2009 15:39:02 +0100 Subject: Syntax patterns: more statistics. In-Reply-To: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> Message-ID: <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> Ruslan, I believe that the Elvis check isn't checking for the right thing ConditionalExpression( EqualityExpression($x,"==",NullLiteral()), $ifNull, MethodCall($x,$method,$args)) -> true [ violationDiscovered(Elvis, "elvis", $method) ], This would at first glance appear to match: (a == null ? null : a.xxx()) which isn't Elvis. Elvis is: (a == null ? b : a) (a != null ? a : b) (null == a ? b : a) (null != a ? a : b) Unfortunately, my attempts to encode this failed: ConditionalExpression( EqualityExpression($x,"==",NullLiteral()), $y, $x) -> true [ violationDiscovered(Elvis, "elvis", $x) ], On a separate item, the following finds all conditionals: define(AllConditionals,coin,"all conditionals", BT_TYPE_RULESET, ruleset( ConditionalExpression($x,$y,$z) -> true [ violationDiscovered(AllConditionals, "all conditionals",$x) ] ), true ), Stephen 2009/4/20 Ruslan Shevchenko : > Good day, community ! > > ?I want to share some statistics about java usage patterns, related to > some of coin-dev proposals. > > Main changes from previous post are: > ?- added counts for 'if' syntax constructions, so we can say, hom many > ?percents of if's can be eliminated by elvis operator ( [4-5]%) > ?- added counts for 'catch' syntax constructions, so we can say that > multicath eliminate 6-8% of all catch clauses. > ?- added count for big integers integers (where undescore can be > applicable, I guess this is x: x > 100000 || x < -10000) and for all > integer literals. > ? (underscore can be applicable to near 1%) > ?- added count for object-switch proposal by Ulf Zibis (refining, that > Left/Right part of expressions are first operand in equalirty expression > or object in method call) > ?- added count for rethrow proposal by Mark Mahieu (near 50% of all > catches in some packages (!) ). > ?- added count for catches inside finally block. (Is this is a real > problem [?]). > > If anybody whant run checks on own dataset or/and add own check > definitions: all ?procedure is the same as in my previous letter (see > http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001442.html) > except URL for last version > ?is > http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerSourceInstaller-2.5.0p1.jar > > Now summary statistics for some well-known packages: > jetty (web server) > all catchs ? ? ?: ? ? ? 281 > all ifs : ? ? ? 764 > all integer literals ? ?: ? ? ? 2903 > big integer literals(undescores) ? ? ? ?: ? ? ? 25 > byte literal ? ?: ? ? ? 52 > catch in finally ? ? ? ?: ? ? ? 3 > elvis ? : ? ? ? 43 > instanceof switch ? ? ? : ? ? ? 8 > loop with remove ? ? ? ?: ? ? ? 0 > multi catch ? ? : ? ? ? 22 > object switch ? : ? ? ? 31 > rethrow clause ?: ? ? ? 34 > string in switch ? ? ? ?: ? ? ? 19 > Files:187 > > gwt-users (google java ajax client library) > all catchs ? ? ?: ? ? ? 171 > all ifs : ? ? ? 735 > all integer literals ? ?: ? ? ? 2282 > big integer literals(undescores) ? ? ? ?: ? ? ? 24 > byte literal ? ?: ? ? ? 2 > catch in finally ? ? ? ?: ? ? ? 2 > elvis ? : ? ? ? 30 > instanceof switch ? ? ? : ? ? ? 6 > loop with remove ? ? ? ?: ? ? ? 5 > multi catch ? ? : ? ? ? 9 > object switch ? : ? ? ? 27 > rethrow clause ?: ? ? ? 84 > string in switch ? ? ? ?: ? ? ? 10 > Files:920 > > hibernate (ORM toolkit) > all catchs ? ? ?: ? ? ? 650 > all ifs : ? ? ? 2410 > all integer literals ? ?: ? ? ? 3240 > big integer literals(undescores) ? ? ? ?: ? ? ? 12 > byte literal ? ?: ? ? ? 1 > catch in finally ? ? ? ?: ? ? ? 27 > elvis ? : ? ? ? 182 > instanceof switch ? ? ? : ? ? ? 28 > loop with remove ? ? ? ?: ? ? ? 12 > multi catch ? ? : ? ? ? 25 > object switch ? : ? ? ? 94 > rethrow clause ?: ? ? ? 450 > string in switch ? ? ? ?: ? ? ? 86 > Files:1372 > > openjdk7 (standard java library) > all catchs ? ? ?: ? ? ? 8404 > all ifs : ? ? ? 28494 > all integer literals ? ?: ? ? ? 124356 > big integer literals(undescores) ? ? ? ?: ? ? ? 4066 > byte literal ? ?: ? ? ? 1454 > catch in finally ? ? ? ?: ? ? ? 103 > elvis ? : ? ? ? 877 > instanceof switch ? ? ? : ? ? ? 318 > loop with remove ? ? ? ?: ? ? ? 62 > multi catch ? ? : ? ? ? 411 > object switch ? : ? ? ? 1363 > rethrow clause ?: ? ? ? 3264 > string in switch ? ? ? ?: ? ? ? 445 > Files:9252 > > Hope, this data will be useful in some cases. > Regards ! > > > > From rssh at gradsoft.com.ua Fri Apr 24 08:20:17 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 24 Apr 2009 18:20:17 +0300 (EEST) Subject: Syntax patterns: more statistics. In-Reply-To: <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> Message-ID: <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> > Ruslan, > I believe that the Elvis check isn't checking for the right thing > > ConditionalExpression( > EqualityExpression($x,"==",NullLiteral()), > $ifNull, MethodCall($x,$method,$args)) -> true > [ violationDiscovered(Elvis, "elvis", $method) ], > > This would at first glance appear to match: > > (a == null ? null : a.xxx()) > This is (a==null ? b : a.xxx()) Also note, that check elvis contains 4 rules (starting fromn line 112, end from line 131 in ) http://redmine.gradsoft.ua/repositories/entry/javachecker/trunk/JavaChecker/etc/checkers_coin.def You cite only one. (Under elvis I understand http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000047.html) where the most generic is conditional expression. What you guess: (a == null ? null : a.xxx()) is ConditionalExpression( EqualityExpression($x,"==",NullLiteral()), NullLiteral(), MethodCall($x,$method,$args)) -> true [ violationDiscovered(Elvis, "elvis", $method) ], > which isn't Elvis. > > Elvis is: > > (a == null ? b : a) > (a != null ? a : b) > (null == a ? b : a) > (null != a ? a : b) > // Let's create this version. > Unfortunately, my attempts to encode this failed: > ConditionalExpression( > EqualityExpression($x,"==",NullLiteral()), > $y, $x) -> true > [ violationDiscovered(Elvis, "elvis", $x) ], > > > On a separate item, the following finds all conditionals: > define(AllConditionals,coin,"all conditionals", > BT_TYPE_RULESET, > ruleset( > ConditionalExpression($x,$y,$z) > -> true [ violationDiscovered(AllConditionals, "all > conditionals",$x) ] > ), > true > ), > Sorry, can you attach modified checkers_coin.def ? (or diff) > ConditionalExpression( > EqualityExpression($x,"==",NullLiteral()), > $y, $x) -> true > [ violationDiscovered(Elvis, "elvis", $x) ], is correct (in first look), but not complete //Probably, you can place rule inside ruleset of AllConditional to achieve such effect, or may be write AllConditionals instead Elvis in violation discovered To say something concrete, I need to see full define term. I. e. starts from define( .... and up to ,) //btw, If you agree, I can give you write access to svn, create file checkers_elvis.def, than will able see you changes and point on errors automatically after commits. > Stephen > > > 2009/4/20 Ruslan Shevchenko : >> Good day, community ! >> >> ?I want to share some statistics about java usage patterns, related to >> some of coin-dev proposals. >> >> Main changes from previous post are: >> ?- added counts for 'if' syntax constructions, so we can say, hom many >> ?percents of if's can be eliminated by elvis operator ( [4-5]%) >> ?- added counts for 'catch' syntax constructions, so we can say that >> multicath eliminate 6-8% of all catch clauses. >> ?- added count for big integers integers (where undescore can be >> applicable, I guess this is x: x > 100000 || x < -10000) and for all >> integer literals. >> ? (underscore can be applicable to near 1%) >> ?- added count for object-switch proposal by Ulf Zibis (refining, that >> Left/Right part of expressions are first operand in equalirty expression >> or object in method call) >> ?- added count for rethrow proposal by Mark Mahieu (near 50% of all >> catches in some packages (!) ). >> ?- added count for catches inside finally block. (Is this is a real >> problem [?]). >> >> If anybody whant run checks on own dataset or/and add own check >> definitions: all ?procedure is the same as in my previous letter (see >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001442.html) >> except URL for last version >> ?is >> http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerSourceInstaller-2.5.0p1.jar >> >> Now summary statistics for some well-known packages: >> jetty (web server) >> all catchs ? ? ?: ? ? ? 281 >> all ifs : ? ? ? 764 >> all integer literals ? ?: ? ? ? 2903 >> big integer literals(undescores) ? ? ? ?: ? ? ? 25 >> byte literal ? ?: ? ? ? 52 >> catch in finally ? ? ? ?: ? ? ? 3 >> elvis ? : ? ? ? 43 >> instanceof switch ? ? ? : ? ? ? 8 >> loop with remove ? ? ? ?: ? ? ? 0 >> multi catch ? ? : ? ? ? 22 >> object switch ? : ? ? ? 31 >> rethrow clause ?: ? ? ? 34 >> string in switch ? ? ? ?: ? ? ? 19 >> Files:187 >> >> gwt-users (google java ajax client library) >> all catchs ? ? ?: ? ? ? 171 >> all ifs : ? ? ? 735 >> all integer literals ? ?: ? ? ? 2282 >> big integer literals(undescores) ? ? ? ?: ? ? ? 24 >> byte literal ? ?: ? ? ? 2 >> catch in finally ? ? ? ?: ? ? ? 2 >> elvis ? : ? ? ? 30 >> instanceof switch ? ? ? : ? ? ? 6 >> loop with remove ? ? ? ?: ? ? ? 5 >> multi catch ? ? : ? ? ? 9 >> object switch ? : ? ? ? 27 >> rethrow clause ?: ? ? ? 84 >> string in switch ? ? ? ?: ? ? ? 10 >> Files:920 >> >> hibernate (ORM toolkit) >> all catchs ? ? ?: ? ? ? 650 >> all ifs : ? ? ? 2410 >> all integer literals ? ?: ? ? ? 3240 >> big integer literals(undescores) ? ? ? ?: ? ? ? 12 >> byte literal ? ?: ? ? ? 1 >> catch in finally ? ? ? ?: ? ? ? 27 >> elvis ? : ? ? ? 182 >> instanceof switch ? ? ? : ? ? ? 28 >> loop with remove ? ? ? ?: ? ? ? 12 >> multi catch ? ? : ? ? ? 25 >> object switch ? : ? ? ? 94 >> rethrow clause ?: ? ? ? 450 >> string in switch ? ? ? ?: ? ? ? 86 >> Files:1372 >> >> openjdk7 (standard java library) >> all catchs ? ? ?: ? ? ? 8404 >> all ifs : ? ? ? 28494 >> all integer literals ? ?: ? ? ? 124356 >> big integer literals(undescores) ? ? ? ?: ? ? ? 4066 >> byte literal ? ?: ? ? ? 1454 >> catch in finally ? ? ? ?: ? ? ? 103 >> elvis ? : ? ? ? 877 >> instanceof switch ? ? ? : ? ? ? 318 >> loop with remove ? ? ? ?: ? ? ? 62 >> multi catch ? ? : ? ? ? 411 >> object switch ? : ? ? ? 1363 >> rethrow clause ?: ? ? ? 3264 >> string in switch ? ? ? ?: ? ? ? 445 >> Files:9252 >> >> Hope, this data will be useful in some cases. >> Regards ! >> >> >> >> > > From rssh at gradsoft.com.ua Fri Apr 24 08:58:58 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 24 Apr 2009 18:58:58 +0300 (EEST) Subject: elvis pattern refinement (was Syntax patterns) In-Reply-To: <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> Message-ID: Hi, Stephen //At first - in previous letter I forgott to say thanks for refinement. I just commited elvis1 definition, which is exaclty what you write. http://redmine.gradsoft.ua/repositories/entry/javachecker/trunk/JavaChecker/etc/checkers_elvis.def But I mean this is incorrect, becouse it does not cover case of 'null-safe method call' (which is often used for describing elvis). So, for example, in jetty we see only one matching for four patterns. More - rereading proposal, I see that I implement check for 'safe method call' but in proposal we have 'safe index; safe field access, .. etc) So, let's explicit define all aviable patterns. First question: is 'safe-method call': i. e. (a==null ? b : a.method(...)) pattern is correct ? // Which can be rewritten as a?.method() ?: b From scolebourne at joda.org Fri Apr 24 09:15:11 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Fri, 24 Apr 2009 17:15:11 +0100 Subject: Syntax patterns: more statistics. In-Reply-To: <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> Message-ID: <4b4f45e00904240915p1ef7337h154ad887610f1108@mail.gmail.com> 2009/4/24 Ruslan Shevchenko : > To say something concrete, I need to see full define term. > I. e. starts from define( .... ?and up to ,) This is what I tried: define(Elvis,coin,"elvis", BT_TYPE_RULESET, ruleset( ConditionalExpression( EqualityExpression($x,"==",NullLiteral()), $y, $x) -> true [ violationDiscovered(Elvis, "elvis", $method) ], ... similar for the other three ),true), But it didn't work. The second one was to find all conditionals - aiming to find any and all conditional statements: define(AllConditionals,coin,"all conditionals", BT_TYPE_RULESET, ruleset( ConditionalExpression($x,$y,$z) -> true [ violationDiscovered(AllConditionals, "all conditionals",$x) ] ), true ), That is working fine. I should also note that the iterator remove() only catches remove() within a while-statement, and not within an iterator-driven for-statement. Stephen From rssh at gradsoft.com.ua Fri Apr 24 09:33:01 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 24 Apr 2009 19:33:01 +0300 (EEST) Subject: Syntax patterns: more statistics. In-Reply-To: <4b4f45e00904240915p1ef7337h154ad887610f1108@mail.gmail.com> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> <4b4f45e00904240915p1ef7337h154ad887610f1108@mail.gmail.com> Message-ID: <8a12b3c18bc0298cd3ca3521b5244462.squirrel@wmail.gradsoft.ua> > 2009/4/24 Ruslan Shevchenko : >> To say something concrete, I need to see full define term. >> I. e. starts from define( .... ?and up to ,) > > This is what I tried: > > define(Elvis,coin,"elvis", > BT_TYPE_RULESET, > ruleset( > ConditionalExpression( > EqualityExpression($x,"==",NullLiteral()), > $y, $x) -> true > [ violationDiscovered(Elvis, "elvis", $method) ], > ... similar for the other three > ),true), > > But it didn't work. > > $method in violationDiscovered now is free variable, which have no line and number information. // how this work inside -- javachecker retrieve location information from first identifier, found inside term in third parameter. So, better write something in style > define(Elvis,coin,"elvis", > BT_TYPE_RULESET, > ruleset( > ConditionalExpression( > EqualityExpression($x,"==",NullLiteral()), > $y, $x) -> true > [ violationDiscovered(Elvis, "elvis", $x) ], > ... similar for the other three > ),true), And what mean 'does not work' ? Let's define some common small dataset. > The second one was to find all conditionals - aiming to find any and > all conditional statements: > > define(AllConditionals,coin,"all conditionals", > BT_TYPE_RULESET, > ruleset( > ConditionalExpression($x,$y,$z) > -> true [ violationDiscovered(AllConditionals, "all > conditionals",$x) ] > ), > true > ), > > That is working fine. > > > I should also note that the iterator remove() only catches remove() > within a while-statement, and not within an iterator-driven > for-statement. Yes. Will be fixed. (I guess iterator-driven for statement does not exist in life and usually written as while, but better check all, of course.) > > Stephen > > From scolebourne at joda.org Fri Apr 24 09:40:36 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Fri, 24 Apr 2009 17:40:36 +0100 Subject: Syntax patterns: more statistics. In-Reply-To: <8a12b3c18bc0298cd3ca3521b5244462.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> <4b4f45e00904240915p1ef7337h154ad887610f1108@mail.gmail.com> <8a12b3c18bc0298cd3ca3521b5244462.squirrel@wmail.gradsoft.ua> Message-ID: <4b4f45e00904240940i254c310chb2eaebee63f53bfe@mail.gmail.com> 2009/4/24 Ruslan Shevchenko : > And what mean 'does not work' ? > Let's define some common small dataset. These are the patterns that need to be identified for Elvis: (a == null ? b : a) (a != null ? a : b) (null == a ? b : a) (null != a ? a : b) where a is any expression (occurs twice and is exactly the same in both cases), and b is any expression. Ideally, these same patterns should also be matched as if-statements, but that will be a lot harder/impossible. The null-safe operator patterns are more complex. >> I should also note that the iterator remove() only catches remove() >> within a while-statement, and not within an iterator-driven >> for-statement. > > Yes. Will be fixed. Thanks > ?(I guess iterator-driven for statement does not exist > in life and usually written as while, but better check all, of course.) Not so. About 50% of the remove() are in while-statement and 50% in for-statement in the sourcebase I'm evaluating. Stephen From scolebourne at joda.org Fri Apr 24 09:45:21 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Fri, 24 Apr 2009 17:45:21 +0100 Subject: elvis pattern refinement (was Syntax patterns) In-Reply-To: References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> Message-ID: <4b4f45e00904240945o4630227rc75996cad3d7fba4@mail.gmail.com> 2009/4/24 Ruslan Shevchenko : > But I mean this is incorrect, becouse it does not cover case of > 'null-safe method call' (which is often used for describing elvis). Officially, 'Elvis' just refers to the 'default if null' pattern. The other operators are the 'null-safe' operators. > So, for example, in jetty we see only one matching for four patterns. > More - rereading ?proposal, I see that I implement check for 'safe method > call' but in proposal we have 'safe index; safe field access, .. etc) > > So, let's explicit define all aviable patterns. > > First question: is 'safe-method call': i. e. > (a==null ? b : a.method(...)) pattern is correct ? > // Which can be rewritten as ? ?a?.method() ?: b If I were writing Java today without the null-safe operators, then I would typically use an if-statement: if (foo != null) { foo.process(); } Bar bar = null; if (foo != null) { bar = foo.process(); } Stephen From rssh at gradsoft.com.ua Fri Apr 24 09:57:28 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 24 Apr 2009 19:57:28 +0300 (EEST) Subject: Syntax patterns: more statistics. In-Reply-To: <4b4f45e00904240940i254c310chb2eaebee63f53bfe@mail.gmail.com> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> <4b4f45e00904240915p1ef7337h154ad887610f1108@mail.gmail.com> <8a12b3c18bc0298cd3ca3521b5244462.squirrel@wmail.gradsoft.ua> <4b4f45e00904240940i254c310chb2eaebee63f53bfe@mail.gmail.com> Message-ID: <604e8bb368364a76e8df1e7865f91527.squirrel@wmail.gradsoft.ua> > 2009/4/24 Ruslan Shevchenko : >> And what mean 'does not work' ? >> Let's define some common small dataset. > > These are the patterns that need to be identified for Elvis: > (a == null ? b : a) > (a != null ? a : b) > (null == a ? b : a) > (null != a ? a : b) > > where a is any expression (occurs twice and is exactly the same in > both cases), and b is any expression. Ideally, these same patterns > should also be matched as if-statements, but that will be a lot > harder/impossible. > Under common small dataset I mean sourcebase. I. e. while you think that such patterns does not works ? May be they absent in you sourcebase. (I just scan jetty sources for such patterns - only one matching per 187 files ). So 'clear elvis' is extremely rare. So, let's define some common sources (well-known packet or just archive). Show me, where this patterns is skipped and I will be able to debug this. > The null-safe operator patterns are more complex. > >>> I should also note that the iterator remove() only catches remove() >>> within a while-statement, and not within an iterator-driven >>> for-statement. >> >> Yes. Will be fixed. > Thanks > >> ?(I guess iterator-driven for statement does not exist >> in life and usually written as while, but better check all, of course.) > > Not so. About 50% of the remove() are in while-statement and 50% in > for-statement in the sourcebase I'm evaluating. > surprised ;) > Stephen > > From ali.ebrahimi1781 at gmail.com Fri Apr 24 10:02:25 2009 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Fri, 24 Apr 2009 21:32:25 +0430 Subject: My wishlist and Ideas for java 7 as java developer Message-ID: <5ab441490904241002r3ac43f59g327ffe88bd63b7b8@mail.gmail.com> Hi All, java needs cool features. My wishlist and ideas for java 7: 1) switch on objects. switch(obj){ case *String str:* println("obj instance of String and *str* result of cast (String)obj"); break; *// instanceof case* case *obj2 :* println("obj equals obj2"); break; // *equals case* .... } a few rules for this statement. 1) subclasses must be apears after superclass class Base{} clase SubClass extends Base{} switch(obj){ case Base b: dowithBase(b); .... // Compile error or Warning case SubClasss s: dowithSub(s); } this rule anagulus to rules for catch clauses .... I very like this switch statement compared with all proposed proposals to list in this case. I want to see this in java 7. 2) function types(method references) base on Method Handles(Thanks john rose for your great work). In other words, add language support for Method Handles. sample: public static void each(Collection c, *MethodHandle mh*) { for(Object element:c) { *mh.invoke(element);* } } public static void sayHello(Object message) { System.out.println("hello "+message); } public static void main(String[] args) { * MethodType methodType=MethodType.make(void.class, Object.class); MethodHandle **myFunc**=MethodHandles.findStatic(MethodHandleTest.class, "sayHello", methodType); * List list=Arrays.asList("item1", "item2"); each(list, *myFunc*); } with language support for Method Handles(function types) code would be as below : public static void each(Collection c, *(Object)=>void* method) { // or void(Object) for(Object element:c) { method.invoke(element); or method(element) } } public static void sayHello(Object message) { System.out.println("hello "+message); } public static void main(String[] args) { *(Object)=>void myFunc = MyClass#sayHello(Object);* List list=Arrays.asList("item1", "item2"); each(list, *myFunc*); } 3) *Property support with Automatic Binding Support* sample: class Person{ //form1: with Compiler aware Annotation(As Override) *private @**Property** String name;* // Or // form2: *property **String name;* } Translated to: class Person{ *public final Property Name = Property.make();* public String getName(){ return this.name.getValue(); } public void setName(String name){ this.name.setValue(name); } } how to use: Person person = new Person(); person*.name = "Ali";* //Translated to person.setName("Ali"); *String PName = *person*.name;* //Translated to String PName = person.getName(); *Property nameProperty = *person*.Name;* // access property object - *Adding auto binding support:* With only one bind method in Property class *public void bind(Propery dest){ bind(dest,false)} **public void bind(Propery dest, boolean inverse){ .....} * usage : //UI class class TextFieldUI extends ...{ property String text; } Person person = new Person(); person.name = "Ali"; TextFieldUI nameUI = new TextFieldUI(); *// Uni-directional binding nameUI.Text.bind(person.Name); // Or bind(nameUI.Text,person.Name); // bi-directional binding nameUI.Text.bind(person.Name,true); // bind(nameUI.Text,person.Name,true**);* - *Validation support:* By adding one method to Property class *public void addValidator(Validator validator){ ...}* - *Triger or Change Listener support* By adding one method to Property class *public void addTriger(ChangeListener changeListener){ ...} // or add**ChangeListener* Propery class thing like as below: class Property{ private T value; public T getValue(){ return value; } public void setValue(T newVal){ T old = this.value; if( !old.equals(newVal)){ if(validate(newVal)){ this.value = newVal; valueChanged(old,newVal); } } } private Set> dependents; private Set validators; private Set trigers; private valueChanged(K oldV, K newV){ fireTrigers(oldV,newV); propagateToDependencies(); } private void fireTrigers(K oldV, K newV){ if(trigers == null || trigers.size() == 0) return; for(ChangeListener triger:trigers){ triger.onChange(oldV,newV); } } private void propagateToDependendts(){ if(dependents == null || dependents.size() == 0) return; for(Property dependentP:dependents){ depedentP.setValue(this.value); } } public void addTriger(ChangeListener changeListener){ if(trigers == null) trigers=new HashSet(); trigers.add(changeListener); } public void removeTriger(ChangeListener changeListener){ if(trigers != null) trigers.remove(changeListener); } public void bind(Property dest){ bind(dest,false);} public void bind(Property dest, boolean inverse){ dest.addDependency(this); if(inverse) this.addDependency(dest) } public void addDependent(Property dependentProperty){ if(dependents == null) dependets = new HashSet(); dependencts.add(dependentProperty); } public void removeDependent(Property dependentProperty){ if(dependents != null) dependents.remove(dependentProperty); } public void unBind(Property dest){ dest.removeDependet(this); } ... } Advantages 1) comprehensive property support 2) Non-Reflection base: do'nt use reflection therefore high perfomance 3) Minimum language change; .... And many other ideas. Best Regards Ali Ebrahimi From ali.ebrahimi1781 at gmail.com Fri Apr 24 10:08:04 2009 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Fri, 24 Apr 2009 21:38:04 +0430 Subject: My wishlist and Ideas for java 7 as java developer In-Reply-To: <5ab441490904241002r3ac43f59g327ffe88bd63b7b8@mail.gmail.com> References: <5ab441490904241002r3ac43f59g327ffe88bd63b7b8@mail.gmail.com> Message-ID: <5ab441490904241008l54a8746bi8154b86fc1344cde@mail.gmail.com> Hi All, java needs cool features. My wishlist and ideas for java 7: 1) switch on objects. switch(obj){ case String str: println("obj instance of String and str result of cast (String)obj"); break; // instanceof case case obj2 : println("obj equals obj2"); break; // equals case .... } a few rules for this statement. 1) subclasses must be apears after superclass class Base{} clase SubClass extends Base{} switch(obj){ case Base b: dowithBase(b); .... // Compile error or Warning case SubClasss s: dowithSub(s); } this rule anagulus to rules for catch clauses .... I very like this switch statement compared with all proposed proposals to list in this case. I want to see this in java 7. 2) function types(method references) base on Method Handles(Thanks john rose for your great work). In other words, add language support for Method Handles. sample: public static void each(Collection c, MethodHandle mh) { for(Object element:c) { mh.invoke(element); } } public static void sayHello(Object message) { System.out.println("hello "+message); } public static void main(String[] args) { MethodType methodType=MethodType.make(void.class, Object.class); MethodHandle myFunc=MethodHandles.findStatic(MethodHandleTest.class, "sayHello", methodType); List list=Arrays.asList("item1", "item2"); each(list, myFunc); } with language support for Method Handles(function types) code would be as below : public static void each(Collection c, (Object)=>void method) { // or void(Object) for(Object element:c) { method.invoke(element); or method(element) } } public static void sayHello(Object message) { System.out.println("hello "+message); } public static void main(String[] args) { (Object)=>void myFunc = MyClass#sayHello(Object); List list=Arrays.asList("item1", "item2"); each(list, myFunc); } 3) Property support with Automatic Binding Support sample: class Person{ //form1: with Compiler aware Annotation(As Override) private @Property String name; // Or // form2: property String name; } Translated to: class Person{ public final Property Name = Property.make(); public String getName(){ return this.name.getValue(); } public void setName(String name){ this.name.setValue(name); } } how to use: Person person = new Person(); person.name = "Ali"; //Translated to person.setName("Ali"); String PName = person.name; //Translated to String PName = person.getName(); Property nameProperty = person.Name; // access property object - Adding auto binding support: With only one bind method in Property class public void bind(Propery dest){ bind(dest,false)} public void bind(Propery dest, boolean inverse){ .....} usage : //UI class class TextFieldUI extends ...{ property String text; } Person person = new Person(); person.name = "Ali"; TextFieldUI nameUI = new TextFieldUI(); // Uni-directional binding nameUI.Text.bind(person.Name); // Or bind(nameUI.Text,person.Name); // bi-directional binding nameUI.Text.bind(person.Name,true); // bind(nameUI.Text,person.Name,true); - Validation support: By adding one method to Property class public void addValidator(Validator validator){ ...} - Triger or Change Listener support By adding one method to Property class public void addTriger(ChangeListener changeListener){ ...} // or addChangeListener Propery class thing like as below: class Property{ private T value; public T getValue(){ return value; } public void setValue(T newVal){ T old = this.value; if( !old.equals(newVal)){ if(validate(newVal)){ this.value = newVal; valueChanged(old,newVal); } } } private Set> dependents; private Set validators; private Set trigers; private valueChanged(K oldV, K newV){ fireTrigers(oldV,newV); propagateToDependencies(); } private void fireTrigers(K oldV, K newV){ if(trigers == null || trigers.size() == 0) return; for(ChangeListener triger:trigers){ triger.onChange(oldV,newV); } } private void propagateToDependendts(){ if(dependents == null || dependents.size() == 0) return; for(Property dependentP:dependents){ depedentP.setValue(this.value); } } public void addTriger(ChangeListener changeListener){ if(trigers == null) trigers=new HashSet(); trigers.add(changeListener); } public void removeTriger(ChangeListener changeListener){ if(trigers != null) trigers.remove(changeListener); } public void bind(Property dest){ bind(dest,false);} public void bind(Property dest, boolean inverse){ dest.addDependency(this); if(inverse) this.addDependency(dest) } public void addDependent(Property dependentProperty){ if(dependents == null) dependets = new HashSet(); dependencts.add(dependentProperty); } public void removeDependent(Property dependentProperty){ if(dependents != null) dependents.remove(dependentProperty); } public void unBind(Property dest){ dest.removeDependet(this); } ... } Advantages 1) comprehensive property support 2) Non-Reflection base: do'nt use reflection therefore high perfomance 3) Minimum language change; .... And many other ideas. Best Regards Ali Ebrahimi From rssh at gradsoft.com.ua Fri Apr 24 10:08:19 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 24 Apr 2009 20:08:19 +0300 (EEST) Subject: elvis pattern refinement (was Syntax patterns) In-Reply-To: <4b4f45e00904240945o4630227rc75996cad3d7fba4@mail.gmail.com> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> <4b4f45e00904240945o4630227rc75996cad3d7fba4@mail.gmail.com> Message-ID: <152e5a7a9f1cc3e929fe730e7913e36b.squirrel@wmail.gradsoft.ua> > 2009/4/24 Ruslan Shevchenko : >> But I mean this is incorrect, becouse it does not cover case of >> 'null-safe method call' (which is often used for describing elvis). > > Officially, 'Elvis' just refers to the 'default if null' pattern. The > other operators are the 'null-safe' operators. > In such case we need rename one. What I count was 'optimization of method calls, via operators defined in elvis proposal', not occurences of elvis. >> So, for example, in jetty we see only one matching for four patterns. >> More - rereading ?proposal, I see that I implement check for 'safe >> method >> call' but in proposal we have 'safe index; safe field access, .. etc) >> >> So, let's explicit define all aviable patterns. >> >> First question: is 'safe-method call': i. e. >> (a==null ? b : a.method(...)) pattern is correct ? >> // Which can be rewritten as ? ?a?.method() ?: b > > If I were writing Java today without the null-safe operators, then I > would typically use an if-statement: > > if (foo != null) { > foo.process(); > } > > Bar bar = null; > if (foo != null) { > bar = foo.process(); > } > > Stephen > Great - you found hole, I just forgot, that IfStatement already can be optimized. // will start write such pattern in Elvis1 now. But let's return to original question: is 'safe-method call': i. e. optimization of pattern (a==null ? b : a.method(...)) // Which can be rewritten as a?.method() ?: b using operators, defined in elvis, can be counted as entry for optimization as result of elvis proposal, or not ? > From scolebourne at joda.org Fri Apr 24 10:25:48 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Fri, 24 Apr 2009 18:25:48 +0100 Subject: Statistics for E-Commerce system Message-ID: <4b4f45e00904241025k6ccd948i5b0d646a0cc2c63b@mail.gmail.com> 1.3 million LOC Old sourcebase, lots of refactoring down the years Java EE, Servlets but not EJB Two parts - low level utilities, and main E-commerce codebase Low level utilities ------------------------- all catchs : 549 all conditionals : 297 all ifs : 1521 all integer literals : 4863 big integer literals(undescores): 326 byte literal : 0 catch in finally : 14 elvis : 86 --> correct value 36 instanceof switch : 27 loop with remove : 5 --> correct value 33 multi catch : 31 object switch : 81 rethrow clause : 271 string in switch : 23 Files:564 while \(.+?\.hasNext\(\)\) all hasNext() while : 39 for \(Iterator all iterator() for : 68 for \(int all int for : 375 for \( all for : 631 Elvis-conditional = 36/297 = 12.1% Loop-remove = 33/631 = 5.2% Multi-catch = 31/549 = 5.6% Main E-Commerce system --------------------------------------- (counted in three parts to avoid out of memory in the tool, and to demonstrate how different types of code affect the results) Main code (most of the business logic: all catchs : 2592 all conditionals : 2185 all ifs : 7431 all integer literals : 45473 big integer literals(undescores): 5738 byte literal : 0 catch in finally : 35 elvis : 600 --> correct value ? instanceof switch : 159 loop with remove : 88 --> correct value 430 multi catch : 39 object switch : 379 rethrow clause : 859 string in switch : 117 Files:5822 Sub part 1 (code generated beans): all catchs : 753 all conditionals : 10244 all ifs : 4955 all integer literals : 145405 big integer literals(undescores) : 25957 byte literal : 0 catch in finally : 0 elvis : 4058 --> correct value, probably 0 instanceof switch : 9 loop with remove : 0 --> correct value 0 multi catch : 0 object switch : 15 rethrow clause : 1 string in switch : 0 Files:1553 Sub part 2 (presentation layer): all catchs : 370 all conditionals : 366 all ifs : 1622 all integer literals : 2632 big integer literals(undescores) : 39 byte literal : 0 catch in finally : 6 elvis : 33 instanceof switch : 47 loop with remove : 8 --> correct value 20 multi catch : 0 object switch : 112 rethrow clause : 61 string in switch : 35 Files:1160 while \(.+?\.hasNext\(\)\) all hasNext() while : 256 for \(Iterator all iterator() for : 536 for \(int all int for : 4530 *not all loops around lists for \( all for : 8248 *not all loops around lists Elvis-conditional = ?/2185 = Loop-with-remove = 450/8248 = 5.5% Multi-catch = 39/3715 = 1.0% The Elvis number currently needs manual work to calculate, so I passed for the size of the main sourcebase. However, 12% of all conditionals in the low level library is a reasonable number of hits. The loop-with-remove is between 5 and 5.5% (of all loops, which includes loops around things other than lists, like strings). I can't easily determine how often the loop index is needed, or whether it is the first/last loop, each of which would push up the %age. Multi-catch has about 1% of all catch statements in the main E-Commerce, but 5.6% in the low level libraries. This perhaps indicates where the sweet spot for the feature is - libraries and frameworks. Stephen From scolebourne at joda.org Fri Apr 24 10:28:33 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Fri, 24 Apr 2009 18:28:33 +0100 Subject: elvis pattern refinement (was Syntax patterns) In-Reply-To: <152e5a7a9f1cc3e929fe730e7913e36b.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> <4b4f45e00904240945o4630227rc75996cad3d7fba4@mail.gmail.com> <152e5a7a9f1cc3e929fe730e7913e36b.squirrel@wmail.gradsoft.ua> Message-ID: <4b4f45e00904241028t140786bfr53ccf0c3e2ed99ff@mail.gmail.com> 2009/4/24 Ruslan Shevchenko : > But let's return to original question: > > is 'safe-method call': i. e. optimization of pattern > ?(a==null ? b : a.method(...)) > ?// Which can be rewritten as > ? ?a?.method() ?: b > ?using operators, defined in elvis, can be counted as entry for > optimization as result of elvis proposal, or not ? This could be coded as a?.method() ?: b however, that would be semantically different in meaning (as now b is returned if method() returns null, which wasn't originally the case) Thus, this construct is invalid for Elvis, Null-safe and the combination of the two. Stephen From ali.ebrahimi1781 at gmail.com Fri Apr 24 10:44:55 2009 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Fri, 24 Apr 2009 22:14:55 +0430 Subject: elvis pattern refinement (was Syntax patterns) Message-ID: <5ab441490904241044p1b51bd3ag5e653da20af68378@mail.gmail.com> My Idea for this proposal: result = a!.method():b; Null-Safe Call Operator: !. return type a.method() and type of var b is assignable to result. equivalents with : if( a!= null){ result = a.method(); } else{ result =b; } *Or result = a != null? a.method(): b; Best Regards Ali Ebrahimi * From reinier at zwitserloot.com Fri Apr 24 10:49:58 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Fri, 24 Apr 2009 19:49:58 +0200 Subject: elvis pattern refinement (was Syntax patterns) In-Reply-To: <5ab441490904241044p1b51bd3ag5e653da20af68378@mail.gmail.com> References: <5ab441490904241044p1b51bd3ag5e653da20af68378@mail.gmail.com> Message-ID: <32B3A77A-F2D9-4647-8E34-8D3E2C9D5641@zwitserloot.com> Ali, the proposal phase is long gone. These discussions about the elvis pattern are about which of 2 already submitted proposals to take (just the elvis operator, or also ?. and others) - that's why Ruslan and Stephen are sorting out how useful they would be in code bases. The other statistics Ruslan is reporting are also in regards to completely specified proposals submitted before the deadline of March 30th. --Reinier Zwitserloot Like it? Tip it! http://tipit.to On Apr 24, 2009, at 19:44, Ali Ebrahimi wrote: > My Idea for this proposal: > > result = a!.method():b; > > Null-Safe Call Operator: !. > return type a.method() and type of var b is assignable to result. > > equivalents with : > > if( a!= null){ > result = a.method(); > } else{ > result =b; > } > > *Or > > result = a != null? a.method(): b; > > > Best Regards > Ali Ebrahimi > * > From rssh at gradsoft.com.ua Fri Apr 24 10:54:35 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 24 Apr 2009 20:54:35 +0300 (EEST) Subject: elvis pattern refinement (was Syntax patterns) In-Reply-To: <4b4f45e00904241028t140786bfr53ccf0c3e2ed99ff@mail.gmail.com> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> <4b4f45e00904240945o4630227rc75996cad3d7fba4@mail.gmail.com> <152e5a7a9f1cc3e929fe730e7913e36b.squirrel@wmail.gradsoft.ua> <4b4f45e00904241028t140786bfr53ccf0c3e2ed99ff@mail.gmail.com> Message-ID: <0bbda97b46febc7962911b1c82616624.squirrel@wmail.gradsoft.ua> > a!=null ? a.method() : b > a?.method() ?: b > > however, that would be semantically different in meaning (as now b is > returned if method() returns null, which wasn't originally the case) > > Thus, this construct is invalid for Elvis, Null-safe and the > combination of the two. > Ok, so will exclude one. next question: a!=null ? a.method() : null must be counted or not ? (i.e. it's clean safe method call) > Stephen > > From rssh at gradsoft.com.ua Fri Apr 24 11:06:31 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 24 Apr 2009 21:06:31 +0300 (EEST) Subject: [if-s done]Re: elvis pattern refinement (was Syntax patterns) In-Reply-To: <152e5a7a9f1cc3e929fe730e7913e36b.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> <4b4f45e00904240945o4630227rc75996cad3d7fba4@mail.gmail.com> <152e5a7a9f1cc3e929fe730e7913e36b.squirrel@wmail.gradsoft.ua> Message-ID: > >> If I were writing Java today without the null-safe operators, then I >> would typically use an if-statement: >> >> if (foo != null) { >> foo.process(); >> } >> >> Bar bar = null; >> if (foo != null) { >> bar = foo.process(); >> } >> >> Stephen >> Just added, see http://redmine.gradsoft.ua/repositories/entry/javachecker/trunk/JavaChecker/etc/checkers_elvis.def starting from line 24 So, in next version will be correct elvis and loops. From Joe.Darcy at Sun.COM Fri Apr 24 11:12:22 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Fri, 24 Apr 2009 11:12:22 -0700 Subject: My wishlist and Ideas for java 7 as java developer In-Reply-To: <5ab441490904241002r3ac43f59g327ffe88bd63b7b8@mail.gmail.com> References: <5ab441490904241002r3ac43f59g327ffe88bd63b7b8@mail.gmail.com> Message-ID: <49F20106.6060000@sun.com> Ali Ebrahimi wrote: > Hi All, > java needs cool features. > > My wishlist and ideas for java 7: > The items on your list have generally been covered by submitted proposals and it is long past the time to submit any new proposals. [snip] > And many other ideas. > Ideas alone are worth very little. Merely saying "I want this" without any reasoning or rationale makes at most a negligible contribution to the discussion. -Joe From rssh at gradsoft.com.ua Fri Apr 24 11:20:04 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 24 Apr 2009 21:20:04 +0300 (EEST) Subject: Statistics for E-Commerce system In-Reply-To: <4b4f45e00904241025k6ccd948i5b0d646a0cc2c63b@mail.gmail.com> References: <4b4f45e00904241025k6ccd948i5b0d646a0cc2c63b@mail.gmail.com> Message-ID: Great ! Also interesting that rethrows/all catchs also vary a lot. And how many time require processing of all of this ? // I will try to fix elvis, loop and add loop-indexes tomorrow. > 1.3 million LOC > Old sourcebase, lots of refactoring down the years > Java EE, Servlets but not EJB > Two parts - low level utilities, and main E-commerce codebase > > Low level utilities > ------------------------- > all catchs : 549 > all conditionals : 297 > all ifs : 1521 > all integer literals : 4863 > big integer literals(undescores): 326 > byte literal : 0 > catch in finally : 14 > elvis : 86 --> correct value 36 > instanceof switch : 27 > loop with remove : 5 --> correct value 33 > multi catch : 31 > object switch : 81 > rethrow clause : 271 > string in switch : 23 > Files:564 > > while \(.+?\.hasNext\(\)\) > all hasNext() while : 39 > for \(Iterator > all iterator() for : 68 > for \(int > all int for : 375 > for \( > all for : 631 > > Elvis-conditional = 36/297 = 12.1% > Loop-remove = 33/631 = 5.2% > Multi-catch = 31/549 = 5.6% > > > Main E-Commerce system > --------------------------------------- > (counted in three parts to avoid out of memory in the tool, and to > demonstrate how different types of code affect the results) > Main code (most of the business logic: > all catchs : 2592 > all conditionals : 2185 > all ifs : 7431 > all integer literals : 45473 > big integer literals(undescores): 5738 > byte literal : 0 > catch in finally : 35 > elvis : 600 --> correct value ? > instanceof switch : 159 > loop with remove : 88 --> correct value 430 > multi catch : 39 > object switch : 379 > rethrow clause : 859 > string in switch : 117 > Files:5822 > > Sub part 1 (code generated beans): > all catchs : 753 > all conditionals : 10244 > all ifs : 4955 > all integer literals : 145405 > big integer literals(undescores) : 25957 > byte literal : 0 > catch in finally : 0 > elvis : 4058 --> correct value, probably 0 > instanceof switch : 9 > loop with remove : 0 --> correct value 0 > multi catch : 0 > object switch : 15 > rethrow clause : 1 > string in switch : 0 > Files:1553 > > Sub part 2 (presentation layer): > all catchs : 370 > all conditionals : 366 > all ifs : 1622 > all integer literals : 2632 > big integer literals(undescores) : 39 > byte literal : 0 > catch in finally : 6 > elvis : 33 > instanceof switch : 47 > loop with remove : 8 --> correct value 20 > multi catch : 0 > object switch : 112 > rethrow clause : 61 > string in switch : 35 > Files:1160 > > while \(.+?\.hasNext\(\)\) > all hasNext() while : 256 > for \(Iterator > all iterator() for : 536 > for \(int > all int for : 4530 *not all loops around lists > for \( > all for : 8248 *not all loops around lists > > Elvis-conditional = ?/2185 = > Loop-with-remove = 450/8248 = 5.5% > Multi-catch = 39/3715 = 1.0% > > > The Elvis number currently needs manual work to calculate, so I passed > for the size of the main sourcebase. However, 12% of all conditionals > in the low level library is a reasonable number of hits. > > The loop-with-remove is between 5 and 5.5% (of all loops, which > includes loops around things other than lists, like strings). I can't > easily determine how often the loop index is needed, or whether it is > the first/last loop, each of which would push up the %age. > > Multi-catch has about 1% of all catch statements in the main > E-Commerce, but 5.6% in the low level libraries. This perhaps > indicates where the sweet spot for the feature is - libraries and > frameworks. > > Stephen > > From pdoubleya at gmail.com Fri Apr 24 14:11:02 2009 From: pdoubleya at gmail.com (Patrick Wright) Date: Fri, 24 Apr 2009 23:11:02 +0200 Subject: Statistics for E-Commerce system In-Reply-To: <4b4f45e00904241025k6ccd948i5b0d646a0cc2c63b@mail.gmail.com> References: <4b4f45e00904241025k6ccd948i5b0d646a0cc2c63b@mail.gmail.com> Message-ID: <64efa1ba0904241411u26e5a7beu4fb533b49bd22514@mail.gmail.com> Since you didn't name the project, I assume this is closed-source? It's certainly useful to run this tool across all sorts of codebases, on the other hand, it's probably more useful for the group to run this against open source projects where any of us can open up the codebase and take a peek inside. Regards Patrick On Fri, Apr 24, 2009 at 7:25 PM, Stephen Colebourne wrote: > 1.3 million LOC > Old sourcebase, lots of refactoring down the years > Java EE, Servlets but not EJB > Two parts - low level utilities, and main E-commerce codebase From ali.ebrahimi1781 at gmail.com Fri Apr 24 15:52:00 2009 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Sat, 25 Apr 2009 03:22:00 +0430 Subject: My wishlist and Ideas for java 7 as java developer In-Reply-To: <5ab441490904241545g6e74682rb6ffd9c44f9d274@mail.gmail.com> References: <5ab441490904241002r3ac43f59g327ffe88bd63b7b8@mail.gmail.com> <49F20106.6060000@sun.com> <5ab441490904241545g6e74682rb6ffd9c44f9d274@mail.gmail.com> Message-ID: <5ab441490904241552w288935c9y62e2678576eabbe5@mail.gmail.com> Hi Joe, I'm not proposing new proposal for coin. I just want to share My Ideas regards to submitted proposals. And I very like to supported this Ideas by submitted proposals(in final revision), if them are nice and acceptable. I have followed all discussions on list from first(27 February) and the submitted proposals for me As one java developer is not *sufficient* and acceptable and satisfying(from viewpoint of quality Not quantity and Title). So I decided to register to list (today) and share My Ideas for java 7 not coin. I (not only I *perhaps All developers*) need for this features And every day deal with them In My code. I just want to java to be every day better than yesterday. Also I want to see feedback of All members on list for My Ideas in details not generally. Best regards Ali ebrahimi On Fri, Apr 24, 2009 at 10:42 PM, Joseph D. Darcy wrote: > Ali Ebrahimi wrote: > >> Hi All, >> java needs cool features. >> >> My wishlist and ideas for java 7: >> >> > > The items on your list have generally been covered by submitted proposals > and it is long past the time to submit any new proposals. > > [snip] > >> And many other ideas. >> >> > > Ideas alone are worth very little. > > Merely saying "I want this" without any reasoning or rationale makes at > most a negligible contribution to the discussion. > > -Joe > From scolebourne at joda.org Fri Apr 24 16:25:33 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Sat, 25 Apr 2009 00:25:33 +0100 Subject: elvis pattern refinement (was Syntax patterns) In-Reply-To: <0bbda97b46febc7962911b1c82616624.squirrel@wmail.gradsoft.ua> References: <3708a46a63059d8b1a46a3b7fc56036e.squirrel@wmail.gradsoft.ua> <4b4f45e00904240739g5b313489x162a005c16cc4ff7@mail.gmail.com> <90e12e623b34e8bdd2b9dc8c54ed6e3b.squirrel@wmail.gradsoft.ua> <4b4f45e00904240945o4630227rc75996cad3d7fba4@mail.gmail.com> <152e5a7a9f1cc3e929fe730e7913e36b.squirrel@wmail.gradsoft.ua> <4b4f45e00904241028t140786bfr53ccf0c3e2ed99ff@mail.gmail.com> <0bbda97b46febc7962911b1c82616624.squirrel@wmail.gradsoft.ua> Message-ID: <4b4f45e00904241625n71e6cab5kbd0ada460a74c542@mail.gmail.com> 2009/4/24 Ruslan Shevchenko : > next question: > ?a!=null ? a.method() : null > must be counted or not ? Yes, that would be another pattern. But so would multiple tests: if (a != null && a.b() != null) { a.b().c(); } if (a != null && a.b() != null) { result = a.b().c(); } BTW, I'd prefer to see separate figures for Elvis and Null-Safe operators. Thus that means two 'define's in the def file. Stephen From scolebourne at joda.org Fri Apr 24 16:36:10 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Sat, 25 Apr 2009 00:36:10 +0100 Subject: Statistics for E-Commerce system In-Reply-To: <64efa1ba0904241411u26e5a7beu4fb533b49bd22514@mail.gmail.com> References: <4b4f45e00904241025k6ccd948i5b0d646a0cc2c63b@mail.gmail.com> <64efa1ba0904241411u26e5a7beu4fb533b49bd22514@mail.gmail.com> Message-ID: <4b4f45e00904241636w6fdb1833gdf905fd556da22c3@mail.gmail.com> 2009/4/24 Patrick Wright : > Since you didn't name the project, I assume this is closed-source? Yes, its closed. One point I didn't mention, is that it is Java 5 based source. > It's certainly useful to run this tool across all sorts of codebases, > on the other hand, it's probably more useful for the group to run this > against open source projects where any of us can open up the codebase > and take a peek inside. While being able to look at the source and see why particular pieces of code are triggering particular language change proposals, its worth pointing out that OSS is very different code. OSS is typically library/framework code, closed source is typically business logic. As shown in my figures, that can greatly affect the kind of results you get. I'd also note that there is vastly more closed source than open source. So, its the closed source code that needs to be tackled by language changes. (I'm not arguing that we shouldn't run it against OSS either! But I do believe that closed source is in the end the primary interesting case) BTW, I understand that James Gosling did similar analysis when evaluating accessing lists/maps by array-like syntax. The key is to obtain data points, which help Joe/Sun make decisions. > And how many time require processing of all of this ? The tool took less than an hour total, but split over the four runs. The other figures required some Eclipse searches, so the whole effort took a little longer. Stephen From paul.martin at gmail.com Sat Apr 25 04:12:38 2009 From: paul.martin at gmail.com (Paul Martin) Date: Sat, 25 Apr 2009 12:12:38 +0100 Subject: PROPOSAL: Named method parameters In-Reply-To: <001636458a864f71e304681a2fb7@google.com> References: <001636458a864f71e304681a2fb7@google.com> Message-ID: <4ce75f920904250412k48fe11f9p3cc3b0f8c52bcc03@mail.gmail.com> Hi, Thanks for your suggestions. PEC does seem interesting, and seems to be covering a different space to that covered by analysis tools such as Findbugs (that I am familiar with). I'll take a closer look. Will you extend it to include support for the @Immutable (and similar) annotations that are hopefully coming with Java7? Simple structures are a reasonable alternative to named parameters, particularly based on your assumption that "you would only use this if there were a lot of arguments", which would not be the common case. Other than the (slightly) more complex syntax, the only real disadvantage that I can see is: - It is hard to ensure that all of the fields are explicitly set (to avoid errors where we forget to set a value, or refactor to add a field and then forget to update a caller) However, this does seem to be solvable using static analysis tools such as Findbugs (or PEC?), particularly if there is an annotation such as @SubclassMustSet on the class or each required field, which could indicate that such checks are required. Tools such as Spring should be able to use simple structures directly (and maybe additional support could simplify their use). Maybe I'll give that a go. I still think that adding support for named parameters to Java would be worthwhile (both because the intention is perhaps clearer, and they may be even more valuable in other JVM languages), and don't think that it necessarily has to be too contentious to implement them. Regards, Paul On Wed, Apr 22, 2009 at 1:52 AM, wrote: > I use the builder pattern successfully via my enhanced compiler ( pet > project :) ): > > https://pec.dev.java.net/nonav/compile/index.html > > and in particular: > > https://pec.dev.java.net/nonav/compile/javadoc/pec/compile/immutable/ImmutableValueConversions.html > > The enhanced compiler enforces the pattern, ie if you get it wrong the > compiler gives you an error message. > > You can also use a simple structure like class, eg: > > class Point { > > static class Args { > int x = 0; > int y = 0; > } > > final int x; > > final iny y; > > Point( Args args ) { > x = args.x; > y = args.y; > } > > ... > > } > > Which is used like: > > Point p = new Point( new Point.Args() {{ x = 1; }} ); > > As the original post said you would only use this if there were a lot of > arguments, therefore the overhead of typing "new Point.Args() {{ }}" is > negligible. > > -- Howard. > > From rssh at gradsoft.com.ua Sat Apr 25 07:36:47 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Sat, 25 Apr 2009 17:36:47 +0300 (EEST) Subject: Elvis and NullSafe: description of patterns Message-ID: It;s about patterns for applicability of elvis Proposal in http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000047.html First naive approach was to count all condition expressions, which looks like (a != null ? a.method(..) : b). This approach is criticized, because semantics of substitution with elvis operators _a?method() ?: b_ is differ from original: when _a.method()_ will return _null_, than result of expression will be _b_, not _null_. From other side, when people will write software with elvis operator, I believe they will slightly change semantics of their functions to use elvis, so this approach still can be used as estimation. After helper discussion with Stephen in this list, I want to describe patterns which will used for counting of number of applicability for elvis proposal in next 'release or run' of javachecker coin rules, to ensure, that they are more or less correct. rules can be reviewed now: (see http://redmine.gradsoft.ua/repositories/entry/javachecker/trunk/JavaChecker/etc/checkers_elvis.def) So, patterns are: Elvis itself, i. e. a==null ? a : b a!=null ? b : a null==a ? b : a null!=a ? a : b NullSafe method call (as condition statement) if (a==null) { a.process(); } and if (a==null) { x=a.process(); } NullSafe method call (as condition expression) a!=null ? a.method(...) : null a==null ? null: a.method(...) null==a ? null: a.method(...) null!=a ? a.method(...) : null NullSafe field access. (as method calls, but with field access expression instead method call) NullSafe array index access (as method calls, but with array index expression instead method call) Complex null-safe expression. example is public static Integer qqq(Z[] z, int i) { if ( z!=null && z[i]!=null && z[i].y!=null) { return z[i].y.a; } else { return null; } } We use some approximation, i. e. count all if patterns, where * if condition expression is ConditionAnd of conditions all of which are check for nulls. * argument of first elementary condition from condition expression is contained in block, which evaluated when if condition experssion is evaluated to true. Hope, this is more close to reality, than first naive proposal. Below of run for jetty, main results and javachecker custom version will be available later (hope tomorrow) after adding loop index. handling issues. * : 0 all bit ands : 121 all conditional expressions : 277 all catchs : 281 all ifs : 764 all integer literals : 2903 big integer literals(undescores) : 25 byte literal : 52 catch in finally : 3 elvis : 43 elvis1 : 33 instanceof switch : 8 loop with remove : 0 multi catch : 22 nullsafe call of fields and methods : 44 object switch : 31 rethrow clause : 34 string in switch : 19 widening operator (semantics) : 10 widening operator (syntax) : 20 Files:187 From howard.lovatt at iee.org Sat Apr 25 18:59:24 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Sun, 26 Apr 2009 11:59:24 +1000 Subject: PROPOSAL: Named method parameters In-Reply-To: <4ce75f920904250412k48fe11f9p3cc3b0f8c52bcc03@mail.gmail.com> References: <001636458a864f71e304681a2fb7@google.com> <4ce75f920904250412k48fe11f9p3cc3b0f8c52bcc03@mail.gmail.com> Message-ID: <3dd3f56a0904251859y595c59e4pd664f1005ab5350b@mail.gmail.com> Hi Paul, I am working on including annotations, but there are a few problem with annotations in this context at the moment. Namely if I annotate an interface, then a class that implements that interface does not get the annotation even if the annotation is annotated as Inherited. I think there was discussion of this problem as part of JSR 308, but I am unsure how far a solution progressed. A second problem, less serious if the first was fixed, is that you can't add a method to an annotation, so for example with Immutable Value Conversions I want standardly named conversion methods but with annotations you can't do this. Thirdly it is generally frowned upon to use Annotations to change behavior, with the advice to use a marker interface (e.g. Serialization). As a result I currently plan to use a mixture of annotations and interfaces. -- Howard. 2009/4/25 Paul Martin > Hi, > > Thanks for your suggestions. > > PEC does seem interesting, and seems to be covering a different space > to that covered by analysis tools such as Findbugs (that I am familiar > with). I'll take a closer look. Will you extend it to include > support for the @Immutable (and similar) annotations that are > hopefully coming with Java7? > > Simple structures are a reasonable alternative to named parameters, > particularly based on your assumption that "you would only use this if > there were a lot of arguments", which would not be the common case. > Other than the (slightly) more complex syntax, the only real > disadvantage that I can see is: > - It is hard to ensure that all of the fields are explicitly set (to > avoid errors where we forget to set a value, or refactor to add a > field and then forget to update a caller) > > However, this does seem to be solvable using static analysis tools > such as Findbugs (or PEC?), particularly if there is an annotation > such as @SubclassMustSet on the class or each required field, which > could indicate that such checks are required. Tools such as Spring > should be able to use simple structures directly (and maybe additional > support could simplify their use). Maybe I'll give that a go. > > I still think that adding support for named parameters to Java would > be worthwhile (both because the intention is perhaps clearer, and they > may be even more valuable in other JVM languages), and don't think > that it necessarily has to be too contentious to implement them. > > Regards, > > Paul > > > On Wed, Apr 22, 2009 at 1:52 AM, wrote: > > I use the builder pattern successfully via my enhanced compiler ( pet > > project :) ): > > > > https://pec.dev.java.net/nonav/compile/index.html > > > > and in particular: > > > > > https://pec.dev.java.net/nonav/compile/javadoc/pec/compile/immutable/ImmutableValueConversions.html > > > > The enhanced compiler enforces the pattern, ie if you get it wrong the > > compiler gives you an error message. > > > > You can also use a simple structure like class, eg: > > > > class Point { > > > > static class Args { > > int x = 0; > > int y = 0; > > } > > > > final int x; > > > > final iny y; > > > > Point( Args args ) { > > x = args.x; > > y = args.y; > > } > > > > ... > > > > } > > > > Which is used like: > > > > Point p = new Point( new Point.Args() {{ x = 1; }} ); > > > > As the original post said you would only use this if there were a lot of > > arguments, therefore the overhead of typing "new Point.Args() {{ }}" is > > negligible. > > > > -- Howard. > > > > > -- -- Howard. From paul.martin at gmail.com Sun Apr 26 02:11:02 2009 From: paul.martin at gmail.com (paul.martin at gmail.com) Date: Sun, 26 Apr 2009 09:11:02 +0000 Subject: PROPOSAL: Named method parameters In-Reply-To: <3dd3f56a0904251859y595c59e4pd664f1005ab5350b@mail.gmail.com> Message-ID: <0016e6d7eaacd9af3c0468719bd0@google.com> Hi, That all sounds sensible. It would be good to integrate with JSR 308, but your idea of using standard methods to highlight the design pattern sounds nice and would need an interface. Regards, Paul On Apr 26, 2009 2:59am, Howard Lovatt wrote: > Hi Paul, > I am working on including annotations, but there are a few problem with > annotations in this context at the moment. Namely if I annotate an > interface, then a class that implements that interface does not get the > annotation even if the annotation is annotated as Inherited. I think > there was discussion of this problem as part of JSR 308, but I am unsure > how far a solution progressed. A second problem, less serious if the > first was fixed, is that you can't add a method to an annotation, so for > example with Immutable Value Conversions I want standardly named > conversion methods but with annotations you can't do this. Thirdly it is > generally frowned upon to use Annotations to change behavior, with the > advice to use a marker interface (eg Serialization). > As a result I currently plan to use a mixture of annotations and > interfaces. > -- Howard. > 2009/4/25 Paul Martin paul.martin at gmail.com> > Hi, > Thanks for your suggestions. > PEC does seem interesting, and seems to be covering a different space > to that covered by analysis tools such as Findbugs (that I am familiar > with). I'll take a closer look. Will you extend it to include > support for the @Immutable (and similar) annotations that are > hopefully coming with Java7? > Simple structures are a reasonable alternative to named parameters, > particularly based on your assumption that "you would only use this if > there were a lot of arguments", which would not be the common case. > Other than the (slightly) more complex syntax, the only real > disadvantage that I can see is: > - It is hard to ensure that all of the fields are explicitly set (to > avoid errors where we forget to set a value, or refactor to add a > field and then forget to update a caller) > However, this does seem to be solvable using static analysis tools > such as Findbugs (or PEC?), particularly if there is an annotation > such as @SubclassMustSet on the class or each required field, which > could indicate that such checks are required. Tools such as Spring > should be able to use simple structures directly (and maybe additional > support could simplify their use). Maybe I'll give that a go. > I still think that adding support for named parameters to Java would > be worthwhile (both because the intention is perhaps clearer, and they > may be even more valuable in other JVM languages), and don't think > that it necessarily has to be too contentious to implement them. > Regards, > Paul > On Wed, Apr 22, 2009 at 1:52 AM, howard.lovatt at gmail.com> wrote: > > I use the builder pattern successfully via my enhanced compiler ( pet > > project :) ): > > > > https://pec.dev.java.net/nonav/compile/index.html > > > > and in particular: > > > > > https://pec.dev.java.net/nonav/compile/javadoc/pec/compile/immutable/ImmutableValueConversions.html > > > > The enhanced compiler enforces the pattern, ie if you get it wrong the > > compiler gives you an error message. > > > > You can also use a simple structure like class, eg: > > > > class Point { > > > > static class Args { > > int x = 0; > > int y = 0; > > } > > > > final int x; > > > > final iny y; > > > > Point( Args args ) { > > x = args.x; > > y = args.y; > > } > > > > ... > > > > } > > > > Which is used like: > > > > Point p = new Point( new Point.Args() {{ x = 1; }} ); > > > > As the original post said you would only use this if there were a lot of > > arguments, therefore the overhead of typing "new Point.Args() {{ }}" is > > negligible. > > > > -- Howard. > > > > > -- > -- Howard. From rssh at gradsoft.com.ua Sun Apr 26 08:03:58 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Sun, 26 Apr 2009 18:03:58 +0300 (EEST) Subject: traditional for loop, which use indexes: pattern description Message-ID: <72841246c7ee7bf566925c08146a41c8.squirrel@wmail.gradsoft.ua> Good day, community. It's about proposal about adding for of loop with access for index value. http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000737.html Patterns can be reviewed at http://redmine.gradsoft.ua/repositories/entry/javachecker/trunk/JavaChecker/etc/checkers_coin.def So, what statistics we need: 1) How many for traditional loops we have at all. 2) How many for loops have form: for(int i=0; i Good day, community. Next 'release' for syntax pattern and check tool. Main changes: - added set of patterns, which more correctly describe elvis proposal Approriative names: elvis1 and NullSafe (see http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001610.html for details) - added checking for it.remove() inside for loop. - added set of patterns for widening integer proposal (see http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001582.html for details) - added set of patterns for counting loops with index access (see http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001613.html for details) - added count for all condition expressions. Modofied JavaChecker installation which include new patterns can be downloaded from http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerSourceInstaller-2.5.0p3.jar If anybody whant run checks on own dataset or/and add own check definitions: all procedure is the same as in my previous letter (see http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001442.html) except URL for last version Note, that with all checks users quite run slow, so may be have sense to run only checks you needed, not all. Some results: coin-jetty: all bit ands : 121 all conditional expressions : 277 all catchs : 281 all ifs : 764 all integer literals : 2903 all traditional fors : 315 big integer literals(undescores) : 25 byte literal : 52 catch in finally : 3 elvis : 43 elvis1 : 33 for loop from 0 to size or length : 100 for with limit like it.next() : 4 instanceof switch : 8 invalid checker comments : 0 loop with remove : 0 multi catch : 22 nullsafe call of fields and methods : 35 object switch : 31 rethrow clause : 34 string in switch : 19 widening operator (semantics) : 10 widening operator (syntax) : 20 hibernate: all bit ands : 2 all conditional expressions : 792 all catchs : 650 all ifs : 2410 all integer literals : 3240 all traditional fors : 708 big integer literals(undescores) : 12 byte literal : 1 catch in finally : 27 elvis : 182 elvis1 : 77 for loop from 0 to size or length : 385 for with limit like it.next() : 16 instanceof switch : 28 loop with remove : 12 multi catch : 25 nullsafe call of fields and methods : 175 object switch : 94 rethrow clause : 450 string in switch : 86 widening operator (semantics) : 0 widening operator (syntax) : 0 Files:1372 openjdk: all bit ands : 6822 all conditional expressions : 6770 all catchs : 8411 all ifs : 28464 all integer literals : 121919 all traditional fors : 11530 big integer literals(undescores) : 4589 byte literal : 1452 catch in finally : 103 elvis : 880 elvis1 : 437 for loop from 0 to size or length : 3137 for with limit like it.next() : 235 instanceof switch : 317 loop with remove : 94 multi catch : 412 nullsafe call of fields and methods : 384 object switch : 1360 rethrow clause : 3267 string in switch : 444 widening operator (semantics) : 1090 widening operator (syntax) : 1955 Files:9278 all bit ands : 58 all conditional expressions : 208 all catchs : 171 all ifs : 735 all integer literals : 2282 all traditional fors : 271 big integer literals(undescores) : 24 byte literal : 2 catch in finally : 2 elvis : 30 elvis1 : 18 for loop from 0 to size or length : 71 for with limit like it.next() : 20 instanceof switch : 6 loop with remove : 7 multi catch : 9 nullsafe call of fields and methods : 66 object switch : 27 rethrow clause : 84 string in switch : 10 widening operator (semantics) : 0 widening operator (syntax) : 2 Files:920 (btw, I plan to add result for compiere ERP, when understand their building process) From brucechapman at paradise.net.nz Sun Apr 26 16:07:47 2009 From: brucechapman at paradise.net.nz (brucechapman at paradise.net.nz) Date: Mon, 27 Apr 2009 11:07:47 +1200 (NZST) Subject: Syntax patterns: more more statistics. In-Reply-To: <28a181896c1bc05e2777cb6bcb166fec.squirrel@wmail.gradsoft.ua> References: <28a181896c1bc05e2777cb6bcb166fec.squirrel@wmail.gradsoft.ua> Message-ID: <1240787267.49f4e9432c4f9@www.paradise.net.nz> Quoting Ruslan Shevchenko : > Note, that with all checks users quite run slow, so may be have sense > to > run only checks you needed, not all. > > Some results: > > widening operator (semantics) : 10 > widening operator (syntax) : 20 > > Ruslan, The "widening operator (syntax)" check is not really helpful for the widening conversion stuff. The "semantic" one seems to be correct. I suspect the "syntax" one is also picking up a corresponding "encoding" operation corresponding to the "decoding" operation which is normally being detected by the "semantics" check (which is why the syntax value is very close to double the number for the semantic check). To save processing time, please drop the "syntax" check. Oh, And thanks very much for all your effort on this. Bruce From rssh at gradsoft.com.ua Mon Apr 27 09:23:51 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Mon, 27 Apr 2009 19:23:51 +0300 (EEST) Subject: Syntax patterns: more more statistics. In-Reply-To: <1240787267.49f4e9432c4f9@www.paradise.net.nz> References: <28a181896c1bc05e2777cb6bcb166fec.squirrel@wmail.gradsoft.ua> <1240787267.49f4e9432c4f9@www.paradise.net.nz> Message-ID: <7ed018835d415448739477c8349958ae.squirrel@wmail.gradsoft.ua> > > The "widening operator (syntax)" check is not really helpful for the > widening > conversion stuff. The "semantic" one seems to be correct. I suspect the > "syntax" > one is also picking up a corresponding "encoding" operation corresponding > to the > "decoding" operation which is normally being detected by the "semantics" > check > (which is why the syntax value is very close to double the number for the > semantic check). To save processing time, please drop the "syntax" check. > Ok. thanks, will be dropped. (for now to disable possible comment out lines 214-221 in checkers_coin.def) Also I forgot to drop old incorrect elvis check. (lines 124-143) > Oh, > > And thanks very much for all your effort on this. > Thanks for good words. Problems are quite funny to justify scheduled time. // Interesting that near 50% of my a priory assumptions about frequency of constructions in Java code was wrong ;) From John.Rose at Sun.COM Wed Apr 29 19:37:01 2009 From: John.Rose at Sun.COM (John Rose) Date: Wed, 29 Apr 2009 19:37:01 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <8D7F16CE-69EB-4742-97E4-2B1E88A222BF@Sun.COM> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <15e8b9d20903290055p399a724al786f34b8188a62d2@mail.gmail.com> <49D013A3.60505@univ-mlv.fr> <8D7F16CE-69EB-4742-97E4-2B1E88A222BF@Sun.COM> Message-ID: <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> I have factored out the Dynamic type from the proposal, leaving a static-only type called InvokeDynamic in its place. Here is the updated spec (also enclosed FTR): http://wikis.sun.com/display/mlvm/ProjectCoinProposal The type java.dyn.InvokeDynamic is a uninstatiable class (like Collections or Arrays) with no apparent methods. However, the compiler treats it has if it had an infinite supply of static methods of all names and signatures, for which it generates invokedynamic instructions instead of invokestatic instructions. By removing the value type Dynamic from the base proposal, we serve the immediate need for system programming on top of JSR 292, while deferring the question (a truly absorbing and important question) of integrating dynamic values with Java's type system. -- John P.S. The factored-out parts, about interface Dynamic and its interesting rules for conversion and method invocation, are placed here: http://wikis.sun.com/display/mlvm/InterfaceDynamic And, should you have an appetite for even more of the same, some rough notes a fuller integration of Java with dynamic types is here: http://wikis.sun.com/display/mlvm/DynamicJava P.P.S. Here is a text-only copy of the basic proposal: -------------- next part -------------- From John.Rose at Sun.COM Wed Apr 29 19:41:41 2009 From: John.Rose at Sun.COM (John Rose) Date: Wed, 29 Apr 2009 19:41:41 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <49D5C7E3.50801@sun.com> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <6F835C91-A2F2-4050-BD03-DB1B462C2B4F@sun.com> <49D5C7E3.50801@sun.com> Message-ID: <2B41E202-273B-4876-BEB4-2C1BADA1A22E@Sun.COM> On Apr 3, 2009, at 1:25 AM, Joseph D. Darcy wrote: > Reiterating a point Neal raised, if Dynamic is not related to Object, > what does that mean when Dynamic is used as the format type argument > to > a type parameter? What do "? extends Dynamic" and "? super Dynamic" > mean to the type system? It means something limited like ? extends String or ? super Object. I.e., there aren't any interesting types other than Dynamic itself that match the wildcard. > Actually there is a special rule that catching Exception is always > okay > per JLS 11.2.3; this program is legal and compiles fine: > > public class Test { > public static void main(String... args){ > try { > ; > } catch (Exception e) { > ; > } > } > } > Thanks. Amending the example to IOError. > > So what are the notions of identity and equality for method handles? Inherited from Object. Nothing special. > [snip] >> 4.1 As specified above, the interface java.dyn.Dynamic has no >> supertypes or members. As such, it is a bare reference type. (As an >> arbitrary relation, the superclass of Dynamic[] is Object[].) We >> > > Are there any other type building operations besides arrays we need to > worry about? I don't think so. List is impossible for interesting reasons. The (erased) implementation of List internally makes use of Object.toString, Object.equals, and perhaps other such methods. These calls are wrong for Dynamic values, since Dynamic (not being a subtype) does not inherit Object.equals and the rest. This allows a Dynamic object to cleanly model another language, without holes in its method namespace. (Consider a process-oriented capability for which the name "wait" is significant, or some knowledge representation language that has different notions about "equals". The MOP doesn't need to special- case those names. It's a small point but worth defending, I think.) (In C#, with reified types, they can customize their List to make a MOP-mediated call to equals, I suppose.) >> But, the Java operators "==" "!=" "+" "+=" on reference types are >> clarified to apply only to reference types which are java.lang.Object >> or one of its subtypes; they do not have a predefined meaning if >> either operand is dynamic. The "synchronized" and "throw" statements >> cannot be applied to dynamic expressions. >> > > So if there is no predefined meaning, are those operations illegal? Yes. More specifically, they are reserved for future use, in case we want to do something with dynamic operator overloading. (There's a half-baked sketch of what this could mean someday, on the mlvm wiki. It's not ready to discuss yet.) >> Facilities which compute type relations (such as >> javax.lang.model.util.Types) may need to be updated to take Dynamic >> into account. Generally speaking, the new Dynamic conversions >> operate >> in parallel to the implicit boxing conversions. That is, they add no >> new subtype or supertype relations, but they provide a few more ways >> for values to be implicitly converted or casted. >> > > Yes, I would expect a few changes to the type-related APIs. They may > also need to be changes to programs that assume Object is the root of > the reference type hierarchy. I know I've written annotation > processing > code like that and Dynamic would need to be special cased in there. Thanks. As noted in the previous message, I have updated the proposal. -- John From neal at gafter.com Wed Apr 29 20:14:44 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 29 Apr 2009 20:14:44 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <15e8b9d20903290055p399a724al786f34b8188a62d2@mail.gmail.com> <49D013A3.60505@univ-mlv.fr> <8D7F16CE-69EB-4742-97E4-2B1E88A222BF@Sun.COM> <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> Message-ID: <15e8b9d20904292014r39b881f2r993bca0d62f8c377@mail.gmail.com> These proposals appears to allow primitives and "void" to be used as generic type arguments for this special class. This use of the syntax has nothing to do with generics. Therefore, I believe it is an abuse of syntax. If you're going to extend the language to support this special InvokeDynamic class, you might as well just define language support for dynamic invocations directly without the magic class and generic extensions. I don't think the current spec for Dynamic fits with the current type system. If you are adding special types like InvokeDynamic, I think they must be reference types (i.e. a subtype of Object). You should try to get some information about what C# has done in this area for "dynamic", as I believe it could be applied to Java and result in a clean solution. By the way, now is a good time to add the boxed "Null" type, which has no instances, referring to the type of null. I don't think this purpose is well served by using java.lang.Void. On Wed, Apr 29, 2009 at 7:37 PM, John Rose wrote: > I have factored out the Dynamic type from the proposal, leaving a > static-only type called InvokeDynamic in its place. Here is the updated > spec (also enclosed FTR): > http://wikis.sun.com/display/mlvm/ProjectCoinProposal > > The type java.dyn.InvokeDynamic is a uninstatiable class (like Collections > or Arrays) with no apparent methods. However, the compiler treats it has if > it had an infinite supply of static methods of all names and signatures, for > which it generates invokedynamic instructions instead of invokestatic > instructions. > > By removing the value type Dynamic from the base proposal, we serve the > immediate need for system programming on top of JSR 292, while deferring the > question (a truly absorbing and important question) of integrating dynamic > values with Java's type system. > > -- John > > P.S. The factored-out parts, about interface Dynamic and its interesting > rules for conversion and method invocation, are placed here: > http://wikis.sun.com/display/mlvm/InterfaceDynamic > > And, should you have an appetite for even more of the same, some rough > notes a fuller integration of Java with dynamic types is here: > http://wikis.sun.com/display/mlvm/DynamicJava > > P.P.S. Here is a text-only copy of the basic proposal: > > > > > > > From rssh at gradsoft.com.ua Wed Apr 29 23:39:01 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Thu, 30 Apr 2009 09:39:01 +0300 (EEST) Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <15e8b9d20903290055p399a724al786f34b8188a62d2@mail.gmail.com> <49D013A3.60505@univ-mlv.fr> <8D7F16CE-69EB-4742-97E4-2B1E88A222BF@Sun.COM> <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> Message-ID: <0a78e808aead077cd9f7cb5c7934fdd9.squirrel@wmail.gradsoft.ua> > http://wikis.sun.com/display/mlvm/ProjectCoinProposal > 2.7 If a class extends MethodHandle, it does not inherit any of the implicitly defined invoke methods... Why not make MethodHandle final ? From Maurizio.Cimadamore at Sun.COM Thu Apr 30 02:55:03 2009 From: Maurizio.Cimadamore at Sun.COM (Maurizio Cimadamore) Date: Thu, 30 Apr 2009 10:55:03 +0100 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <2B41E202-273B-4876-BEB4-2C1BADA1A22E@Sun.COM> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <6F835C91-A2F2-4050-BD03-DB1B462C2B4F@sun.com> <49D5C7E3.50801@sun.com> <2B41E202-273B-4876-BEB4-2C1BADA1A22E@Sun.COM> Message-ID: <49F97577.4090002@sun.com> John Rose wrote: > On Apr 3, 2009, at 1:25 AM, Joseph D. Darcy wrote: > > >> Reiterating a point Neal raised, if Dynamic is not related to Object, >> what does that mean when Dynamic is used as the format type argument >> to >> a type parameter? What do "? extends Dynamic" and "? super Dynamic" >> mean to the type system? >> > > It means something limited like ? extends String or ? super Object. > I.e., there aren't any interesting types other than Dynamic itself > that match the wildcard. > > 1) I'd strongly recommend to forbid usage of InvokeDynamic type in the following contexts: (i) extends clause (e.g. class MyDynamic extends InvokeDynamic) (ii) type-parameter bound (e.g. class Foo>) (iii) wildcard type-argument (e.g. FoomyDynMethod("Hello!"); // type (String) -> String Can this optional type argument be inferred so that the following method call will behave identically? int i = InvokeDynamic.myDynMethod("Hello!"); // type (String) -> String [I did some testing and it seems like inference is not supported - the above line will give an incompatible types error, found Object, expecetd int] If so, you are mimicking an under-constrained type-variable (a method type variable that cannot be inferred from actual arguments passed to the method). This raises a question: what happens when the dynamic call site does not appear within an assignment context, e.g. InvokeDynamic.myDynMethod("Hello!"); or int i = (Integer)InvokeDynamic.myDynMethod("Hello!"); In those cases, following 15.12.2.8, the under-constrained type variable should be inferred to be its declared bound. What does it mean in this case? Object ? Null ? Reading from your examples it seems like if no optional type-argument for the return type is provided, no info about the return type is included in the MethodHandle type generated by javac. Which means that this behavior cannot be explained in terms of generic method call/type inference (and thus 15.12.2.7/15.12.2.8). An alternative would be to pass to InvokeDynamic the return type Class object corresponding the to expected return type as the first parameter of the dynamic call: InvokeDynamic.myDynMethod(int.class, "Hello!"); // type (String) -> int This has the advantage of not requiring a separate language extension in order to allow primitive type (and void) to be specified as parameter types. Maurizio >> Actually there is a special rule that catching Exception is always >> okay >> per JLS 11.2.3; this program is legal and compiles fine: >> >> public class Test { >> public static void main(String... args){ >> try { >> ; >> } catch (Exception e) { >> ; >> } >> } >> } >> >> > > Thanks. Amending the example to IOError. > > >> So what are the notions of identity and equality for method handles? >> > > Inherited from Object. Nothing special. > > >> [snip] >> >>> 4.1 As specified above, the interface java.dyn.Dynamic has no >>> supertypes or members. As such, it is a bare reference type. (As an >>> arbitrary relation, the superclass of Dynamic[] is Object[].) We >>> >>> >> Are there any other type building operations besides arrays we need to >> worry about? >> > > I don't think so. > > List is impossible for interesting reasons. The (erased) > implementation of List internally makes use of Object.toString, > Object.equals, and perhaps other such methods. These calls are wrong > for Dynamic values, since Dynamic (not being a subtype) does not > inherit Object.equals and the rest. This allows a Dynamic object to > cleanly model another language, without holes in its method namespace. > > (Consider a process-oriented capability for which the name "wait" is > significant, or some knowledge representation language that has > different notions about "equals". The MOP doesn't need to special- > case those names. It's a small point but worth defending, I think.) > > (In C#, with reified types, they can customize their List to > make a MOP-mediated call to equals, I suppose.) > > >>> But, the Java operators "==" "!=" "+" "+=" on reference types are >>> clarified to apply only to reference types which are java.lang.Object >>> or one of its subtypes; they do not have a predefined meaning if >>> either operand is dynamic. The "synchronized" and "throw" statements >>> cannot be applied to dynamic expressions. >>> >>> >> So if there is no predefined meaning, are those operations illegal? >> > > Yes. More specifically, they are reserved for future use, in case we > want to do something with dynamic operator overloading. > > (There's a half-baked sketch of what this could mean someday, on the > mlvm wiki. It's not ready to discuss yet.) > > >>> Facilities which compute type relations (such as >>> javax.lang.model.util.Types) may need to be updated to take Dynamic >>> into account. Generally speaking, the new Dynamic conversions >>> operate >>> in parallel to the implicit boxing conversions. That is, they add no >>> new subtype or supertype relations, but they provide a few more ways >>> for values to be implicitly converted or casted. >>> >>> >> Yes, I would expect a few changes to the type-related APIs. They may >> also need to be changes to programs that assume Object is the root of >> the reference type hierarchy. I know I've written annotation >> processing >> code like that and Dynamic would need to be special cased in there. >> > > Thanks. > > As noted in the previous message, I have updated the proposal. > > -- John > > From forax at univ-mlv.fr Thu Apr 30 12:07:50 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 30 Apr 2009 21:07:50 +0200 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <49F97577.4090002@sun.com> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <6F835C91-A2F2-4050-BD03-DB1B462C2B4F@sun.com> <49D5C7E3.50801@sun.com> <2B41E202-273B-4876-BEB4-2C1BADA1A22E@Sun.COM> <49F97577.4090002@sun.com> Message-ID: <49F9F706.3030909@univ-mlv.fr> The first question is what is the goal of such construct. If the goal is to be able to call any dynamic languages from Java, this is in my opinion a nice dream but that means mixing different language semantics. If the goal is to help dynamic language developers, the question is why a language developer code in Java and not in its own language. If the goal is to simplify reflection or dynamic invocation in Java, the dynamic type of C# is what we want. R?mi Maurizio Cimadamore a ?crit : > John Rose wrote: > >> On Apr 3, 2009, at 1:25 AM, Joseph D. Darcy wrote: >> >> >> >>> Reiterating a point Neal raised, if Dynamic is not related to Object, >>> what does that mean when Dynamic is used as the format type argument >>> to >>> a type parameter? What do "? extends Dynamic" and "? super Dynamic" >>> mean to the type system? >>> >>> >> It means something limited like ? extends String or ? super Object. >> I.e., there aren't any interesting types other than Dynamic itself >> that match the wildcard. >> >> >> > 1) I'd strongly recommend to forbid usage of InvokeDynamic type in the > following contexts: > > (i) extends clause (e.g. class MyDynamic extends InvokeDynamic) > (ii) type-parameter bound (e.g. class Foo Comparable>) > (iii) wildcard type-argument (e.g. Foo > While generics/wildcards are essentially a way to refine static > type-checking, InvokeDynamic provides a way to disable static checking > completely. For this reason I don't see the two features going side by > side in any meaningful way. It is true that now that InvokeDynamic has > become an abstract holder of static methods, it probably makes less > sense to write code like the above (apart from (i) which users might be > tempted to write) - nevertheless the compiler should detect such invalid > usages and flag them as errors. > > My point is that a Java class shouldn't ever need to be parameterized on > something that is bound by InvokeDynamic (or Dynamic) - as those types > do not provide the type-system with any info. > > 2) I agree with Neal that the usage of Void feels a bit hacky. If you > need null values to be typed differently then I agree that probably > adding java.lang.Null would be the best thing to do, rather than > overriding the semantics of Void. > > 3) InvokeDynamic and type-inference. It seems like you can optionally > provide a type-parameter denoting the dynamic call's expected return > type. This is fine, as long as it is consistent with JLS 15.12.2.7 and > 15.12.2.8. In your examples it seems like the usage of such type > argument is completely optional. If specified, it provides additional > info about the dynamic call site such that, e.g. the following code will > be rejected: > > int i = InvokeDynamic.myDynMethod("Hello!"); // type (String) -> > String > > Can this optional type argument be inferred so that the following method > call will behave identically? > > int i = InvokeDynamic.myDynMethod("Hello!"); // type (String) -> String > > [I did some testing and it seems like inference is not supported - the > above line will give an incompatible types error, found Object, expecetd > int] > > If so, you are mimicking an under-constrained type-variable (a method > type variable that cannot be inferred from actual arguments passed to > the method). This raises a question: what happens when the dynamic call > site does not appear within an assignment context, e.g. > > InvokeDynamic.myDynMethod("Hello!"); > > or > > int i = (Integer)InvokeDynamic.myDynMethod("Hello!"); > > In those cases, following 15.12.2.8, the under-constrained type variable > should be inferred to be its declared bound. What does it mean in this > case? Object ? Null ? Reading from your examples it seems like if no > optional type-argument for the return type is provided, no info about > the return type is included in the MethodHandle type generated by javac. > Which means that this behavior cannot be explained in terms of generic > method call/type inference (and thus 15.12.2.7/15.12.2.8). > > An alternative would be to pass to InvokeDynamic the return type Class > object corresponding the to expected return type as the first parameter > of the dynamic call: > > InvokeDynamic.myDynMethod(int.class, "Hello!"); // type (String) -> int > > This has the advantage of not requiring a separate language extension in > order to allow primitive type (and void) to be specified as parameter types. > > Maurizio > >>> Actually there is a special rule that catching Exception is always >>> okay >>> per JLS 11.2.3; this program is legal and compiles fine: >>> >>> public class Test { >>> public static void main(String... args){ >>> try { >>> ; >>> } catch (Exception e) { >>> ; >>> } >>> } >>> } >>> >>> >>> >> Thanks. Amending the example to IOError. >> >> >> >>> So what are the notions of identity and equality for method handles? >>> >>> >> Inherited from Object. Nothing special. >> >> >> >>> [snip] >>> >>> >>>> 4.1 As specified above, the interface java.dyn.Dynamic has no >>>> supertypes or members. As such, it is a bare reference type. (As an >>>> arbitrary relation, the superclass of Dynamic[] is Object[].) We >>>> >>>> >>>> >>> Are there any other type building operations besides arrays we need to >>> worry about? >>> >>> >> I don't think so. >> >> List is impossible for interesting reasons. The (erased) >> implementation of List internally makes use of Object.toString, >> Object.equals, and perhaps other such methods. These calls are wrong >> for Dynamic values, since Dynamic (not being a subtype) does not >> inherit Object.equals and the rest. This allows a Dynamic object to >> cleanly model another language, without holes in its method namespace. >> >> (Consider a process-oriented capability for which the name "wait" is >> significant, or some knowledge representation language that has >> different notions about "equals". The MOP doesn't need to special- >> case those names. It's a small point but worth defending, I think.) >> >> (In C#, with reified types, they can customize their List to >> make a MOP-mediated call to equals, I suppose.) >> >> >> >>>> But, the Java operators "==" "!=" "+" "+=" on reference types are >>>> clarified to apply only to reference types which are java.lang.Object >>>> or one of its subtypes; they do not have a predefined meaning if >>>> either operand is dynamic. The "synchronized" and "throw" statements >>>> cannot be applied to dynamic expressions. >>>> >>>> >>>> >>> So if there is no predefined meaning, are those operations illegal? >>> >>> >> Yes. More specifically, they are reserved for future use, in case we >> want to do something with dynamic operator overloading. >> >> (There's a half-baked sketch of what this could mean someday, on the >> mlvm wiki. It's not ready to discuss yet.) >> >> >> >>>> Facilities which compute type relations (such as >>>> javax.lang.model.util.Types) may need to be updated to take Dynamic >>>> into account. Generally speaking, the new Dynamic conversions >>>> operate >>>> in parallel to the implicit boxing conversions. That is, they add no >>>> new subtype or supertype relations, but they provide a few more ways >>>> for values to be implicitly converted or casted. >>>> >>>> >>>> >>> Yes, I would expect a few changes to the type-related APIs. They may >>> also need to be changes to programs that assume Object is the root of >>> the reference type hierarchy. I know I've written annotation >>> processing >>> code like that and Dynamic would need to be special cased in there. >>> >>> >> Thanks. >> >> As noted in the previous message, I have updated the proposal. >> >> -- John >> >> >> > > > From rssh at gradsoft.com.ua Thu Apr 30 12:56:56 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Thu, 30 Apr 2009 22:56:56 +0300 (EEST) Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <49F9F706.3030909@univ-mlv.fr> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <6F835C91-A2F2-4050-BD03-DB1B462C2B4F@sun.com> <49D5C7E3.50801@sun.com> <2B41E202-273B-4876-BEB4-2C1BADA1A22E@Sun.COM> <49F97577.4090002@sun.com> <49F9F706.3030909@univ-mlv.fr> Message-ID: > > If the goal is to help dynamic language developers, > the question is why a language developer code in Java > and not in its own language. > This is for language developers, which want translate their language expressions to bytecode via java as first set (as cfront compiler, which translate C++ programs to C, not to native code). I. e. Java in such case is 'C' for JVM. From Alex.Buckley at Sun.COM Thu Apr 30 15:15:08 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Thu, 30 Apr 2009 15:15:08 -0700 Subject: Points about language support for 292 Message-ID: <49FA22EC.6070208@sun.com> Hi John, 1.1: "The complete lack of supertypes makes it an unusual type, on a par with Object." But InvokeDynamic is defined as a class with a superclass of Object a few lines earlier. The text in () looks redundant. 1.5: As the JVM executes, checked exceptions may be produced by any invokedynamic call. Please don't put "JVM" and "checked exceptions" in the same sentence! More importantly, I don't agree with "the possibility of a missed catch of a checked exception is not considered to be a hazard." An exception handler further up the stack that catches unchecked exceptions will miss it, and the program will in all likelihood stop. In other words, this is a relaxation too far of static exception checking. One option is to have InvokeDynamic.foo() claim to throw all possible checked exceptions. If one actually leaks back to the call site from a dynamic language's runtime, it should be caught right there. Another option, and perhaps a better one since it partitions InvokeDynamic off from checked exceptions entirely, is to specify that its infinite static methods can throw only unchecked exceptions (or one in particular, if you like). An implementation would have to wrap checked exceptions. Neal: InvokeDynamic IS now a reference type. Regarding <..> to indicate return type for a dynamic call site, how does C# denote that? Alex From neal at gafter.com Thu Apr 30 15:23:59 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 30 Apr 2009 15:23:59 -0700 Subject: Points about language support for 292 In-Reply-To: <49FA22EC.6070208@sun.com> References: <49FA22EC.6070208@sun.com> Message-ID: <15e8b9d20904301523y7c381671oba6328fcd5c91893@mail.gmail.com> On Thu, Apr 30, 2009 at 3:15 PM, Alex Buckley wrote: > Neal: InvokeDynamic IS now a reference type. Regarding <..> to indicate > return type for a dynamic call site, how does C# denote that? It doesn't. A dynamic invocation, from the point of view of C#, returns a value of type dynamic. The hoped-for return type isn't encoded into the invocation. -Neal From Alex.Buckley at Sun.COM Thu Apr 30 15:55:11 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Thu, 30 Apr 2009 15:55:11 -0700 Subject: Points about language support for 292 In-Reply-To: <15e8b9d20904301523y7c381671oba6328fcd5c91893@mail.gmail.com> References: <49FA22EC.6070208@sun.com> <15e8b9d20904301523y7c381671oba6328fcd5c91893@mail.gmail.com> Message-ID: <49FA2C4F.7060800@sun.com> Neal Gafter wrote: > On Thu, Apr 30, 2009 at 3:15 PM, Alex Buckley > wrote: > > Neal: InvokeDynamic IS now a reference type. Regarding <..> to indicate > return type for a dynamic call site, how does C# denote that? > > It doesn't. A dynamic invocation, from the point of view of C#, returns > a value of type dynamic. The hoped-for return type isn't encoded into > the invocation. The utility of a Dynamic type is high. The utility of values of Dynamic type is not high, in my view. Coin's support for 292 is limited, and does not include general manipulation of non-Java objects in the Java language. I respect that you believe the time has come for general manipulation of non-C# objects in the C# language. Alex From vapor1 at teleport.com Thu Apr 30 20:59:10 2009 From: vapor1 at teleport.com (Derek Foster) Date: Thu, 30 Apr 2009 23:59:10 -0400 (EDT) Subject: PROPOSAL: Binary literals (Version 2) Message-ID: <38933.1241150350273.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> This is a minor revision of my original proposal. It has been revised to add more examples and discussion of the various alternative attempts to solve the problems that this proposal is intended to address. Add binary literals to Java. (Version 2) AUTHOR(S): Derek Foster OVERVIEW In some programming domains, use of binary numbers (typically as bitmasks, bit-shifts, etc.) is very common. In particular, this type of usage may often be needed in low-level programming such as is typical in severely resource constrained devices such as J2ME, JavaCard, or JavaRing, although it can come up in a variety of larger-scale contexts as well, such as programming to match network packet protocols, compression algorithms, encryption algorithms, and so forth. However, Java code has traditionally forced programmers to represent numbers in only decimal, octal, or hexadecimal. (In practice, octal is rarely used, and is present mostly for backwards compatibility with C) When the data being dealt with is fundamentally bit-oriented, however, using hexadecimal to represent ranges of bits requires an extra degree of mental translation for the programmer, and this can often become a source of errors. For instance, if a technical specification lists specific values in binary (for example, in a compression encoding algorithm or in the specifications for a network protocol, or for communicating with a bitmapped hardware device) then a programmer coding to that specification must translate each key from its binary representation into hexadecimal. Checking to see if this translation has been done correctly is usually accomplished by back-translating the numbers. In most cases, programmers do these translations in their heads, and HOPEFULLY get them right. however, errors can easily creep in. Furthermore, in many cases, the binary representations of numbers makes it much more clear what is actually intended. For instance this: private static final int BITMASK = 0x1E; does not immediately make it clear that the bitmask being declared comprises a single contiguous range of four bits. In many cases, it would be more natural for the programmer to be able to write the numbers in binary in the source code, eliminating the need for manual translation entirely. FEATURE SUMMARY: In addition to the existing "1" (decimal), "01" (octal) and "0x1" (hexadecimal) form of specifying numeric literals, a new form "0b1" (binary) would be added. Note that this is the same syntax as has been used as an extension by the GCC C/C++ compilers for many years, and also is used in the Ruby language, as well as in the Python language. MAJOR ADVANTAGE: It is no longer necessary for programmers to translate binary numbers to and from hexadecimal in order to use them in Java programs. MAJOR BENEFIT: Code using bitwise operations is more readable and easier to verify against technical specifications that use binary numbers to specify constants. MAJOR DISADVANTAGE: Someone might incorrectly think that "0b1" represented the same value as hexadecimal number "0xB1". However, note that this problem has existed for octal/decimal for many years (confusion between "050" and "50") and does not seem to be a major issue. Also, it does not seem to be a major concern in the programming languages in which this construct already exists. (see below) ALTERNATIVES: Users could continue to write the numbers as decimal, octal, or hexadecimal, and would continue to have the problems observed in this document. Alternately, code could be written to translate at runtime from binary strings, such as: int value = Integer.parseInt("00001110", 2) & (Integer.parseInt("00101110", 2) << amount); There are several problems with this style of coding: * First of all, the code is significantly more verbose than it would be if it were not written to use library calls. The basic purpose of the operation (number & (number << amount)) is obscured by the clutter associated with calling a library routine. This makes the code difficult to read at a glance. * There is a significant performance penalty. The call to Integer.parseInt takes significantly more execution time than simply using an integer constant would. This time can be a significant barrier in a resource-constrained device which may have a slow clock speed. Also, if this line of code is occurring in a tight loop (as is common in low-level programming), this extra time may have a dramatic effect on how long it takes to iterate through the loop, since this performance penalty has to be paid each time the line of code is executed, rather than just once, at compile time. * Calling a method such as Integer.parseInt at runtime will typically make it impossible for the compiler to inline the value of this constant, since its value has been taken from a runtime method call. Inlining is important, because code that does bitwise parsing is often very low-level code in tight loops that must execute quickly. (This is particularly the case for mobile applications and other applications that run on severely resource-constrained environments, where a JIT compiler like HotSpot is not an option.) * Values which are returned from evaluating methods at runtime cannot be used as selectors in 'switch' statements. A Java compiler won't allow code like this: switch (foo) { case Binary.parseInt("000"): doThis(); break; case Binary.parseInt("001"): doThat(); break; ... } * Any errors in the string to be parsed (for instance, an extra space, confusion of alphabetic 'O' with numeric '0', etc.) will result in runtime exceptions, rather than compile-time errors as would have occurred in normal parsing. If such a value is declared 'static', this will result in some very ugly exceptions at runtime. Also, the application will then need to be written to handle these errors at runtime, when in principle they could all have been detected at compile time. * Classes java.lang.Integer and java.lang.String simply do not exist for a number of low-level Java platforms, such as JavaCard and JavaRing, since these platforms are used for low-level number crunching and do not normally have need of such high-level constructs. [Note: It might be possible for a compiler to synthesize these classes (basically, to pretend they existed at compile time but were optimized away at runtime due to method inlining). However, this would require a substantial effort on behalf of the compiler team and essentially the introduction of a new programming paradigm (the "exists only at compile time" class). The issues of code verbosity as well as how to handle possible exceptions that might be thown by these methods at would remain.] * Similarly, throwing of exceptions is often not supported in resource-constrained environments. * It is possible to address the code verbosity issue in the above code (by, for instance, creating a library method with a shorter name and taking only one argument), or the performance issue (by creating static named constants with the necessary values), but it is not possible to simultaneously address both issues in Java as it is currently defined. EXAMPLES: // An 8-bit 'byte' literal. byte aByte = (byte)0b00100001; // A 16-bit 'short' literal. short aShort = (short)0b1010000101000101; // Some 32-bit 'int' literals. int anInt1 = 0b10100001010001011010000101000101; int anInt2 = 0b101; int anInt3 = 0B101; // The B can be upper or lower case as per the x in "0x45". // A 64-bit 'long' literal. Note the "L" suffix. long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L; SIMPLE EXAMPLE: class Foo { public static void main(String[] args) { System.out.println("The value 10100001 in decimal is " + 0b10100001); } ADVANCED EXAMPLE: // Boolean constants could be used in code that needs to be // easily checkable against a specifications document, such // as this simulator for a hypothetical 8-bit microprocessor: public State decodeInstruction(int instruction, State state) { if ((instruction & 0b11100000) == 0b00000000) { final int register = instruction & 0b00001111; switch (instruction & 0b11110000) { case 0b00000000: return state.nop(); case 0b00010000: return state.copyAccumTo(register); case 0b00100000: return state.addToAccum(register); case 0b00110000: return state.subFromAccum(register); case 0b01000000: return state.multiplyAccumBy(register); case 0b01010000: return state.divideAccumBy(register); case 0b01100000: return state.setAccumFrom(register); case 0b01110000: return state.returnFromCall(); default: throw new IllegalArgumentException(); } } else { final int address = instruction & 0b00011111; switch (instruction & 0b11100000) { case 0b00100000: return state.jumpTo(address); case 0b01000000: return state.jumpIfAccumZeroTo(address); case 0b01000000: return state.jumpIfAccumNonzeroTo(address); case 0b01100000: return state.setAccumFromMemory(address); case 0b10100000: return state.writeAccumToMemory(address); case 0b11000000: return state.callTo(address); default: throw new IllegalArgumentException(); } } } // Binary literals can be used to make a bitmap more readable: public static final short[] HAPPY_FACE = { (short)0b0000011111100000; (short)0b0000100000010000; (short)0b0001000000001000; (short)0b0010000000000100; (short)0b0100000000000010; (short)0b1000011001100001; (short)0b1000011001100001; (short)0b1000000000000001; (short)0b1000000000000001; (short)0b1001000000001001; (short)0b1000100000010001; (short)0b0100011111100010; (short)0b0010000000000100; (short)0b0001000000001000; (short)0b0000100000010000; (short)0b0000011111100000; } // Binary literals can make relationships // among data more apparent than they would // be in hex or octal. // // For instance, what does the following // array contain? In hexadecimal, it's hard to tell: public static final int[] phases = { 0x31, 0x62, 0xC4, 0x89, 0x13, 0x26, 0x4C, 0x98 } // In binary, it's obvious that a number is being // rotated left one bit at a time. public static final int[] phases = { 0b00110001, 0b01100010, 0b11000100, 0b10001001, 0b00010011, 0b00100110, 0b01001100, 0b10011000, } DETAILS SPECIFICATION: Section 3.10.1 ("Integer Literals") of the JLS3 should be changed to add the following: IntegerLiteral: DecimalIntegerLiteral HexIntegerLiteral OctalIntegerLiteral BinaryIntegerLiteral // Added BinaryIntegerLiteral: BinaryNumeral IntegerTypeSuffix_opt BinaryNumeral: 0 b BinaryDigits 0 B BinaryDigits BinaryDigits: BinaryDigit BinaryDigit BinaryDigits BinaryDigit: one of 0 1 COMPILATION: Binary literals would be compiled to class files in the same fashion as existing decimal, hexadecimal, and octal literals are. No special support or changes to the class file format are needed. TESTING: The feature can be tested in the same way as existing decimal, hexadecimal, and octal literals are: Create a bunch of constants in source code, including the maximum and minimum positive and negative values for integer and long types, and verify them at runtime to have the correct values. LIBRARY SUPPORT: The methods Integer.decode(String) and Long.decode(String) should be modified to parse binary numbers (as specified above) in addition to their existing support for decimal, hexadecimal, and octal numbers. REFLECTIVE APIS: No updates to the reflection APIs are needed. OTHER CHANGES: No other changes are needed. MIGRATION: Individual constants in decimal, hexadecimal, or octal can be updated to binary as a programmer desires. COMPATIBILITY: BREAKING CHANGES: This feature would not break any existing programs, since the suggested syntax is currently considerd to be a compile-time error. EXISTING PROGRAMS: Class file format does not change, so existing programs can use class files compiled with the new feature without problems. REFERENCES: The GCC/G++ compiler, which already supports this syntax (as of version 4.3) as an extension to standard C/C++. http://gcc.gnu.org/gcc-4.3/changes.html The Ruby language, which supports binary literals: http://wordaligned.org/articles/binary-literals The Python language added binary literals in version 2.6: http://docs.python.org/dev/whatsnew/2.6.html#pep-3127-integer-literal-support-and-syntax EXISTING BUGS: "Language support for literal numbers in binary and other bases" http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5025288 URL FOR PROTOTYPE (optional): None. From vapor1 at teleport.com Thu Apr 30 21:01:35 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 1 May 2009 00:01:35 -0400 (EDT) Subject: PROPOSAL: Underscores in Numbers (Version 2) Message-ID: <24587044.1241150495473.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Per feedback on the Project Coin mailing list, the following proposal has been revised to disallow placing underscores at the beginning or end of a sequence of digits within a number. I have also revised the value used for the "alsoMaxLong" example (as it was previously illegal), as well as the other examples showing where underscores can/cannot be placed. AUTHOR(S): Derek Foster OVERVIEW In Java, currently, numbers of various types currently are expressed in their pure form, as a long string of digits possibly interspersed with other punctuation (periods, an exponent specifier, etc.) needed to separate distinct sections of the number. While this is easy for a compiler to process, it is often difficult for a human being to visually parse. The ability of a human to visually separate separate items tops out somewhere near "seven plus or minus two" items. Research done by telephone companies suggests that for many practical purposes, the longest string of numbers an average human can successfully hold in memory at a time is around three or four. Also, it is difficult for the human eye to find common positions in numbers that have no break in their visual structure. As a result, most numbers that humans deal with in day-to-day life have separators included in them to break the long sequence of digits into manageable chunks that are easy to deal with as separate entities. This includes items such as (apologies to non-USA readers...): Phone numbers: 555-555-1212 Credit card numbers: 1234-5678-9012-3456 Social security numbers: 999-99-9999 Monetary amounts: $12,345,132.12 and a wide variety of other types of numbers. However, Java provides no way to add these kinds of visual separators into a number. Java expects the number to be essentially an unbroken string of digits. This proposal suggests that Java follow the lead of the Ruby programming language in allowing the underscore character to be inserted into numbers in most positions, for readability purposes. FEATURE SUMMARY: Java numeric literals will allow underscores to be placed in (nearly) arbitrary positions within the number, at the programmer's discretion, for readability purposes. These underscores shall be ignored by the compiler for the purposes of code generation. MAJOR ADVANTAGE: Programmers won't have to visually parse long strings of digits (a task humans are quite poor at). The internal digit-oriented structure of many numbers can be made more clear. MAJOR BENEFIT: Increased readability of code. MAJOR DISADVANTAGE: The number parsers in the Java compiler would have to be adjusted to parse and ignore the underscores. This is a small amount of effort, but nonzero. There might also be some small performance impact. If someone were to use this feature inappropriately, it could result in difficult to read code. ALTERNATIVES: Do without separators in numbers, or use some other character for them. EXAMPLES SIMPLE EXAMPLE: Show the simplest possible program utilizing the new feature. int phoneNumber = 555_555_1212; ADVANCED EXAMPLE: long creditCardNumber = 1234_5678_9012_3456L; long socialSecurityNumbers = 999_99_9999L; float monetaryAmount = 12_345_132.12; long hexBytes = 0xFF_EC_DE_5E; long hexWords = 0xFFEC_DE5E; long maxLong = 0x7fff_ffff_ffff_ffffL; long alsoMaxLong = 9_223_372_036_854_775_807L; double whyWouldYouEverDoThis = 0x1_.ffff_ffff_ffff_fp10_23; (Additionally, if binary literals are ever added to the Java language, the following might also be possible... byte nybbles = 0b0010_0101; long bytes = 0b11010010_01101001_10010100_10010010; int weirdBitfields = 0b000_10_101; ) Note that according to this proposal, underscores can only be placed between digits. They cannot be placed by themselves in positions where a string of digits would normally be expected: int x1 = _52; // This is an identifier, not a numeric literal. int x2 = 5_2; // OK. (Decimal literal) int x2 = 52_; // Illegal. (Underscores must always be between digits) int x3 = 5_______2; // OK. (Decimal literal.) int x4 = 0_x52; // Illegal. Can't put underscores in the "0x" radix prefix. int x5 = 0x_52; // Illegal. (Underscores must always be between digits) int x6 = 0x5_2; // OK. (Hexadecimal literal) int x6 = 0x52_; // Illegal. (Underscores must always be between digits) int x6 = 0x_; // Illegal. (Not valid with the underscore removed) int x7 = 0_52; // OK. (Octal literal) int x7 = 05_2; // OK. (Octal literal) int x8 = 052_; // Illegal. (Underscores must always be between digits) DETAILS SPECIFICATION: DECIMALS: Section 3.10.1 ("Integer Literals") of the Java Language Specification 3rd edition shall be modified like so: Underscores: _ _ Underscores DecimalNumeral: 0 NonZeroDigit Underscores_opt DigitsAndUnderscores_opt DigitsAndUnderscores: Digit DigitsAndUnderscores Underscores_opt Digit Digit: 0 NonZeroDigit NonZeroDigit: one of 1 2 3 4 5 6 7 8 9 HexNumeral: 0 x HexDigitsAndUnderscores 0 X HexDigitsAndUnderscores HexDigitsAndUnderscores: HexDigit HexDigit Underscores_opt HexDigitsAndUnderscores HexDigit: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F OctalNumeral: 0 OctalDigitsAndUnderscores OctalDigitsAndUnderscores: OctalDigit OctalDigit Underscores_opt OctalDigitsAndUnderscores OctalDigit: one of 0 1 2 3 4 5 6 7 Section 3.10.2 ("Floating-Point Literals") would be modified as follows: FloatingPointLiteral: DecimalFloatingPointLiteral HexadecimalFloatingPointLiteral DecimalFloatingPointLiteral: DigitsAndUnderscores_opt . DigitsAndUnderscores_opt ExponentPart_opt FloatTypeSuffix_opt . DigitsAndUnderscores ExponentPartopt FloatTypeSuffix_opt DigitsAndUnderscores_opt ExponentPart FloatTypeSuffix_opt DigitsAndUnderscores_opt ExponentPart_opt FloatTypeSuffix ExponentPart: ExponentIndicator SignedInteger ExponentIndicator: one of e E SignedInteger: Sign_opt DigitsAndUnderscores Sign: one of + - FloatTypeSuffix: one of f F d D HexadecimalFloatingPointLiteral: HexSignificand BinaryExponent FloatTypeSuffix_opt HexSignificand: HexNumeral HexNumeral . 0x HexDigitsAndUnderscores_opt . HexDigitsAndUnderscores 0X HexDigitsAndUnderscores_opt . HexDigitsAndUnderscores BinaryExponent: BinaryExponentIndicator SignedInteger BinaryExponentIndicator:one of p P COMPILATION: Numbers containing underscores are to be parsed and evaluated by the compiler exactly as if the underscores were not present. The above grammar ensures that removing underscores will not result in an unparseable number. A simple strategy for achieving this is that once a number has been parsed by the compiler lexer and determined to be syntactically valid according to the above grammar, then if the number contains any underscores, then all underscores in it may be removed (by something as simple as numberAsString.replaceAll("_","")) before passing the number on to the code that would normally have parsed the number prior to this proposal. More performant approaches are certainly possible. TESTING: How can the feature be tested? A variety of literals may be generated, of the cross product of each of the following radicies: hex, decimal, octal with each of the following types: byte, char, short, int, long, float, double such that for each possible numeric field in the result, that one or more underscores are inserted at the beginning, in the middle, and at the end of the digits. Note that the above grammar is specifically designed to disallow any underscores from appearing which are not either preceded by or followed by a digit. LIBRARY SUPPORT: Methods such as Integer.decode(String) and Long.decode(String) should probably be updated to ignore underscores in their inputs, since these methods attempt to parse according to Java conventions. I suggest that methods such as Integer.parseInt(), Float.parseFloat(), etc. should probably NOT be updated to ignore underscores, since these methods deal with numbers in their pure form, and are more focused and much more widely used. To alter them to ignore underscores would introduce ambiguity in (and have a performance impact on) various parsing code that uses them. REFLECTIVE APIS: No changes to reflective APIs are needed. OTHER CHANGES: No other changes are needed. MIGRATION: Underscores can be inserted into numbers within an existing code base as desired for readability. COMPATIBILITY BREAKING CHANGES: Since use of underscores within numbers was previously a syntax error, this should not break any existing programs. EXISTING PROGRAMS: This feature does not affect the format of class files. It is purely a notational convenience. Hence, interaction with existing class files would not be affected. REFERENCES EXISTING BUGS: A search of the Bug Database did not find any bug ID's related to this proposal. URL FOR PROTOTYPE (optional): None. From vapor1 at teleport.com Thu Apr 30 23:20:07 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 1 May 2009 02:20:07 -0400 (EDT) Subject: PROPOSAL: Abstract enums (version 2) Message-ID: <24400889.1241158807692.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Per feedback on the Project Coin mailing list, this proposal has been revised to provide more detail about how abstract enums affect serialization, class file format, the 'switch' statement, and 'Class.isEnum()', as well as additional text making more explicit the fact that this proposal is substantially different in both intent and implementation from various "extensible enums" proposals that have been considered and rejected in the past by the enum working group. AUTHOR: Derek Foster OVERVIEW The Java Enumerated type feature is unlike similar features in any other language which preceded it. In prior languages, an enumerated type was simply a collection of integer constants. In contrast, Java's enumerated type is a rich datatype that has more in common with classes than it has with a simple constants. Enumerated types can contain complex data, as well as methods to operate on that data. Individual enumerators may be subclasses of the enumeration class that contains them, and may override methods to provide enumerator-specific behavior. Unfortunately, there is one striking difference between Java's enumerations and classes that can become a significant inconvenience: While classes allow use of a superclass to hold data and methods which are shared between a variety of subclasses, Java enumerations have no such feature. In particular, every Java enumerated type must explicitly specify all of its data and methods that are not inherited from the base class Enum. If there are a number of enumerations that share related behavior, each enumeration must specify it redundantly. The only way to share behavior between these enumerations is to manually implement use delegation. Note that the term "abstract enum" is somewhat imprecise, and has historically been interpreted (in particular, by the team responsible for defining how to add enumerated types to Java) to refer to a different concept than the one that is specified by this proposal. Specifically, the "extendable enums" approach, in which an abstract enumerated type which declares enumeration constants could be extended by another enumerated type which declares additional constants. Since there seems to have been some confusion on this point, I wish to specifically point out that the interpretation of the phrase "abstract enum" as it is used in this proposal is quite different from that assumed by the "extensible enums" feature that has been considered (and rejected) in the past. The extensible enums proposal was an attempt to define behavior of concrete subtypes of concrete enumerated types. This proposal, on the other hand, attempts to define the behavior of abstract uninstantiable supertypes of enumerated types. The focus of this proposal is not on adding "interface"-related features to enums -- it is on implementation sharing. As such, it is specifically designed to avoid the implementation and specification problems (difficulty with serialization, switch statements, etc.) that have given the phrase "abstract enums" a bad name in the past. For instance, imagine a system in which enumerations are used to access columns of tables in a relational database. There might be one enumeration for each table, and the enumerators of each type might represent the columns in that table. Presumably, each enumerator would contain the name of the table, as well as the name of a specific column, and perhaps other metadata, such as access privileges. It would seem natural to model such a system like this: enum Access { PUBLIC, PRIVATE }; /** * This holds the shared definition of what it means * to be a database table column identifier */ abstract enum TableColumnDef { // Note: No enum constants are declared here! // This is just a supertype! private String tableName; private String columnName; private Access access; protected TableColumnDef(String tablename, String columnName, Access access) { this.tableName = tableName; this.columnName = columnName; this.access = access; } public String getTableName() { return tableName; } public String getColumnName() { return columnName; } public Access getAccess() { return access; } @Override final String toString() { return tableName + "." + columnName; } } /** A specific table */ enum PersonTable extends TableColumnDef { NAME_COLUMN("Name", Access.PUBLIC), AGE_COLUMN("Age", Access.PRIVATE), WEIGHT_COLUMN("Weight", ACCESS.PUBLIC); private PersonTable(String columnName, Access access) { super("PersonTable", columnName, access); } } /** Another specific table */ enum PetTable extends TableColumnDef { PETNAME_COLUMN("PetName", Access.PUBLIC), SPECIES_COLUMN("Species", Access.PUBLIC); private PersonTable(String columnName, Access access) { super("PetTable", columnName, access); } } However, this cannot be done in Java, because inheritance from user-specified abstract types is not supported for enumerated types. (The only abstract type that is considered legal to inherit from is Enum). The closest equivalent in Java as it currently exists is to model the desired system is something like this, using delegation instead of inheritance: class TableEnumGuts { private String tableName; private String columnName; private Access access; protected DatabaseEnum(String tablename, String columnName, Access access) { this.tableName = tableName; this.columnName = columnName; this.access = access; } public String getTableName() { return tableName; } public String getColumnName() { return columnName; } public Access getAccess() { return access; } @Override final String toString() { return tableName + "." + columnName; } } enum PersonTable { NAME_COLUMN("Name"), AGE_COLUMN("Age"), WEIGHT_COLUMN("Weight"); private TableEnumGuts guts; private PersonTable(String columnName, Access access) { guts = new TableEnumGuts("PersonTable", columnName, access); } public String getTableName() { return guts.getTableName(); } public String getColumnName() { return guts.getColumnName(); } public Access getAccess() { return guts.getAccess(); } @Override final String toString() { return guts.toString(); } } enum PetTable extends TableEnum { PETNAME_COLUMN("PetName"), SPECIES_COLUMN("Species"); private TableEnumGuts guts; private PersonTable(String columnName) { guts = new TableEnumGuts("PersonTable", columnName, access); } public String getTableName() { return guts.getTableName(); } public String getColumnName() { return guts.getColumnName(); } public Access getAccess() { return guts.getAccess(); } @Override final String toString() { return guts.toString(); } } Note how much more code (and worst of all, boilerplate duplicate code) is required in the second example, since each enumerated type must provide forwarding methods for each method in the 'TableEnumGuts' class. In one example that the author of this proposal was forced to deal with, there were 30 such enumerated types which conceptually extended the same base class, each of which had to implement that conceptual inheritance by delegating four or so methods to an internal "guts" object. This meant that any time time the signature of any of those four methods had to be changed, the change had to take place in 30 different forwarding methods as well. In another case (working for a different company) there were 10 such methods, duplicated over four conceptual subclasses, with similar problems. This proposal attempts to solve the above problem by defining the semantics of abstract enumerated types, and what it means for an enumerated type to have an abstract supertype, so as to allow code similar to the first example to work as expected in a Java compiler. FEATURE SUMMARY: Defines the meaning of inheritance from abstract supertypes for enumerated types. Note that this proposal specifically does not allow abstract enumerated types to have enumerators, since the semantics of these create difficult problems with inheritance (and open, in the words of one evaluator to a Sun bug submission, "a can of worms", related to the defunct "extendable enums" idea that has been proposed and rejected in the past.). MAJOR ADVANTAGE: Eliminates a missing feature between java enumerations and java classes, and restores a feature of the "typesafe enumeration" pattern that is not supported by Java enumerations as they are currently implemented. MAJOR BENEFIT: Elimination of duplicate code when related enumerated types need to be declared. Allows subclassing within enumeration types. Eases maintenance of families of enumerated types. Makes implementation sharing among related enumerated types work in a familiar manner analogous to how it works with classes. MAJOR DISADVANTAGE: There will be some work in the compiler necessary to implement this feature. Some people would like to be able to have concrete enums extend each other ("extensible enums"). This proposal does not attempt to provide such a feature, since it has been determined to be very difficult to specify and implement in the past. ALTERNATIVES: Note the delegation workaround being used above. This allows subtypes to share code, but results in potentially large numbers of forwarding methods and difficulties with code maintenance. EXAMPLES SIMPLE EXAMPLE: abstract enum SuperEnum { // Note: no enum constant declarations allowed here! int getTheAnswerToTheUltimateQuestion() { return 42; } } enum MyEnum extends SuperEnum { MY_ENUMERATOR; } class DeepThought { Object returnTheAnswer() { MyEnum[] values1 = MyEnum.values(); // OK MyEnum values2 = MyEnum.valueOf("MY_ENUMERATOR"); // OK SuperEnum values1 = SuperEnum.values(); // Error: No such method SuperEnum values2 = SuperEnum.valueOf("whatever"); // Error: No such method return MY_ENUMERATOR.getTheAnswerToTheUltimateQuestion(); } } ADVANCED EXAMPLE: abstract enum Base1 { protected final int sharedData; public int getSharedData() {return sharedData;} protected Base1(int sharedData) { this.sharedData = sharedData; } } abstract enum Base2 extends Base1 { protected final int otherSharedData; public int getOtherSharedData() {return sharedData;} protected Base2(int sharedData, int otherSharedData) { super(sharedData); this.otherSharedData = sharedData; } } enum Instances extends Base2 { INSTANCE1(10, 100), INSTANCE2(20, 200), INSTANCE3(30, 300) { public int getSharedData() { return 40; } } private Instances(int sharedData, int otherSharedData) { super(sharedData, otherSharedData); } } class AClient { void someFunc() { assert INSTANCE1.getSharedData()==10; assert INSTANCE2.getSharedData()==20; assert INSTANCE3.getSharedData()==40; Instances[] values = instances.values(); // OK Base2[] values = Base2.values(); // Error: No such method. } } DETAILS SPECIFICATION: A concept of an "abstract enum" shall be added to the Java language, denoted by prepending the word "abstract" to an enumerated type declaration, with restrictions as described below. Rule 1: An enumerated type shall either declare no supertype, or shall declare a supertype which is an abstract enumerated type. Rule 2: It shall be a compile-time error for an ordinary class to extend an enumerated type, either abstract or not. Rule 3: Both abstract and non-abstract enumerated types shall implicitly have a supertype (not necessarily a direct supertype) of Enum>. Thus, within the body of an abstract enumerated type, access to methods of this supertype is allowed. Rule 4: Abstract enumerated types shall not declare enumerators. The body of an abstract enumerated type shall be syntactically and semantically the same as that of an ordinary abstract class which extends its supertype (see rule 3), except with the restriction that all constructors shall be declared with 'protected' or 'package' access (since the class is abstract and cannot declare instances, constructors can only be invoked by subclasses so there is no need to make them more public than necessary). Rule 5: In an abstract enum, the compiler shall not generate the methods that it would generate for a non-abstract enumerated type (specifically, the "values()" or "valueOf(String) methods), for an abstract enumerated type. (Since it is illegal for there to be enumerators declared in an abstract enum, these methods would serve no purpose.) Rule 6: It shall be illegal for the expression used in a 'switch' statement to be an abstract enum type. Specifically, section 8.9 of the JLS3, which currently reads: " An enum declaration has the form: EnumDeclaration: ClassModifiers_opt enum Identifier Interfaces_opt EnumBody " shall be modified to read: " An enum declaration has the form: EnumDeclaration: ClassModifiersopt enum Identifier Super_opt Interfaces_opt EnumBody " Also, section 8.1.1.1 of the JLS3, which currently reads: "Enum types (?8.9) must not be declared abstract; doing so will result in a compile-time error. It is a compile-time error for an enum type E to have an abstract method m as a member unless E has one or more enum constants, and all of E's enum constants have class bodies that provide concrete implementations of m. It is a compile-time error for the class body of an enum constant to declare an abstract method." shall be modified to read: "Enum types (?8.9) may be declared abstract. If an enum type is declared abstract, it may declare abstract methods. However, it is a compile-time error for an abstract enum type to declare enum constants. Furthermore, it is a compile-time error for any constructor declared by an abstract enum type to have 'public' or 'private' access. It is a compile-time error for a non-abstract enum type E to have an abstract method m as a member (either explicitly declared or implicitly inherited from an abstract enum supertype) unless E has one or more enum constants, and all of E's enum constants have class bodies that provide concrete implementations of m. It is a compile-time error for the class body of an enum constant to declare an abstract method. " also, in the same section, the text which currently reads: "If the enum type has no constructor declarations, a parameterless default constructor is provided (which matches the implicit empty argument list). This default constructor is private." shall be modified to read: "If the enum type has no constructor declarations, a parameterless default constructor is provided (which matches the implicit empty argument list). This default constructor is protected if the enum is abstract, and private if it is non-abstract." and in the same section, the text which currently reads: "The direct superclass of an enum type named E is Enum." shall be modified to read: "A non-abstract enum type named E has a superclass (either direct or indirect via one or more abstract enums) of Enum." and in the same section, the text which currently reads: " It is a compile-time error for an enum to declare a finalizer. An instance of an enum may never be finalized. In addition, if E is the name of an enum type, then that type has the following implicitly declared static methods: " shall be modified to read: " It is a compile-time error for an enum (whether abstract or not) to declare a finalizer. An instance of an enum may never be finalized. In addition, if E is the name of a non-abstract enum type, then that type has the following implicitly declared static methods: " and in the same section, the text which currently reads: " It is a compile-time error to reference a static field of an enum type that is not a compile-time constant (?15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e. " shall be modified to read: " It is a compile-time error for a non-abstract enum type to reference one of its static fields which is not a compile-time constant (?15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e. Note however that any code within a non-abstract enum type may legally reference static fields of its abstract enum supertypes, if such supertypes and fields exist. " and in section 14.11 ('The switch statement'), the text which reads: "The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or an enum type (?8.9), or a compile-time error occurs." shall be modified to read: "The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or a non-abstract enum type (?8.9), or a compile-time error occurs." COMPILATION: An abstract enumerated type with no declared supertype, such as: abstract enum Foo { ,,, } shall be desugared to code resembling: @AbstractEnum abstract class Foo> extends Enum { ... } where "@AbstractEnum" is a private compiler-generated annotation similar to the one which is currently used to mark normal enumerated types, and in the same package. Like the annotation which is currently used to mark enumerated types, the @AbstractEnum annotation shall not be visible to ordinary users in source code form -- it exists solely in class files, to allow the compiler to distinguish an abstract class which was declared with the "abstract enum" syntax from one which was declared with the "abstract class" syntax, for the purpose of determining whether an attempt by one class to inherit from another (which may not be supplied in source code form) is legitimate. An abstract or non-abstract enumerated type with a declared supertype (which must be an abstract enumerated type), such as: abstract enum Foo1 extends Bar { ... } enum Foo2 extends Bar { ... } shall be desugared to code resembling: @AbstractEnum abstract class Foo1> extends Bar { ... } @... class Foo2 extends Bar { ... } When compiling such a class, the compiler shall emit a compile-time error if an enum (abstract or not) extends a supertype S unless the following is true: 1) Either S is declared as an "abstract enum" (if specified in source code form) or S is declared with the @AbstractEnum annotation (if specified in binary class file form), or the erasure of S is the type java.lang.Enum. 2) Regardless of whether S and its supertypes are declared in source code form or in binary class file form, all supertypes of S shall obey these same constraints. Furthermore, if a normal class is declared like so: class Bar extends Baz { } it shall be a compile-time error if class Baz is declared in source code to be an abstract enum, or if its binary class file representation has the @AbstractEnum annotation. The Java compiler currently generates certain methods, such as values() and valueOf(String) for enumerated types. It shall not generate these for abstract enumerated types. That is, the following shall be a compile-time error: abstract enum Foo { } void bar() { Foo[] foo1 = Foo.values(); // Error: no such method as 'Foo.values()' Foo foo2 = Foo.valueOf("whatever"); // Error: no such method as 'Foo.valueOf(String)' } SIMPLE EXAMPLE: These classes might be desugared to: @AbstractEnum abstract class SuperEnum> extends Enum { int getTheAnswerToTheUltimateQuestion() { return 42; } } @... class MyEnum extends SuperEnum { // The majority of this non-abstract enumerated type, // including generated methods and annotations, is exactly // the same as the Java compiler would generate // prior to this proposal. However, note that due to // this proposal, it has a supertype of "SuperEnum" // instead of "Enum". } ADVANCED EXAMPLE: These classes might be desugared to: @AbstractEnum abstract class Base1> extends Enum { protected final int sharedData; public int getSharedData() {return sharedData;} protected Base1(int sharedData) { this.sharedData = sharedData; } } @AbstractEnum abstract class Base2> extends Base1 { protected final int otherSharedData; public int getOtherSharedData() {return sharedData;} protected Base2(int sharedData, int otherSharedData) { super(sharedData); this.otherSharedData = sharedData; } } @... class Instances extends Base2 { // The majority of this non-abstract enumerated type, // including generated methods and annotations, is exactly // the same as the Java compiler would generate // prior to this proposal. However, note that due to // this proposal, it has a supertype of "Base2" // instead of "Enum". } TESTING: Testing can be accomplished by declaring various abstract enumerated types, having them extend each other, and having non-abstract enumerated types extend them. Normal inheritance relations (method overriding, etc.) should exist among the resulting types. Furthermore, at least one test should ensure that an attempt to extend an abstract enum (either specified in source or binary form) with a normal class is considered illegal, as is an attempt to have a non-abstract enum or an abstract enum extend a class which is not an abstract enum. Furthermore, a test should ensure that an attempt to use an expression whose compile-time type is that of an abstract enum in a 'switch' statement is considered illegal. Furthermore, a test should ensure that an attempt to reference the "values()" or "valueOf()" methods of an abstract enum is considered illegal. LIBRARY SUPPORT: No changes to supporting libraries are needed, except for the addition of the "@AbstractEnum" annotation type as mentioned above. REFLECTIVE APIS: The "Class.isEnum()" method shall return false when invoked on an abstract enum. (This is necessary to avoid unexpected side effects in methods which currently depend on identifying concrete enumerated types with this method. Technically, despite the syntax used to declare them, abstract enums aren't really enums -- they are just supertypes of them, and so should be treated basically exactly the same as class Enum is for the purposes of reflection, etc. This should be documented clearly in the javadoc for Class.isEnum()) It may be desirable to create a "Class.isAbstractEnum()" convenience method to detect the @AbstractEnum annotation. For consistency, such a method should probably return 'true' when invoked on the Enum supertype as well. OTHER CHANGES: Javadoc might possibly need to be updated to handle the possibility of generating documentation for an abstract enumerated type. In order to allow abstract supertypes to be added or removed from an abstract enum without making it impossible to read back existing serialized data, it will be necessary to modify the Java serialization specification as follows: In section "1.12 Serialization of Enum Constants", the following text shall be added at the end of the section: " Furthermore, in order to preserve the ability to deserialize enumerated constants which may have been serialized with an enumerated type having a different type hierarchy from what was written (due to the addition or deletion of "abstract enum" supertypes), the type of every enumerated constant shall be serialized and deserialized as if the immediate supertype of the declared non-abstract enum type which defines the constant was java.lang.Enum. In particular, a type such as: abstract enum Foo { } abstract enum Bar extends Foo { } enum Baz extends Bar { QUX; } shall exist in serialized form exactly as if it were declared as: enum Baz { // implicit supertype of Enum> QUX; } " MIGRATION: New abstract enumerated types can be created, as desired, to do code sharing between existing non-abstract enumerated types in an existing code base. The above "OTHER CHANGES" section ensures that adding or removing abstract supertypes of an enum will not affect the ability to serialize or deserialize instances of it. COMPATIBILITY BREAKING CHANGES: Since this syntax was previously considered a syntax error, no previously valid programs will be invalidated by it. EXISTING PROGRAMS: This feature should not change the semantics of existing class files. The features being added should desugar to normal method calls, class declarations, etc. Hence, I do not anticipate problems interacting with existing class files. REFERENCES EXISTING BUGS: Add language support for abstract Enum's http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6507006 allow "abstract enum AbstractEnum" and "enum MyEnum extends AbstractEnum" http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6222244 Support for public abstract enum declaration http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570766 (The original enum proposal, the comments for which allude to the possibility of abstract enums) Bug ID: 4401321 Add type-safe enums to Java http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4401321 URL FOR PROTOTYPE (optional): Although not implemented in response to this specific proposal, Fred Simon has implemented a substantially similar feature in Kijaro: http://tech.puredanger.com/2008/01/10/property-enum/ From vapor1 at teleport.com Thu Apr 30 23:45:40 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 1 May 2009 02:45:40 -0400 (EDT) Subject: PROPOSAL: Sameness operators (version 2) Message-ID: <8792005.1241160341070.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Per discussion on the Project Coin mailing list, this proposal has been expanded somewhat to discuss the possibility of using alternate operator sets (using # or ~ instead of $), and some discussion has been added on the merits of defining $$ and !$ in terms of Object.equals() instead of Comparable.compareTo(T). Sameness Operators (Version 2) AUTHOR: Derek Foster OVERVIEW Many Java objects implement the Comparable interface, and/or override the Object.equals() method, to provide a way of ordering their instances or detecting whether two instances are equivalent . However, the syntax for using these methods has historically been fairly ugly: // We want to write "if a >= b", but we have to write... if (a.compareTo(B) >= 0) { whatever(); } // We want to write "if a == b", but we have to write... if (a.equals(b)) { whatever(); } The ugliness of these methods has often motivated the creation of special-purpose APIs to simplify the use of classes which implement them, such as the 'Date.before(Date)' and 'Date.after(Date)' methods in java.util.Date. However, these methods are inconsistent from class to class, and often not present. Furthermore, the existing language == and != operators exhibit a strange assymetry between the behavior of objects and that of primitive types that often catches new users of Java by surprise: int i; if (i == 5) { // gets here if the VALUE of i is 5 } String j = new String("abc"); if (j == "abc") { // probably never gets here! Comparing the values of the references, not the values of the strings. } String k = new String("abc"); if (k.equals("abc")) { // gets here if the VALUE of k is "abc". } This behavior often confuses newcomers to Java, and is a common source of bugs even for experienced programmers. This proposal suggests that a new set of relational operators be added to Java which would simplify ordering classes by their declared orderings (as specified by the Comparable class and Object.equals()), while still yielding syntax that is as simple as using the existing >=, <=, ==, and != operators. FEATURE SUMMARY: Adds four new operators to Java: a $$ b "same as": a==null ? b==null : a.equals(b), or a == b for primitive types. a !$ b "not same as": a==null ? b!=null : !a.equals(b), or a != b for primitive types. a >$ b "greater than or same": a.compareTo(b) >= 0, or a >= b for primitive types. a <$ b "less than or same": a.compareTo(b) <= 0, or a <= b for primitive types. and adds additional overloadings to existing operators: a < b a.compareTo(b) < 0, or a < b for primitive types. a > b a.compareTo(b) > 0, or a > b for primitive types. Note that this proposal specifies several alternatives to the specific operator names chosen ( for instance, the proposal could be implemented using ##, !#, >#, and <# instead of $$, !$, >$, and <$) if the use of '$' is deemed too problematic due to possible breaking changes to generated files. This is discussed in the "BREAKING CHANGES" section below. MAJOR ADVANTAGE: Use of new operators for these relational tests would simplify code and make it more clear what relational tests are being made, as well as reducing the opportunity for mistakes (such as accidentally typing a.compareTo(b) >=0 when <=0 was intended). MAJOR BENEFIT: Clearer code due to the use of infix operators instead of using method calls and an extra pair of parentheses, plus possible extra tests (often accidentally omitted) for nullness around calls to Object.equals(Object). Future proposals involving limited uses of operator overloading for code clarity (for BigInteger, etc. classes) would no longer run into the iceberg of "but you can't change the behavior of == in a backwards-compatible fashion!" MAJOR DISADVANTAGE: Modifications to the compiler would be required. These do not appear particularly difficult, but would take some effort. The !$ operator would not be available for Perl-style pattern matching, if that were ever added to Java. ALTERNATIVES: Keep using the Comparable.compareTo and Object.equals methods as they are. It would have been better to define == and != this way in the first place, and use some other operator (perhaps === as in some other languages?) to indicate comparison by object identity. This would have made Java simpler and easier for newcomers to understand. However, that's not how the language is currently defined, and to change the behavior of == now would be a backwards incompatible change. It might be possible to define $$ and !$ in terms of "Comparator.compareTo(T)" instead of in terms of Object.equals(Object). However, doing so would have been less general purpose (it would only have worked on comparable classes). Although it is possible for these methods to disagree (for instance, Float's handling of Float.NaN), in practice this rarely occurs in the scenarios for which compareTo is typically used for determining well-ordering (sorting algorithms, etc.). EXAMPLES SIMPLE EXAMPLE: String getOrdering(String first, String second) { if (first $$ second) { System.out.println("They are equal"); } else if (first !$ second) { System.out.println("They are not equal"); } else if (first > second) { System.out.println("The first is after the second"); } else if (first >$ second) { System.out.println("The first is same as or after the second"); } else if (first < second) { System.out.println("The first is before the second"); } else if (first <$ second) { System.out.println("The first is before or the same as the second"); } } ADVANCED EXAMPLE: Really, the simple example pretty much illustrates the feature. DETAILS SPECIFICATION: The following new tokens $$ !$ >$ <$ shall be added to section 3.12 of the JLS3. The expression grammar in section 15.20 shall be modified like so: RelationalExpression: ShiftExpression RelationalExpression < ShiftExpression RelationalExpression > ShiftExpression RelationalExpression <= ShiftExpression RelationalExpression >= ShiftExpression RelationalExpression >$ ShiftExpression RelationalExpression <$ ShiftExpression RelationalExpression instanceof ReferenceType The expression grammar in section 15.21 shall be modified like so: EqualityExpression: RelationalExpression EqualityExpression == RelationalExpression EqualityExpression != RelationalExpression EqualityExpression $$ RelationalExpression EqualityExpression !$ RelationalExpression Semantically, the behavior of these new operators is as follows: $$ and !$ operators: Evaluation of these operators shall occur exactly as they do for the == and != operators, as specified in section 15.21 of the JLS3 ("Equality Operators"), with the exception that for the purposes of these operators, section 15.21.3 ("Reference equality operators == and !=") shall be disregarded and replaced with: If the operands of a sameness operator are both of either reference type or the null type, then the operation is object equivalence. The behavior described below is for the $$ operator. The !$ operator shall behave identically except that it shall return false when the $$ operator would return true, and vice versa. The procedure for evaluating the $$ operator is as follows: If both operands are null, then the result shall be 'true'. Otherwise, if the left operand is null and the right operand is not null, then the result shall be 'false'. Otherwise, the return value shall be the value of the expression "left.equals(right)", evaluated using the java.lang.Object.equals(Object) method. >, >$, <, and <$ operators: Evaluation of these operators shall occur exactly as it does for corresponding >, >=, <, and <= operators, in section 15.20.1 of the JLS3 ("Numerical Comparison Operators <, <=, >, and >=") with the exception of the following. The text "The type of each of the operands of a numerical comparison operator must be a type that is convertible (?5.1.8) to a primitive numeric type, or a compile-time error occurs." shall be replaced with the text "If the type of both of the operands of a numerical comparison operator is a type that is convertible (?5.1.8) to a primitive numeric type, the following algorithm is used to evaluate the operator. Otherwise, the operation is object ordering (See ?15.20.1.1)" A new section 15.20.1.1 shall be added consisting of the folowing text: If one or both operands of a relational operator cannot be converted to primitive numeric types, then boxing conversions shall be used to convert both operands to object types. After this conversion, if the type of the left operand does not extend the raw type java.lang.Comparable, and also does not extend java.lang.Comparable for some type T which is equal to or a supertype of the type of the right operand, then a compiler error shall be reported. Otherwise, the result of the comparison shall be evaluated at runtime as follows: If the left operand is null, a NullPointerException shall be thrown. Otherwise, the method left.compareTo(right) shall be called. The following table shall be used to determine the result of the operator evaluation, based on the value returned from this method: left.compareTo(right) <0 ==0 >0 > false false true < true false false >$ false true true <$ true true false COMPILATION: Compilation of the example given above would be desugared as follows: if (first==null ? second==null : first.equals(second)) { System.out.println("They are equal"); } else if (first==null ? second != null : !first.equals(second)) { System.out.println("They are not equal"); } else if (first.compareTo(second) > 0) { System.out.println("The first is after the second"); } else if (first.compareTo(second) >= 0) { System.out.println("The first is same as or after the second"); } else if (first.compareTo(second) < 0) { System.out.println("The first is before the second"); } else if (first.compareTo(second) <= 0) { System.out.println("The first is before or the same as the second"); } TESTING: The feature can be tested by ensuring, first of all that the new operators return the same results as existing operators when invoked on operands which are both convertible to numeric primitive types. Secondly, that the new operators return the same results as their desugaring equivalents when invoked in circumstances where one or both operands are not convertible to numeric primitive types. Thirdly, that the relational operators throw NullPointerExceptions when the leftmost operation is null. Fourthly, that compiler errors are reported exactly in the cases when the desugared equivalents of the operators would not compile. LIBRARY SUPPORT: No library changes are needed for this feature. REFLECTIVE APIS: No changes to reflective APIs are needed for this feature. OTHER CHANGES: No other parts of the platform need to be updated. MIGRATION: A tool such as Eclipe or IntelliJ Idea might identify for the users existing calls to .compareTo or .equals which could be converted to use the new operators, and could offer to perform the change automatically at the user's request. Or a user could simply refactor code to use the new operators as desired. COMPATIBILITY BREAKING CHANGES: The default set of operators ($$, !$, >$, and <$) suggested in this proposal were chosen because the "$" has an easy mnemonic meaning of "sameness". However, there are some rare circumstances in which a valid program that uses the $ operator within identifiers (typically only done in machine-generated code) might become invalid according to this proposal. Specifically, a program which, in source code, used the $ character at the start of an identifier might not compile correctly, if it contained code such as: if (a<$something) { } meaning "if ( a < $something )" rather than "if ( a <$ something )" which is how it would be parsed according to this proposal. This would almost certainly result in a compiler error about a missing variable "something", particularly if the body of generated code was large, so the odds of this resulting in correctly compiling but silently misinterpreted code is small. This would only happen in generated code (the only place a $ character is supposed to be used, according to the JLS), and is expected to be an extremely rare phenomenon, since generated code rarely starts identifiers with dollar signs, and also usually generates code with spaces around operators for readability. This problem can be easily fixed when upgrading to Java 7 by altering the code generator to put a space in front of any such identifiers, either globally or only when they follow a < or > character. Note that internal synthetic variables generated by a compiler in a class file would be immune from this problem since they would never appear in source code form. Alternately, this proposal could be altered to use another character instead of $ for its tokens. One good candidate for this would be "~" which lends itself to being read as "is equivalent to" (rather than "$" for "is the same as"). There are, however, rare cases that this could break as well ( if (a<~b) { ... } ) and although relational tests against negated values are quite rare (since combining bitwise operations and relationals is usually a nonsensical operation), unfortunately this breakage could occur in non-generated code, which is much more common than generated code. Yet another option would be "#", which somewhat resembles an equals sign. Thus, instead of the $$, !$, <$, and >$ operators, this proposal could be implemented to use the ##, !#, <#, and ># operators. The # operator has the advantage of being unused in Java, and so is guaranteed not to break code. However, it is highly sought after by writers of language change proposals (such as closures, method pointers, and others), and so is under heavy competition as to its future meaning. The #-related operators would certainly be the safest set of operators to use to implement this proposal, although some care might be required to ensure that this use would not interfere with some other future desired meaning of these operators. Fortunately, most proposals for using the "#" in code have attempted to use it as an infix operator with identifiers on either side rather than as a prefix operator, which reduces the risk of conflicting with this proposal. Also, if the above symbols were defined as tokens before any such code exists, it should be easy to ensure that any future use of the # character simply never falls into the pattern of one of these tokens. EXISTING PROGRAMS: Except for the minor, rare, breaking change listed above, this change should not create incompatibilities with existing source or class files. REFERENCES EXISTING BUGS: There are a variety of proposals in the Bug Database related to various people's desires to support operator overloading for certain built-in mathematical classes such as BigInteger. A couple of such proposals are listed below. "Add [], -, +, *, / operators to core classes as appropriate" (related) http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5099780 "BigInteger should support autoboxing" http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6407464 Also, see discussion on the Project Coin mailing list regarding the proposal "Draft proposal: allow the use of relational operators on Comparable classes," particularly with regards to why that proposal was withdrawn (namely, inability to make the == and != operators work properly on Comparable classes). http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000361.html URL FOR PROTOTYPE (optional): None.