I suggest to add something like this to D2 Phobos (this is D1 code): template Chainable() { Chain!(typeof(this), Range) opCat(Range)(Range r) { return chain(this, r); } } Then in the body of a lazy range both Phobos ones like map, filter, zip, iota, and so on, and user-defined ones, you may add: mixin Chainable; This allows to write more natural and readable code like: iota(5) ~ filter!q{a}([1,0,3]) map!abs([1,2,-5]) ~ [10, 20] instead of more noisy: chain(iota(5), filter!q{a}([1,0,3])) chain(map!abs([1,2,-5]), [10, 20]) See also bug 5638 for an useful optimization.
Very interesting idea! In fact, it's a bit odd that we allow the generally slow array appends (due to allocations, reallocations, etc), but we use functions for chaining ranges. I wonder if Andrei would approve this. Maybe you should bring this up to the newsgroups for better awareness.
There was an attempt at getting this in phobos, that was rejected. For more information see the newsgroup post [1] and the interesting discussion in the PR [2]. Closing as WONTFIX. [1] http://forum.dlang.org/post/bcazbwztlspwzpvlrblm@forum.dlang.org [2] https://github.com/dlang/phobos/pull/3353