Search code examples
syntaxcompiler-constructionprogramming-languagestheoryproof

Should languages offer a syntactic alternative to method chaining?


DOM, ThreeJS and now canvas have all had libraries written to provide method chaining (perhaps most familiar from jQuery). Chaining has also been used in core C libraries.

These fluent interfaces avoid unnecessary repetition of the object of interest. Compare:

var cx = cq(640, 480);
cx.drawImage(image, 0, 0);
cx.fillStyle("#ff0000");
cx.fillRect(64, 64, 32, 32);
cx.blur();
cx.appendTo("body");

to:

cq(640, 480)
  .drawImage(image, 0, 0)
  .fillStyle("#ff0000")
  .fillRect(64, 64, 32, 32)
  .blur()
  .appendTo("body");

It could be argued that the former "traditional" style is over-verbose, and violates DRY.

To avoid repetition of the cx variable, some languages allows us to express a set of calls using a with statement:

with ( cq(640, 480) ) {
    drawImage(image, 0, 0);
    fillStyle("#ff0000");
    fillRect(64, 64, 32, 32);
    blur();
    appendTo("body");
}

Whilst JavaScript's with statement is dangerous in the presence of typos, Scala's more restrictive with statement is safe to use, and Haxe also offers import of functions to the local scope through its using keyword. Unfortunately Java and C offer no such shortcut, forcing us to choose between traditional code or chaining.

Should language authors consider a safe with-like statement as an alternative to method chaining, or are there good reasons to avoid it? If such a feature is desirable, what form should it take?


One concern I have with method chaining is that the ambiguity about the subject of the later calls in the chain may prevent optimizations previously available when compiling code where repeated use of cx was explicit. For example, if the calls to cx's methods do not overlap, they could be parallelized, but it may be harder for the compiler to be sure of this in the chained example.

Another disadvantage, as rambo points out below, is that methods designed for chaining are unable to return any other value, which seems rather wasteful.


Solution

  • It's called Method Chaining. It frequently appears in the discussion of a Fluent Interface.

    Perhaps the biggest drawback is that you cannot return a value, because you must return the implied object to allow chaining. Not all methods make sense without returning a value, and then you end up with an interface that has some chainable methods, and some not.

    I don't think it indicates a missing language feature, because there's no serious loss of functionality without it. But language support for somethign like this might be interesting.