Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It's not that awkward, C# does the same thing:

   interface IPoint
    {
   // Property signatures: 
   int x
   {
      get;
      set;
   }

   int y
   {
      get;
      set;
   }
   }
(taken from http://msdn.microsoft.com/en-us/library/87d83y5b.aspx)


I don't see the similarity. The Ceylon feature I find awkard is that class definitions have two parts (initializer/declaration) with different semantics, without explicit demarcation.

In the example above, this code:

    class Point() {
        Float x => y;
        Float y => x;
    }
is fine, because both declarations are parsed as being in the declaration section. However, when you add another line after that:

    class Point() {
        Float x => y;  //compiler error: y is not referenceable
        Float y => x;
        Float->Float xy = x->y;
    }
The original two declarations are now part of the initializer section, because the third line is a statement that is not allowed in the declaration section. This changes the semantics of the first two lines.


FTR, the whole declaration section vs initialization section stuff really boils down to this:

    You can't declare mutually-recursive methods before 
    initialization logic in the body of a class. You have to 
    declare them _after_ the fields of the class are fully 
    initialized.
That's not so hard to understand.

To see why it's like this, you need to consider :

- Unlike most OO languages Ceylon statically _guarantees_ that a field of an object is initialized before it is accessed. (If we didn't, then we would have to have something conceptually equivalent to a NullPointerException when you access a field before initialization.) - We've always hated the amazingly repeaty syntax of constructors in C++/C#/Java.

What I mean is, in Java I have to write stuff like:

    class Point {
        final float x; 
        final float y;
        Point(float x, float y) {
            this.x = x;
            this.y = y;
        }
    }
In Ceylon, it would be:

    class Point(Float x, Float y) {}
And even with all that verbosity in the Java version, I _still_ don't get a static guarantee that `x` and `y` are initialized before they are used by a method. This code prints `0.0`:

    class Point {
        final float x; 
        final float y;
        Point(float x, float y) {
            fun();
            this.x = x;
            this.y = y;
        }
        void fun() { System.out.println(x); }
        public static final void main(String[] args) {
            new Point(1.0f,2.0f);
        }
    }
So Ceylon wants to solve _both_ these problems: eliminate the verbosity, and provide the static checking for initialization. Now, this is an _almost_ completely transparent process. I almost never find myself thinking about declaration section vs initialization section. I just write classes so that fields are initialized before the methods that use them are declared. Which is basically super-intuitive. In >95% of classes that's all you need to know. Very rarely, I mix this up, and the compiler complains and I need to move a member up or down. Which takes seconds to fix. Very, very rarely, I have a class with some kind of self-recursive initialization logic and then only in that case do I need to start holding the mental model of declaration-vs-initialization sections in my head. In practice, I think I've only run into this situation _once_, and it took me a few minutes to restructure the code. (FTR, it was `ArrayList` in `ceylon.collection`.)


Seems like a bug.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: