TypeInfo.init has been deprecated. This is a step towards removal of TypeInfo.init, which is necessary to resolve a name clash with the type property init. Use TypeInfo.initializer instead.

New druntime switch --DRT-oncycle allows specifying what to do on cycle detection in modules. When module cycles are detected, the default behavior is to print the cycle, and abort execution. However, in many cases, the cycles are not harmful. With the new --DRT-oncycle switch, you can effect a different behavior when cycles are detected: --DRT-oncycle=abort This is the default behavior, and will abort, printing the cycle to stderr when the first cycle is detected --DRT-oncycle=print Print all cycles that are detected to stderr , but do not halt execution. Order of initialization is arbitrarily chosen based on the order the modules are in the binary --DRT-oncycle=ignore Do not print anything, and do not halt execution. Order of initialization is arbitrarily chosen based on the order the modules are in the binary ($P As there were improvements of the cycle detection algorithm implemented within the scope of this release, previously undetected (even harmless) module dependency cycles may start to abort program execution or program may malfunction due to changed call order of module static construction/destruction. In order to preserve the program behaviour without the need to specify --DRT-oncycle command line argument, it is possible to instruct the linker by declaring the following array in the source code:) extern (C) __gshared string[] rt_options = [ "oncycle=ignore" ]; ($P For more information, please consult the D language specification, section Overriding Cycle Detection Abort in chapter 4 and chapter 28.7 Configuring the Garbage Collector.)

Implementation of std.digest.murmurhash . std.digest.murmurhash has been added. MurmurHash is a non-cryptographic hash function suitable for general hash-based lookup. It is optimized for x86 architectures. import std.digest.murmurhash; ubyte [4] hashed = digest!MurmurHash3_32_opt32([1, 2, 3, 4]);

Process creation in std.process was sped up on Posix. Previously, Posix systems would attempt to close every file descriptor from 3 to the maximum file descriptor number if inheritFDs was not specified with spawnProcess, pipeProcess, etc. std.process now uses poll() to determine which descriptors need closing.

algorithm.iteration.cumulativeFold was added. std.algorithm.iteration.cumulativeFold returns the successive reduced values of an input range. assert ([1, 2, 3, 4, 5].cumulativeFold!((a, b) => a + b).array == [1, 3, 6, 10, 15]); assert ([1, 2, 3].cumulativeFold!((a, b) => a + b)(100).array == [101, 103, 106]);

std.range.padLeft and std.range.padRight were added. std.range.padLeft and std.range.padRight are functions for padding ranges to a specified length using the given element. import std.range; import std.algorithm.comparison; assert ([1, 2, 3, 4, 5].padLeft(0, 7).equal([0, 0, 1, 2, 3, 4, 5])); assert ( "Hello World!" .padRight('!', 15).equal( "Hello World!!!!" ));

std.regex.regex now supports matching multiple patterns in one go. import std.regex; auto multi = regex([ `\d+,\d+` , `(a-z]+):(\d+)` ]); auto m = "abc:43 12,34" .matchAll(multi); assert (m.front.whichPattern == 2); assert (m.front[1] == "abc" ); assert (m.front[2] == "43" ); m.popFront(); assert (m.front.whichPattern == 1); assert (m.front[1] == "12" );

std.regex.splitter now supports keeping the pattern matches in the resulting range. import std.regex; import std.algorithm.comparison : equal; auto pattern = regex( `([\.,])` ); assert ( "2003.04.05" .splitter!(No.keepSeparators)(pattern) .equal([ "2003" , "04" , "05" ])); assert ( "2003.04.05" .splitter!(Yes.keepSeparators)(pattern) .equal([ "2003" , "." , "04" , "." , "05" ]));

findLocalMin was added to std.numeric . std.numeric.findLocalMin finds a real minimum of a real function f(x) via bracketing. import std.numeric, std.math; auto ret = findLocalMin(( double x) => (x-4)^^2, -1e7, 1e7); assert (ret.x.approxEqual(4.0)); assert (ret.y.approxEqual(0.0));

ptr property and public constructor were added to std.experimental.ndslice.slice.Slice . ptr property allows to access Slice's underlaying pointer or range. Please refer to std.experimental.ndslice.slice.Slice's internal binary epresentation before using the property. ptr property is used in Mir for sparse tensors. ndslice developer mirror in Mir will be removed as soon as LDC (LLVM D compiler) supports D version 2.072. Public constructor for Slice was added to support std.experimental.ndslice integration with other languages and libraries such as Julia language and NumPy library.

std.experimental.ndslice.slice.Slice.toHash method was added. import std.experimental.ndslice; auto a = iotaSlice(3, 7); auto b = iotaSlice(3, 7).slice; assert (a.toHash == b.toHash);

slice , shape , ndarray , and other utilities were added to std.experimental.ndslice.slice . These utility functions have been added to std.experimental.ndslice: std.experimental.ndslice.slice.makeNdarray ,

, std.experimental.ndslice.slice.makeSlice ,

, std.experimental.ndslice.slice.makeUninitializedSlice ,

, std.experimental.ndslice.slice.ndarray ,

, std.experimental.ndslice.slice.shape ,

, std.experimental.ndslice.slice.slice ,

, std.experimental.ndslice.slice.uninitializedSlice . Example: Transposing common 2D array using ndslice import std.experimental.ndslice; auto ar = [[0, 1, 2], [3, 4, 5]]; auto sh = ar.shape; auto sl = slice! int (sh); sl[] = ar; ar = sl.transposed.ndarray; assert (ar == [[0, 3], [1, 4], [2, 5]]);

std.experimental.ndslice.slice.as lazy tensor was added. import std.experimental.ndslice; auto matrix = slice! double ([2, 2], 0); auto stringMatrixView = matrix.as!string; assert (stringMatrixView == [[ "0" , "0" ], [ "0" , "0" ]]); matrix.diagonal[] = 1; assert (stringMatrixView == [[ "1" , "0" ], [ "0" , "1" ]]);

iotaSlice lazy tensor was added to std.experimental.ndslice.selection . std.experimental.ndslice.selection.iotaSlice is the fastest possible Slice. import std.experimental.ndslice; auto sl = iotaSlice([2, 3], 10); assert (sl.transposed == [[10, 13], [11, 14], [12, 15]]);

std.experimental.ndslice.selection.indexSlice lazy tensor was added. import std.experimental.ndslice; auto slice = indexSlice(2, 3); assert (slice == [[[0, 0], [0, 1], [0, 2]], [[1, 0], [1, 1], [1, 2]]]);

std.experimental.ndslice.selection.repeatSlice lazy tensor was added. import std.experimental.ndslice; auto sl = iotaSlice(3).repeatSlice(4); assert (sl == [[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2]]); auto m = 4.repeatSlice(2, 3); assert (m == [[4, 4, 4], [4, 4, 4]]);

std.experimental.ndslice.selection.mapSlice lazy tensor was added. import std.experimental.ndslice; auto s = iotaSlice(2, 3).mapSlice!(a => a * a); assert (s == [[ 0, 1, 4], [ 9, 16, 25]]);

partial support for Math Index Order was added to std.experimental.ndslice.slice.Slice . import std.experimental.ndslice; auto sl = iotaSlice(3, 4); assert (sl[2, 3] == 11); assert (sl(3, 2) == 11);

std.algorithm.mutation.swapAt was exposed std.algorithm.mutation.swapAt allows to swap elements of a RandomAccessRange by their indices.

std.range.iota 's .length property is fixed to size_t instead of the type being iterated std.range.iota's .length property is now always returned as size_t. This means if you are on a 32-bit CPU and you are using iota to iterate 64-bit types, the length will be truncated to size_t. In non-release mode, you will get an exception if the length exceeds size_t.max in your call to iota.

std.algorithm.searching.{min,max}Element have been added. std.algorithm.searching.minElement and std.algorithm.searching.maxElement are functions to search for the minimum and maximum element in a range. They support a custom map accessor. import std.algorithm.searching; import std.range; import std.typecons; assert ([3, 1, 4].minElement == 1); assert ([4, 7, 5].enumerate.maxElement! `a.value` == tuple(1, 7));

Added std.math.quantize . std.math.quantize rounds to the nearest multiple of some number. Features: The rounding method can be specified using the rfunc parameter. By default, the current rounding mode will be used, which is typically "banker's rounding".

parameter. By default, the current rounding mode will be used, which is typically "banker's rounding". Overloads are included for the common case of rounding to the Nth digit place in some base.

digit place in some base. If known at compile time, the base and exponent (digit place) can be supplied as template parameters for better performance. import std.math; assert (12345.6789L.quantize(20.0L) == 12340.0L); assert (12345.6789L.quantize!(10, -2) == 12345.68L); assert (12345.6789L.quantize!(10, floor)(-2) == 12345.67L);

Three new traits were added to std.traits . std.traits.isType, std.traits.isFunction, and std.traits.isFinal were added to std.traits. import std.traits; static assert (isType! int ); struct S {} class C {} interface I {} static assert (isType!S); static assert (isType!C); static assert (isType!I); import std.traits; void func(){} struct S { @property int prop(){ return 0; } } static assert (isFunction!func); static assert (isFunction!(S.prop)); static assert (!isFunction!( typeof (&S.prop))); import std.traits; class C { void nf() {} final void ff() {} } final class FC {} static assert (!isFinal!(C)); static assert ( isFinal!(FC)); static assert (!isFinal!(C.nf)); static assert ( isFinal!(C.ff));

std.range.generate fixed to be a proper range. std.range.generate was set up to return a different value on each call to front. In addition, popFront did nothing. This means that manipulation functions like std.range.drop did nothing. The new version uses a one-element cache to meet the expectations of the range definition. It preserves the ref-ness of the generator as well.

Final was added to std.experimental.typecons . std.experimental.typecons.Final can't be mutated directly. However references are typed with their original mutability. This is equivalent to final in Java or readonly in C#. auto a = makeFinal([1, 2, 3]); assert (a[0] == 1); a[0] = 42; assert (a[0] == 42);

std.traits.isInnerClass was added to identify nested classes with an accessible outer pointer Classes, that are nested inside other classes (and not inside functions) and that don't define any outer symbol, have an outer field which allows to get and even set the instance of the outer class they are nested in. std.traits.isInnerClass allows to identify them. The types satisfying isInnerClass are a subset of the ones satisfying isNested, as the latter includes classes and structures nested inside functions or that redefine outer. class Outer { class Inner1 { } class Inner2 { int outer; } static class Inner3 {} } static assert (isInnerClass!(Outer.Inner1)); static assert (!isInnerClass!(Outer.Inner2)); static assert (!isInnerClass!(Outer.Inner3));

std.conv.emplace no longer allows to emplace classes nested directly inside other classes without specifying a suitable outer pointer If a class is nested within another class (there's a new trait std.traits.isInnerClass to check for this condition), emplace requires now the outer class instance as additional mandatory parameter. Before this change, emplacing did not require this parameter and access to variables of the outer class resulted in segmentation faults. class Outer { int x; class Inner { auto getX() { return x; } } } Outer outer = new Outer(); auto inner = buf.emplace!(Outer.Inner)(outer); auto x = inner.getX();

A runtime switch for selecting the GC implementation was added. This allows to select a GC at program startup. ./my_d_exe --DRT-gcopt=gc:conservative # use conservative GC ( default ) ./my_d_exe --DRT-gcopt=help # list available GC options See gc_config for more information about gcopt. In a future release it should be possible to extend the list of GCs by linking with an alternative one.