The Artima Developer Community
Sponsored Link

Weblogs Forum
Comparing Inner Class/Closure Proposals

9 replies on 1 page. Most recent reply: Apr 20, 2007 6:27 AM by Howard Lovatt

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 9 replies on 1 page
Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Comparing Inner Class/Closure Proposals (View in Weblogs)
Posted: Apr 11, 2007 6:23 PM
Reply to this message Reply
Summary
There are at least 4 inner class/closure proposals for Java 7 and it is hard to compare them because they use different terms and different syntax for similar concepts. This post makes the comparison easier by seperating concerns.
Advertisement

Comparing Inner Class/Closure Proposals

There are at least 4 inner class/closure proposals for Java 7 and it is hard to compare them because they use different terms and different syntax for similar concepts. The idea of this post is to separate out the inner class/closure part of the proposals from the extras and make explicit that the extras can be added or taken away from any of the proposals or be part of other proposals; because they are separate concerns. This separation of concerns gives clarity and also allows you to roughly rank the various features (my ranking is the order presented).

In some instances there is synergy between these separate concerns and hence these extras are presented together with the main proposal. In fact all but the CICE proposal covers issues other than the inner classes/closures themselves. Before continuing I should declare my self-interest; I authored the C3S proposal. Explanations and examples of the different features are given below, but first an “at a glance” comparison.

Table 1: “At a Glance” Comparison
Feature C3S FCM CICE BGGA
1. Short syntax for the creation of an instance of an inner class/closure Y Y Y Y
2. Access to both this pointers and methods within an inner class Y Y
3. More than one method in an inner class/closure instance Y
4. Implementation of methods defined in classes Y Y
5. Type inference Y Y Y Y
6. Method, constructor, and field literals Y
7. Short syntax (particularly for control structures and short methods) Y Y Y
8. Assignment to local variables and no final requirement Y Y Y Y
9. Variable number of exceptions Y Y Y Y
10. Method/function types (with shorter syntax) Y Y
11. Non-local, return, break, and continue Y Y Y

Definition of terms

  • Closure is a new term in the current Java 6 context; closures are like inner classes except that the normal inner class this pointer isn't available, only the pointer to the enclosing class, which is confusingly (?), called this.

  • C3S is Clear, Consistent, and Concise Syntax for Java

  • FCM is First Class Methods v0.5 and the companion Java Control Abstraction (JCA)

  • CICE is Concise Instance Creation Expressions

  • BGGA is Closures for the Java Programming Language v0.5 (named after the initials of the authors)

Summary of features

From the table you can see that the proposals only really agree that there should be: short syntax for inner classes/closures, more type inference, a variable number of exceptions, and that the read-only and final declaration restriction for local variables should be removed. Should these be the only extensions made to Java?

As for the other features, that depends upon the weighting you give each feature. This weighting need not be a simple progression of a weighting of 11 for your number 1 to a weighting of 1 for your number 11. For example I personally give little weighting to my numbers 8 to 11 inclusive; however others find these points important and therefore I have included some of them in my C3S proposal to hopefully broaden acceptance.

Explanations and examples

1. Short syntax for creation of an instance of an inner class/closure

This is the focus of all the proposals and a typical use is to apply a method to the elements in a collection.

C3S

 
    declare ls = ... ;
    sort ls, method( s1, s2 ) { s1.length - s2.length };

FCM

    List< String > ls = ... ;
    sort( ls, #( String s1, String s2 ) { return s1.length() - s2.length(); } );

CICE


    List< String > ls = ... ;
    sort( ls, Comparator< String >( String s1, String s2 ) { return s1.length() - s2.length(); } );

BGGA

    List< String > ls = ... ;
    sort( ls, { String s1, String s2 => s1.length() - s2.length() } );

2. Access to both this pointers and to methods within an inner class

This is the real distinguishing feature between a closure and an inner class, a closure only has access to the this pointer associated with the enclosing class and not, also, its inherited this pointer. Therefore inside a closure you cannot call any other method of the closure including itself (inner classes don’t have these restrictions). C3S and CICE have inner classes, whereas FCM and BGGA only have closures. Anything that can be done with a closure can therefore be done with an inner class but not vice versa. For inner classes there may be a case for adding a keyword, say enclosing, that is used like this, but refers to the enclosing class (what do people think about adding this keyword?). For me this is a very important feature, so I will give three examples.

A. Reducer

Firstly, consider a reduce method (a.k.a. fold) on a list. If you had a class Reducer as shown, using Java 6 syntax:

    public abstract class Reducer< E > {
      public E total;
      public Reducer( final E initial ) { total = initial; }
      public abstract void call( E element );
      public static < T > T reduce( final Iterable< T > collection, final Reducer< T > reducer ) {
        for ( final T element : collection ) { reducer.call( element ); }
        return reducer.total;
      }
    }

then

C3S

    method Integer sum() { 
      return reduce ls, new( 0 ) { method( e ) { total += e } };
    }

FCM (Only one this, therefore make total explicit and use each instead of reduce.)

    Integer sum() {
      Integer total = 0;
      each( ls, #( Integer e ) { total += e; } );
      return total;
    }

Alternatively reducer could be re-written to pass the total each time and then you could write:

    Integer sum() {
      return reduce( ls, 0, #( Integer total, Integer e ) { return total += e; } );
    }

CICE (Constructor must have zero arguments, therefore use straight Java 6 code. Alternatively code similar to FCM above could be used.)

    Integer sum() {
      return reduce( ls, new Reducer( 0 ) {
        public void call( e ) { total += e; }
      } );
    }

BGGA (Only one this, therefore make total explicit and use each instead of reduce. Code not shown since it is similar to FCM above.)

B. Recursion

The second example of needing access to the methods inside the inner class is recursion (without access to methods within the inner class you cannot use recursion — it is a long while since I used a language without recursion :-( ). Given a list of Integers:

C3S


    method Integer sumOfFactorials( final Iterable< Integer > ls ) {
      return reduce ls, new( 0 ) { 
        method( e ) { total += factorial e }
        static method int factorial( final int x ) {
          if ( x <= 1 ) { return 1 }
          x * factorial x – 1
      }
    };

FCM (No access to methods within the closure from within the closure, therefore use normal Java 6.)

    Integer sumOfFactorials( final Iterable< Integer > ls ) {
      return reduce( ls, new Reducer< Integer >( 0 ) {
        public void call( e ) { total += factorial( e ); }
        static int factorial( final int x ) {
          if ( x <= 1 ) { return 1; }
          return x * factorial( x – 1 );
        }
      };
    }

CICE (Constructor must have zero arguments and only one method allowed, therefore use straight Java 6 code as above.)

BGGA (No access to methods within the closure from within the closure, therefore use Java 6 as shown for FCM above.)

C. Worker

With the advent of multi-core processors the importance of multi-threaded code will increase. Any new language features should anticipate this trend and a favour multi-threading. Access to the enclosing scope is of less value in a multi-threaded environment since the enclosing scope may be long gone when the method is evaluated. Multi-threading therefore emphasizes access to the inherited this pointer and to methods and fields within an inner class.

For example, at times you need to wait for previous tasks to complete before proceeding. This can be done by waiting for Futures to complete; a Future's get method will sleep a thread for example. Unfortunately a Thread is expensive and therefore you ideally don't want to sleep one. Instead you might delay scheduling a calculation until its inputs are ready:

  static method< R, A1, A2 > Future< R > submitWithGuard(
          final ExecutorService pool,
          final Future< A1 > a1,
          final Future< A2 > a2,
          final Method2< R, A1, A2 > binary ) {
    final result = FutureTask< R >.new method { binary.call a1.get, a2.get };
    pool.submit method {
        if ( a1.isDone && a2.isDone ) { pool.submit result } // inputs available, submit job
        else { pool.submit this } // inputs not available, check again in the future
    };
    return result;
  }

FCM and BGGA cannot implement submitWithGuard, as shown above, because it accesses the inherited this and instead normal Java 6 would be used or a name would be given to the inner class via a method declaration (which would then be wrapped in a Runnable). A CICE implementation would be similar to the above code, but a little more verbose.

3. More than one method in an inner class/closure

C3S is unique in allowing the overriding of more than one method. The others can only override one method and therefore some uses, particularly for asynchronous calls, can’t be accomplished directly. EG imagine a method called time that takes an array of Callable methods, runs them all a few times and in different orders, and then reports the average execution time for each as well as checking each call gives the same result. This time method requires objects that have a call method from Callable, but also uses the toString method for identification and reporting purposes.

C3S

    time new {
      method Integer call { ...; ... }
      method toString { "Method1" }
    }, new {
      method Integer call { ...; ... }
      method toString { "Method2" }
    };

FCM (Only one method allowed therefore use straight Java 6.)

    time( new Callable< Integer >() {
      public Integer call() { ...; return ...; }
      public String toString() { return "Method1"; }
    }, new Callable< Integer >() {
      public Integer call() { ...; return ...; }
      public String toString() { return "Method2"; }
    } );

CICE (Only one method allowed therefore use straight Java 6, as shown above for FCM.)

BGGA (Only one method allowed therefore use straight Java 6, as shown above for FCM.)

4. Implementation of methods from classes

No problem with C3S and no problem for CICE provided that for CICE there is only one abstract method to override (see point 3 above). FCM can implement a method from a class provided that only one method is to be implemented, the class doesn't have generic arguments, the class has a no-arg constructor, and no access is required to other class members. BGGA can’t use classes at all. Consider an Integer array factory (a factory that returns a List of Integers, but the list is fixed sized):

C3S

    static method List< Integer > factory( final int capacity ) { // final optional

      return AbstractList.new< Integer > {
        private final values = Integer.new[ size ];
        method size { capacity };
        method get( index ) { values[ index ] }
        method set( index, value ) {
          final temp = values[ index ];
          values[ index ] = value;
          temp
        }
      }
    }

FCM (No access to inherited this (see point 2 above), therefore use standard Java 6.)

    static List< Integer > factory( final int capacity) {
      return new AbstractList< Integer >() {
        private final Integer[] values = new Integer[ size ];
        public int size() { return capacity; }
        public Integer get( final int index ) { return values[ index ]; }
        public Integer set( final int index, final Integer value ) {
          final Integer temp = values[ index ];
          values[ index ] = value;
          return temp;
        }
      };
    }

CICE (Cannot override more than one method (point 3 above), therefore use standard Java 6 (see FCM above).)

BGGA (Cannot extend abstract classes at all, therefore use standard Java 6 (see FCM above).)

5. Type inference

C3S, FCM, and BGGA have some type inference and CICE states that type inference could be added. The type inference for C3S (but see below for other examples), FCM, BGGA, and suggested for CICE is to infer a class/interface/method name. EG the sort example given in 1 above which in C3S is:

    sort ls, method( s1, s2 ) { s1.length - s2.length };

Infers: the interface name, Comparable, the generic type parameter, String, the return type, int, the method argument types, both String, and the method name, compare. The examples for BGGA and FCM are almost identical, except that the argument type is needed, and therefore FCM and BGGA are not shown; for CICE you need to supply the interface name and argument types (see 1 above). The type inference in C3S is however much more extensive than for the other proposals and more extensive than the above example demonstrates. The C3S type inference is similar in scope and nature to the type inference that is in Scala. This copying of Scala is an important point, since Scala demonstrates that this level of type inference is practical and still produces good error messages unlike more extensive type inference in other languages. In C3S the method construct given above can be used for any declaration, e.g. an anonymous AbstractList:

    static method List< Integer > factory( final int capacity ) {
      return AbstractList< Integer >.new {
        private final values = Integer.new[ size ];
        method size { capacity };
        method get( index ) { values[ index ] }
        method set( index, value ) {
          final temp = values[ index ];
          values[ index ] = value;
          temp
	    }

      };
    }

Also in the AbstractList example above note how the type of variable declarations are inferred from the right hand side. To support this type inference a new keyword declare is added for non final declarations, e.g.:

    declare list = ArrayList.new( 1, 2, 3 );

Instead of:

    List< Integer > list = new ArrayList< Integer >( 1, 2, 3 );

6. Method, constructor, and field literals

The FCM proposal provides syntax for method, constructor, and field literals (currently only a type has a literal in Java, name.class, and strings have to be used for the others). The proposal in FCM mimics the construct used in Javadocs, e.g.:

    Method m = ClassName#methodName( argumentTypes );
    Constructor< ClassName > c = ClassName#ClassName( argumentTypes );
    Field f = ClassName#fieldName;

A unique and emphasized feature of FCM is the ability to refer to methods as an alternative to writing an inner class/closure. E.G.:

    public void init() {
      JButton button = ...;
      button.addActionListener( this#handleAction( ActionEvent ) );
    }
    public void handleAction( ActionEvent ev ) {
      // handle event
    }

This syntax allows you to seperate out the method to a stand alone method. Assuming that no access to local variables is required. The above code could alternatively be written as:

      button.addActionListener( #( ActionEvent e ) { handleAction( e ); } );

7. Short syntax (particularly for control structures and short methods)

C3S, FCM, and BGGA provide short syntax for constructs other than inner classes/closures, the other proposals don’t address further short syntax. First BGGA, it has two other short syntax constructs one for short methods and one for control like constructs. The short method construct is from within a closure only (i.e. not generally available). The short method construct is that return isn’t used; instead a statement without a terminating semicolon must be used instead. E.G.:

    Boolean someMethod() {
      return invert( { => true } );
    }

(Note { => true; }, { => return true } and { => return true; } might not behave how you expect.)

BGGA also provides short syntax for control structures, it uses the for keyword to identify these methods and allows the movement of the closure to outside the method brackets, provided that the closure is the last argument. E.G. an each iterator might be:

    public static < V > void for each( Iterable< V > collection, { V => void } block ) {
      for ( V v : collection ) { block( v ); }
    }
    ...
    for each( Integer e : ls ) { total += e; }

If each where not declared with for then its use in BGGA it would be:

    public static < V > void each( Iterable< V > collection, { V => void } block ) {
      for ( V v : collection ) { block( v ); }
    }
    ...
    each( ls, { Integer e => total += e; } );

FCM does not have any short method syntax but it does have control syntax, much along the lines of BGGA and therefore not shown.

C3S takes a different approach than BGGA, it provides general short constructs, not just specifically for inner classes, that can be used throughout Java and all of which are optional. Type inference, discussed above, is an example. Others examples are: method declarations in general, generic declarations, inference of generic types for constructors, declaration of constructors, and declaration of properties. See C3S for details. It is interesting to note that in the vast majority of examples C3S versions are the most concise; this is a surprising result since C3S’s design favoured clarity and therefore used keywords rather than symbols and since the keywords are longer than the symbols used in other proposals you might expect C3S to be verbose. The reason that C3S is the most concise, is because generally applicable constructs have been favoured in C3S over constructs with a few use cases.

For all methods C3S makes return optional and uses the value of the last line in the block if return is omitted, therefore the invert example above in C3S would be:

    method Boolean someMethod {
      return invert method { true };
    }

(Note { true; }, { return true } and { return true; } all do the same as { true }.)

For all methods C3S makes unambiguous brackets optional (like Ruby) and makes the semicolon before a closing brace optional (like Pascal), therefore the for example in C3S is:

    each ls, method( e ) { total += e };

8. Assignment to local variables and no final requirement

All the proposals are basically the same, they allow writing to local variable (in the case of CICE a writable local needs to be annotated with public) and there is no need to declare local variables final. Since all the proposals are so similar on this point only C3S is shown:

    method int sum() {
      int total = 0;
      each ls, method( e ) { total += e };
      return total;
    }

In BGGA you can turn off access to non-final local variables by making the interface that the closure implements the method of extend RestrictedFunction. It is not clear how practical this technique of adding RestrictedFunction would be since you can't retrofit to existing code easily.

9. Variable number of exceptions

At times it is convenient to be able to declare very general methods that throw any number of exceptions, including checked exceptions. Currently either RuntimExceptions only are allowed, e.g. Runnable, or Exception, as opposed to a specific exception list, is thrown, e.g. Callable. C3S, FCM, and BGGA propose solutions, C3S uses generic varargs and FCM and BGGA provide a similar capability but don’t use the varargs syntax.

C3S

    interface< R, A1, Throwable... Es > Method1 {
      method R call( A1 a1 ) throws Es;
    }

FCM & BGGA

    interface Method1< R, A1, throws Es > {
      R call( A1 a1 ) throws Es;
    }

CICE

Joshua Bloch (one of the authors of CICE) said in an email:

While CICE [JB said BGGA but I am sure he meant CICE] doesn't specifically allow for disjunctively typed throws clauses (“Variable number of exceptions”) it doesn't rule it out either. I see this as a defect in the generic typing facility that should be fixed there. Once so fixed, it will apply to all parameterized types, even those produce using old-fashioned anonymous class instance creation expressions.

This is a fair point, “Variable number of exceptions” is a seperate concern.

10. Method/function types (with shorter syntax)

FCM and BGGA both provide support for declaring the type of classes that contain a single method. In both cases the syntax is based on their inner class/closure syntax, e.g.:

    #( void( MouseEvent ) ) me = #( MouseEvent e ) { ...; ...; }; // FCM
    { MouseEvent => void } me = { MouseEvent e => ...; ...; }; // BGGA

In both cases the types above are translated into a standard interface, e.g.:

    Method1< Void, MouseEvent >

See point 9 above for the definition of Method1. To convert the anonymous method given in the above example to an instance of Method1 the correct generic parameters for Method1 need to be inferred. The generic arguments are easy, since they are explicitly stated, the return type of the anonymous method is however potentially difficult. Consider (in FCM syntax):

    #( boolean useIntegerArithmatic, Number value ) {
      if ( useIntegerArithmatic ) { return value.longValue() * 2L; } 
      return value.doubleValue() * 2.0; 
    }

The correct return type is Number, but this is very hard to deduce.

With C3S (and potentially with CICE, but the concept isn’t explicitly mentioned) there is no new syntax and instead Method1 is used directly. This option avoids the difficulty of inferring the return type. The equivalent “mouse” line in C3S and CICE is:

    declare me = Method1< Void, MouseEvent >.method( e ) { ...; ... }; // C3S
    Method1< Void, MouseEvent > me = Method1< Void, MouseEvent >( MouseEvent e ) { ...; ...; }; // CICE

Note on variance as used in BGGA and FCM

The above examples given for FCM and BGGA are slightly simplified. In practice both proposals suggest variance is used to make the method types more general. E.G. in FCM (but similarly for BGGA):

    #( Number( Number, Number ) ) add = #( final Number lhs, final Number rhs ) { return lhs.doubleValue() + rhs.doubleValue(); };

Is translated into:

    Method2< ? extends Number, ? super Number, ? super Number > add = new Method2< Number, Number, Number > () {
      public Double call( final Number lhs, final Number rhs ) { return lhs.doubleValue() + rhs.doubleValue(); }
    };

Note how the generic arguments to Method2 when declaring add use variance. The idea is to increase the generality of the method, this is a laudable aim.

11. Non-local return, break, and continue

C3S, FCM, and BGGA support non-local return, break, and continue, whereas CICE doesn’t. In BGGA this facility is highly emphasized whereas in C3S it is listed as a possible future option. In BGGA it is considered a most important feature and new syntax is introduced into closures for normal method return and the normal method return syntax is used for a non-local return (see point 7 above). It is hard to find a good usage example for non-local returns because throwing an exception is a viable alternative; in fact they are implemented by throwing an exception! Another point to note is that the concept of non-local returns is only applicable in single threaded code in which the evaluation order is well known (typically sequential). This style of coding will be used less in the future because processors are all going multi-core and therefore favour multi-threading. (This multi-core and hence multi-threading for the future was noted in point 2 above.)

As already noted; a good example is hard to find, but suppose that the collections library did not contain binarySearch but did contain each (and you didn’t want to use a loop!):

C3S

    method Integer find( final Integer key ) {
      each list, method( e ) {
        if ( e.equals key ) { find.return e }
      };
      null
    }

BGGA


    Integer find( final Integer key ) {
      for each ( final Integer e : list ) {
        if ( e.equals( key ) ) { return e; }
      };
      return null;
    }

(The most common justification for the non-local return feature of BGGA using the traditional method return syntax is that it allows easy refactoring of something like a for loop into an each loop. It is true that this refactoring is simple in BGGA, but I would suggest that the more common refactoring of an inner class’s method/closure into a stand-alone method is now harder. Therefore the use of normal method syntax for non-local return seems dubious. The value you place on this feature would seem to depend on your programming style. If you use a heavy procedural style then you might make extensive use of blocks nested inside one another. However if you use an OO style or a functional style you are much more likely to use a lot of small methods instead and therefore hardly ever use a non-local return.)

In BGGA you can turn off non-local returns by making the interface that the closure implements the method of extend RestrictedFunction. It is not clear how practical this technique of adding RestrictedFunction would be since you can't retrofit to existing code easily.

Code for FCM would be similar to the above BGGA code and therefore isn't shown. There is however a major point of difference between FCM and BGGA, in BGGA a non-local return is allowed for all closures. In FCM non-local returns are only allowed in control blocks. In fact in FCM all return statements within a control block are non-local returns and further more the return type of a control loop block is void and therefore no confusion exists as to whether a return is local or not. This difference concerning non-local returns considerably simplifies the FCM proposal.

Acknowledgements

Stefan Schultz and Stephen Colebourne (the authors of FCM) both suggested that I write this blog. I asked the authors of the respected proposal to check my examples of their code, thanks to those who responded.


Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Comparing Inner Class/Closure Proposals Posted: Apr 12, 2007 10:15 PM
Reply to this message Reply
I edited the original post to reflect comments from the respective authors of the three proposals that I didn't author, i.e. BGGA, CICE, and FCM.

Thanks to these other authors for helping me out.

Marc Stock

Posts: 17
Nickname: salient1
Registered: Mar, 2007

Re: Comparing Inner Class/Closure Proposals Posted: Apr 13, 2007 11:06 AM
Reply to this message Reply
Nice job comparing the proposals. That said, I would prefer that Java not have closures at all and if it was to get them, I would prefer it to use the syntax that Groovy uses for closures.

Again, Java should not have closures. Java was designed with certain principles in mind (like same syntax as C/C++, etc.) and the more you stray from those principles, the more you just pollute the language into a monstrosity. If you want next-gen language constructs, use a next-gen language (like Groovy or Ruby). Personally, I would prefer Groovy to simply replace Java over time.

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Comparing Inner Class/Closure Proposals Posted: Apr 15, 2007 7:14 AM
Reply to this message Reply
Thanks for saying you liked the blog.

I think it is important that many views are canvassed and your view that Java should be left alone is quite ncommon. So I think the powers that be on the JCP should seriously consider doing nothing.

Ired Sedl

Posts: 2
Nickname: ired
Registered: Dec, 2006

Re: Comparing Inner Class/Closure Proposals Posted: Apr 16, 2007 6:25 AM
Reply to this message Reply
Good Job Howard, C3S looks very clean. Although I really like BGGA control invocation syntax, your expression looks cleaner over all.

I hope that when EG is formed, your participation will help ensure that Java remains a competitive language in the future such that our existing investment can be grown without reservation. (JCP should really expedite its community voting mechanism)

Aside from minor inconveniences, inner classes already provide much of the functionality of closures, therefore syntax should be be concise, clean and familiar as it would represent what appears to be the biggest improvement to the current means of abstraction at the method level.

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Comparing Inner Class/Closure Proposals Posted: Apr 16, 2007 7:53 PM
Reply to this message Reply
Thanks for your comments. I agree with everything you said (including liking the control loop invocation syntax in BGGA, I have my reservations about the declaration syntax and about just how useful new control loops are). It would be good if some sort of consensus could be reached via the JCP.

Kannan Goundan

Posts: 18
Nickname: cakoose
Registered: Nov, 2005

Re: Comparing Inner Class/Closure Proposals Posted: Apr 20, 2007 1:31 AM
Reply to this message Reply
I think the Ruby-like invocation syntax of C3S obscures the comparison a little. This omission of parens seems orthogonal to the closure-related modifications; for the purposes of comparing closure proposals, it would be more useful to see the C3S examples with the extra parens. Alternatively, you could try writing out all the proposals without the extra parens.

(BTW, I think removing the parens from Java is too radical a change. If you're willing to go that far, you might as well use Scala!)

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Comparing Inner Class/Closure Proposals Posted: Apr 20, 2007 1:57 AM
Reply to this message Reply
@Kannan,

I am hoping that one of the values of this comparison is to enable people to prioritize which of the separate concerns they like and which option for a given concern they like. So taking your example, you don't like option 7 Short Syntax or at least not the C3S options for short syntax. That is useful feedback on the proposals.

As an aside, the reason that I preferred making () optional over special syntax for a given control structure is that it achieves a similar level of conciseness and yet has many more uses cases. Personally I find all the () in Java cluttering and don't think they add to clarity much.

But as I said the purpose of the blog is to separate concerns and let people have their say.

Kannan Goundan

Posts: 18
Nickname: cakoose
Registered: Nov, 2005

Re: Comparing Inner Class/Closure Proposals Posted: Apr 20, 2007 4:46 AM
Reply to this message Reply
> I am hoping that one of the values of this comparison is
> to enable people to prioritize which of the separate
> concerns they like and which option for a given concern
> they like. So taking your example, you don't like option 7
> Short Syntax or at least not the C3S options for short
> syntax. That is useful feedback on the proposals.

Actually, I was trying to say that your examples don't fully separate concerns. Most of the C3S examples (not just the ones in section 7) omit parentheses on method invocations.

Omitting parentheses on method invocations is a feature that is mostly orthogonal to the core closure-related issues (it could probably be added on to any of the other proposals). Therefore, I think it's best to keep that feature out of sight. The easiest way to do that is to change the C3S examples on this page to use parentheses on method invocations (except perhaps in the few cases where it is relevant).


> Personally I find all the () in Java cluttering and don't
> think they add to clarity much.

I agree and that's one of the things I like about Ruby (and Scala). It's just that without them, it doesn't even look like Java code anymore :)

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Comparing Inner Class/Closure Proposals Posted: Apr 20, 2007 6:27 AM
Reply to this message Reply
@Kannan,

> Actually, I was trying to say that your examples don't
> fully separate concerns. Most of the C3S examples (not
> just the ones in section 7) omit parentheses on method
> invocations.

Sorry for not getting your point first time. I did consider using standard Java except for the feature under discussion. For example, not using short syntax for inner classes/closures, point 1, except when discussing point 1. This would effect the presentation of all the proposals, not just C3S. In the end I decided it was best to show all examples, in each syntax, in what I considered the most likely way that example would be written in a particular syntax.

> Omitting parentheses on method invocations is a feature
> that is mostly orthogonal to the core closure-related
> issues (it could probably be added on to any of the other
> proposals).

Yep I agree, it almost certainly a feature that could be added to the other proposals. It is a two way street though, for example the BGGA control loop syntax could be added to C3S. However I was documenting the proposals as they stand. Maybe you want to choose the variations you like and give some examples in another set of features.

> > Personally I find all the () in Java cluttering and
> don't
> > think they add to clarity much.
>
> I agree and that's one of the things I like about Ruby
> (and Scala). It's just that without them, it doesn't even
> look like Java code anymore :)

I didn't particularly push the no () point. One of the advantages in eliminating () is that it lets you make an embedded-domain-specific language more easily. Because you can make a library call look like a statement. Many of the Ruby libraries use this to great effect.

Flat View: This topic has 9 replies on 1 page
Topic: Comparing Inner Class/Closure Proposals Previous Topic   Next Topic Topic: Future of Commercial Java IDEs


Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us