Ceylon language

spir denis.spir at gmail.com
Thu Apr 14 06:34:04 PDT 2011


On 04/13/2011 02:34 PM, bearophile wrote:

> -------------
>
> Ceylon does not support method overloading (or any other kind of overloading).

How to survive? Named args and default values somewhat mitigate this lack, but 
still...
I read (somewhere) this only for /operator/ overloading.

> -------------
>
> If a value of type T can be null, it must be declared as type Optional<T>, which may be abbreviated to T?
>
> String? name = process.args.first;
> if (exists name) {
>      writeLine("Hello " name "!");
> }
> else {
>      writeLine("Hello World!");
> }
>
> Use of an optional value must be guarded by the if (exists ... ) construct. Therefore, NullPointerExceptions are impossible.
>
> This is exactly what I suggested for D in a enhancement request.
> It seems this kind of stuff is becoming a standard in new languages.

+++

But I guess optionality could, and should, extend to non-ref types; thus, null 
is just a particular case of non-existence. And this would apply especially on 
function parameters:
    void f (int i?) {...}

Also, they should reuse '?' to mean 'exists', possibly '!?' meaning the opposite:
    void f (int i?) {
    if (? i) doWithI(i);
    if (!? i) doWithoutI();
    ...
}

> -------------
>
> Attributes and local variables are immutable by default. Assignable values must be annotated variable:
>
> variable Natural count := 0;

Immutability should be the default for locals (especialy params) in all languages.

'Natural' is great ;-)

> -------------
>
> A getter looks like a method without a parameter list:
>
> shared Natural currentValue {
>          return count;
>      }
> }

good

> Attributes are polymorphic. A subclass may override a superclass attribute. It may even override a simple attribute with a getter or vice versa!
>
> This means there is no need for explicit getter/setters until you are ready for them. This is nice.

very good

I often miss this in D. The fact that subtyping in D applies only to methods 
forces to add fake data members in supertypes (which are thus present in all 
subtypes...). I find this design crazy !!!
Same note for mixins: why do they hold only methods? A "role" to be mixed-in 
often requires both data & methods.

> -------------
>
> There is no new keyword:
>
> Counter c = Counter();

great! get rid of new in D as well

     coll = (new Coll(cap)).fill(data);
==>
     coll = Coll(cap).fill(data);

> -------------
>
> Assignment to a variable value or attribute setter is done using the := operator. The = specifier is used only for specifying immutable values:
>
> shared assign currentValue {
>      count := currentValue;
> }

If I understand you correctly, this is wrong. The operators should instead make 
distinct *creation* versus *change*:
    variable Natural count = 0; 	// create
    count := 3;			// change
    local Natural i = 1;		// cannot be changed

> -------------
>
> We may define a class method "by reference":
>
> void hello(String name) = hello;

???

> -------------
>
> A method may declare multiple lists of parameters. The method body is executed after arguments have been supplied to all parameter lists:
>
> Float add(Float x)(Float y) {
>      return x+y;
> }
>
> This is a kind of user defined and safe partial application, it's a cute idea.
>
> Providing arguments to just one parameter list produces a method reference:
>
> Float addOne(Float y) = add(1.0);
> Float three = addOne(2.0);
>
> (The point of all this is that we are able to provide all the functionality of first-class and higher-order functions without needing to resort to unnatural syntactic constructs inspired by the lambda calculus notation.)

I don't get the diff between currying & partial app. And find this feature much 
complication for close to uselessness.

> -------------
>
> There is a Named argument syntax.

A true programmer uses named args in half of all method calls; meaning, 
everywhere args' meanings are not absolutely obvious.

>  They use it for a syntax trick: A named argument invocation is enclosed in 
braces, and non-vararg arguments are listed using the name=value; syntax.

> This seems one of the most peculiar and refined parts of the syntax of this language. See slides 34-37 in the first PDF.

examples?

> -------------
>
> A class or interface satisfies zero or more interfaces
>
> shared class Character(Natural utf16)
>      extends Object()
>      satisfies Ordinal&  Comparable<Character>  {
>          ...
> }
>
> The syntax X&Y represents the intersection of two types. The syntax X|Y represents the union of two types.

Too bad, they got it wrong, like D. Should instead rip Go interfaces, which are 
structural & implicite, while still fully compile-time type-safe:

     struct File inStream {
         ...
         void write (string s) {...};
     }
     ...
     interface Writer {
         void write (string s);
     }
File is *also* a Writer, thus one can call the following on a specimen of File:
     void formatWrite (Writer w, string s, string format) {...}

More generally, any type can satisfy any number of interfaces, wherever and 
whenever they are defined (eg years after, in user code). The obligation of 
explicitely declaring interface satisfaction is both useless and blocking.

Free interfaces even provide some kind of simple generics for free (like in 
above example). And there is no need for
      ... if (is(...))
or
      ... if (isWriter!T)

===========================================
All in all, Ceylon looks like a very good imrovement. Too bad its base for 
imrovement is Java (there is no way to get light & flexible coding from there, 
you'd have to change everything ;-), and it's designed to run on the JVM. :-(

Denis
-- 
_________________
vita es estrany
spir.wikidot.com



More information about the Digitalmars-d mailing list