View source code
Display the source code in std/range/package.d from which this page was generated on github.
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using local clone.

Function std.range.chain

Spans multiple ranges in sequence. The function chain takes any number of ranges and returns a Chain!(R1, R2,...) object. The ranges may be different, but they must have the same element type. The result is a range that offers the front, popFront, and empty primitives. If all input ranges offer random access and length, Chain offers them as well.

auto chain(Ranges...) (
  Ranges rs
if (Ranges.length > 0 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void));

Note that repeated random access of the resulting range is likely to perform somewhat badly since lengths of the ranges in the chain have to be added up for each random access operation. Random access to elements of the first remaining range is still efficient.

If only one range is offered to Chain or chain, the Chain type exits the picture by aliasing itself directly to that range's type.


rs the input ranges to chain together


An input range at minimum. If all of the ranges in rs provide a range primitive, the returned range will also provide that range primitive.

See Also

only to chain values to a range


import std.algorithm.comparison : equal;

int[] arr1 = [ 1, 2, 3, 4 ];
int[] arr2 = [ 5, 6 ];
int[] arr3 = [ 7 ];
auto s = chain(arr1, arr2, arr3);
writeln(s.length); // 7
writeln(s[5]); // 6
assert(equal(s, [1, 2, 3, 4, 5, 6, 7][]));


Range primitives are carried over to the returned range if all of the ranges provide them

import std.algorithm.comparison : equal;
import std.algorithm.sorting : sort;

int[] arr1 = [5, 2, 8];
int[] arr2 = [3, 7, 9];
int[] arr3 = [1, 4, 6];

// in-place sorting across all of the arrays
auto s = arr1.chain(arr2, arr3).sort;

assert(s.equal([1, 2, 3, 4, 5, 6, 7, 8, 9]));
assert(arr1.equal([1, 2, 3]));
assert(arr2.equal([4, 5, 6]));
assert(arr3.equal([7, 8, 9]));


Due to safe type promotion in D, chaining together different character ranges results in a uint range.

Use byChar, byWchar, and byDchar on the ranges to get the type you need.

import std.utf : byChar, byCodeUnit;

auto s1 = "string one";
auto s2 = "string two";
// s1 and s2 front is dchar because of auto-decoding
static assert(is(typeof(s1.front) == dchar) && is(typeof(s2.front) == dchar));

auto r1 = s1.chain(s2);
// chains of ranges of the same character type give that same type
static assert(is(typeof(r1.front) == dchar));

auto s3 = "string three".byCodeUnit;
static assert(is(typeof(s3.front) == immutable char));
auto r2 = s1.chain(s3);
// chaining ranges of mixed character types gives `dchar`
static assert(is(typeof(r2.front) == dchar));

// use byChar on character ranges to correctly convert them to UTF-8
auto r3 = s1.byChar.chain(s3);
static assert(is(typeof(r3.front) == immutable char));




import std.algorithm.comparison : equal;
import std.typecons : Nullable;

immutable Nullable!string foo = "b";
string[] bar = ["a"];
assert(chain(bar, foo).equal(["a", "b"]));




import std.algorithm.iteration : filter;

auto range = chain([2], [3].filter!"a");

// This might happen in format!"%s"(range), for instance.


Andrei Alexandrescu, David Simcha, Jonathan M Davis, and Jack Stouffer. Credit for some of the ideas in building this module goes to Leonardo Maffi.


Boost License 1.0.