2

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.

Gama11
  • 31,714
  • 9
  • 78
  • 100
joeytwiddle
  • 29,306
  • 13
  • 121
  • 110
  • 2
    It's not a missing language feature - jQuery is just JS, so obviously JS allows it... – nnnnnn Jan 05 '13 at 02:00
  • 4
    IIRC, it's called chaining. You just `return this` after each method, which allows you to keep calling methods on your object over and over again. You can do it with pretty much any language that supports OOP. It's nice, but keep your use sane (i.e. don't have multi-line chains on one object). – Blender Jan 05 '13 at 02:00
  • 1
    1. I don't know if there is an exact name for it, but I believe most people call it chaining, or function chaining. 2. It's a nice little feature to have, but in most cases, same goes with jQuery, it's a matter of user preference; they have the option to chain or not to chain. – kennypu Jan 05 '13 at 02:02
  • Thanks. Would you recommend writing libraries for languages other than JS in chaining style, or in the traditional style? It seems to have become very popular, but I'm not sure if it's desirable. – joeytwiddle Jan 05 '13 at 02:03
  • 1
    @joeytwiddle: Implementing it doesn't replace or really affect the "traditional" style at all, so if you want to, why not? – Blender Jan 05 '13 at 02:05
  • I personally like it, it prevents a lot of repetitive typing. instead of `var obj = new Obj(); obj.doSomething(); obj.doSomethingElse();` it can be `var obj = new Obj().doSomething().doSomethingElse();` it's not a huge thing, but if you have multiple objects in this case, you can easily tell them apart in the later. – kennypu Jan 05 '13 at 02:06
  • 1
    @joeytwiddle Totally depends on how the library will be used. (And, obviously, determines how the library *will* be used.) Some things just make more sense when read as a "fluent interface", and IMO some things don't. – Dave Newton Jan 05 '13 at 02:06
  • One concern: Naive compilers might find optimization harder on chained expressions. From a compiler's point of view, any of the chained calls could return an entirely different object at some point in the expression. In the traditional style, clearly the same object is being called every time. This might impact compile or run-time optimization in some languages. – joeytwiddle Jan 05 '13 at 02:14
  • 1
    This has less to do with JavaScript's shortcomings than it has to do with its "Good Parts". Whether this style is the "best practice" isn't even important; a good language has the **minimal** constructs to allow for a variety of expressive styles. Feature overload in a language can lead to lots of confusing or insecure behavior. Case in point: use of the `with` statement, while [occasionally useful](http://stackoverflow.com/questions/61552/are-there-legitimate-uses-for-javascripts-with-statement), is usually a [bad idea](http://yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/). – namuol Jan 05 '13 at 02:36
  • The point about languages seeking to be minimal is a fair one. But when it bloats the code written in the language, or forces us to convolute our libraries, perhaps there may be cause to bend that rule? – joeytwiddle Nov 25 '13 at 22:16

2 Answers2

2

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.

goat
  • 31,486
  • 7
  • 73
  • 96
  • Interesting that Scala uses its own kind of `with` statement to achieve this. HaXe actually provides some convenient importing through the [`using`](http://haxe.org/manual/using) keyword, but that may only be for static functions. – joeytwiddle Jan 05 '13 at 02:30
1

It's not a missing language feature, instead it is a language feature. If it was missing then it wouldn't be possible to do it in Javascript.

This is not syntax. Instead, it is a design pattern. And it's called chaining. In fact, there are libraries that implements chaining alone. DED|Chain for example is a library that implementes chaining for YUI2 which was not written with chaining in mind.

A specialized syntax like with (which is indeed implemented in js like you mentioned) is problematic regardless what you call it (you suggested using the name "on" but it will have all the problems that "with" has).

The problem is, inside a code block, it can be confusing to a human (the compiler is not confused) weather the method or variable refers to method of the object or if there was a typo and it accidentally refers to a global variable or a variable that is not part of the object but is in scope.

Of course, you could say that it is the job of the programmer to make sure that they don't use variable and method names that may cause confusion. In which case you can use with.

slebetman
  • 109,858
  • 19
  • 140
  • 171
  • I suppose my `on` statement would differ from `with` in that it would demand every line be an access to a property of the object. It would strictly deal with the repeated `cx.a(); cx.b();` issue, and would allow only calls or assignments. For example: `on (elem.style) { position="fixed"; top=20; left=40; setTimeout();/*not_found*/ }` – joeytwiddle Jan 05 '13 at 02:22