eclipse-archived / ceylon

The Ceylon compiler, language module, and command line tools
http://ceylon-lang.org
Apache License 2.0
399 stars 62 forks source link

Supports syntax for method chaining #4049

Open CeylonMigrationBot opened 10 years ago

CeylonMigrationBot commented 10 years ago

[@loganmzz] Fluent interfaces use a lot the method chaining. But when using inheritance its become hardy due to the type system. You must explicitly refines all the methods to restrict the return type to the current child class.

A very good features will be to implement a "this" return type. Such the compilor/type system could assume methods return the current declared type.

I suggest using "this" keyword such as "void" is used when nothing is supposed to be returned. These methods should use only "empty return" (again, such as "void" ones).

Here is a class declaration example:

class MethodChainingSample() {
   shared this first(String? str) { 
     if (str.empty) return;
     print(str);
  }
}

[Migrated from ceylon/ceylon-spec#943]

CeylonMigrationBot commented 10 years ago

[@gavinking] I don't dislike the concept, but note that so-called "fluent" interfaces aren't idiomatic Ceylon. We use named argument invocations instead.

CeylonMigrationBot commented 10 years ago

[@loganmzz] You suggest transform:

Query query = new QueryBuilder().select("x", "y").from("Coordinates").where("...");

to:

Query query = queryBuilder { select={"x","y"}; from={"Coordinates"}; where={"..."}; };

?

I'm not sure this construct can handle the cases where:

Because this an abstract discussion, I don't know if my phrases apply. Here is "stupid" sample:

new StupidApi().setName("Foo").printName().setName("Bar").printName();

Moreover, I have some doubt about the ease to write (and re-read/maintain) some kind of APIs using named arguments. As I have already said I haven't experienced this. As Java developer I think a lot like Java-way more than Ceylon-way. It's easier to learn than unlearn ;) I suppose "named-argument" construct is more usual in languages such as JavaScript ?

CeylonMigrationBot commented 10 years ago

[@FroMage] Dart's .. operator is much better than some syntax which forces you to design APIs as fluent. That operator applies the right-hand side to the previous left-hand expression.

CeylonMigrationBot commented 10 years ago

[@loganmzz] It's like a VB's with operator ? However fluent APIs can also return different kind of "handler" during the chain. Especially to structurally restrict access to some methods. Lombok generated-builders are good example. A SQL query API can also uses this logic to "fix" syntax. A select is always followed by a from which is followed optionnally by where, order by and group by. Whereas having only appears after a group by:

interface ExpressionList {
  this add(String expression);
}
interface ToQuery extends ExpressionList {
  Query toQuery();
}
interface BeforeOrderBy extends ToQuery {
  OrderBy orderBy();
}
interface BeforeGroupBy extends BeforeOrderBy {
  GroupBy groupBy();
}
interface Select extends ExpressionList {
  From from();
}
interface From extends BeforeGroupBy {
  Where where();
}
interface Where extends BeforeGroupBy {}
interface GroupBy extends BeforeOrderBy {
  Having having();
}
interface Having extends BeforeOrderBy {}
interface OrderBy extends ToQuery {}

QueryBuilder
    .select()
        .add("x")
        .add("y")
    .from()
        .add("Coordinates")
    .where()
        .add("x < 10")
        .add("y != 20")
    .orderBy()
        .add("distance(x,y,0,0)")
    .toQuery();
CeylonMigrationBot commented 10 years ago

[@simonthum] I'm using self types to achieve "this type":

shared interface TraitB<Representation> given Representation satisfies TraitB<Representation> {
    shared formal Representation modfiyB();
}

There are some rough edges but I believe that's another bug.

CeylonMigrationBot commented 10 years ago

[@PhiLhoSoft] I involuntarily +1ed this issue with the following thread: https://groups.google.com/forum/#!topic/ceylon-users/Eg6hi1-1XRI I link to it here, as I tried to give more use cases for this feature.