TDPL Erratadlogo.png

The list below is created by readers and D users like you and maintained by the book's author.

All code samples can be downloaded off here (also refer to the related announcement). Get individual examples or to get them all. The examples that currently don't work as expected with the reference implementation are in the "shouldwork" subdirectory.

To add entries, please contact Andrei. Don't forget to specify the printing, which can be seen at the bottom of the copyright page (the one just before Contents) and reads like "First printing, May 2010".


PrintCurrent textCorrectionSubmitter
xxv 1 justfy justify Björn Fahller
5 1

%i for integers

%d for integers Andrei Alexandrescu (on behalf of Roel)
5 1

The code snippet showing "foreach" is only indented by 2 spaces instead of the customary 3.

Several other code samples use other indent than 2-space (more sent via email). Paul Jurczak
6 1

the code sample above also introduced the if statement

there is no if statement above Benjamin Shropshire
8 1

the large example should use size_t instead of uint

  Andrei Alexandrescu (on behalf of bearophile)
8 1 The use of dictionary[word] in the dictionary code sample does not compile with dmd 2.050+. Instead, the code should use dictionary[word.idup] or dictionary[to!string(word)] to convert word of type char[] to type string, which is required by the dictionary. Also, splitter is in module std.algorithm, not std.string. Andrei Alexandrescu (on behalf of Caligo and Chris Saunders)
8 1 foreach(word; split(strip(line))) Should be foreach(word; splitter(strip(line))) for consistency with the example on page 8 and for better efficiency. Michal Mocny
8 1 The example doesn't compile on 64-bit because size_t is not convertible to uint. Change definition of dictionary from uint[string] to size_t[string], or cast newID to uint. Jonathan M Davis
12 1 idup used without a prior definition   Amaury Sechet (deadalnix)
12 1 Speaking of state, let's write a recursive implementation of binarySearch that doesn't reassign index at all: Replace "index" with "input" Geert Fannes
12 1 if ( mid > value ) return binarySearch( input[0 .. i] );

if ( mid < value ) return binarySearch( input[i + 1 .. $] );

if ( mid > value ) return binarySearch( input[0 .. i], value );

if ( mid < value ) return binarySearch( input[i + 1..$], value );

Byron Heads
12 1 the compiler modifies the argument the compiler modifies the arguments Andrei Alexandrescu
13 1 Doesn't mention the need to import std.algorithm to gain access to the sort function. 'Add `, std.algorithm` to the first line.' Bernard Helyer
14 1 In your hamlet.txt, the King has only 103 lines (as you call them), the ones where the line starts with "  King. ". There are 4 more lines that start with "    King. " which correspond to the King inside the play inside the play. The rest up to the 116 you mention are occurrences of "King." in other characters' lines.   Horia Toma
16 1 The last paragraph in the code example is not added

Add right after the loop:

    if (!currentParagraph.empty) addParagraph(currentParagraph, info);

Tim Marston
16 1 import std.ctype; import std.uni; or import std.ascii; Louis Wust
16 1 isalpha (two occurrences) isAlpha Louis Wust
17 1 better makes a copy of it better make a copy of it Philip Zigoris
17 1 "... null for arrays ..." It's unclear at this point what null means for an array. David Vickrey
18 1 Text mentions std.algorithm find, but code uses haystack.find(needle). At this point the reader has not been explained that both forms work. Michal Mocny
18 1 tolower toLower Lous Wust
18 1 The symbol split needs prefixing, i.e. std.regex.split. Otherwise compilation fails with ambiguity error between std.regex.split and std.string.split See also Jesus Alvarez
19 1 After fixing the bug on page 16, Fort 74 61 should be replaced with Fort 138 102.   Andrew Talbot
20 1 Word count is a bit higher because split adds empty strings because some lines have a separator string on the ends.

Add this line after split:

words = filter!(a => !a.empty)(words).array();


Dennis Cote
21 1 The name "postprocess" used in text should be camel cased (postProcess) just like it is in code. Also occurs on pages 22-25.   Patrick O'Brien
22 1 stats example will not compile and run as is readf should be stdin.readf, and need to add a try/catch for std.conv.ConvError. Dan Renfro
22 1 std.contracts std.exception  
22 1 Object.factory.Object four lines from the bottom of the page. There is confusion between the use of "." in code and typographically. Michal Mocny
22 1 The bottom of page 22 and the top of page 23 refer to Max, which hasn't been yet defined. For clarity the references should be changed to Min. Thanate Dhirasakdanon
23 1 aside from a slight change in accumulate, everything is exactly the same The member needs to be initialized to -double.max (and possibly renamed) Eitan Frachtenberg
24 1 Deprecation: overriding base class function without using override attribute is deprecated (stats.Average.accumulate overrides stats.IncrementalStat.accumulate) Must use 'override' on all methods in the abstract class, not just methods declared 'abstract' Darkfeign
25 1 Skipped over accumulate() function for class Average. As above, also needs to be declared as overriding abstract function accumulate(). Darkfeign
26 1 In D, slicing could never occur. This should probably be: In D, C++'s damaging slicing could never occur.

Andrej Mitrovic

26 1 "Value semantics alone preclude, for example, ..." Should clarify that an array member in a struct makes the struct non-value. David Vickrey
26 1 makes a systematic approach takes a systematic approach

Patrick O'Brien


1 List of keywords Keywords immutable, lazy, pure, nothrow, and shared are missing (more detail) Jonathan M Davis
32 1 Integral literals Octal literals have been removed from the language and replaced with a standard library facility std.conv.octal. Vladimir Panteleev
35 1 String WYSIWYG literals Delimited WYSIWYG string literals are missing Vladimir Panteleev
36 1 The ASCII values for backspace, formfeed, line feed and carriage return seem to be given in octal.   Jos
39 1 "Strings are a particular kind of arrays featuring their own..." Either "Strings are a particular kind of array featuring..." or "Strings are particular kinds of arrays featuring..." Darkfeign
39 1 you can suffix a string literal with c, w or d, which, similar to the homonym character literal suffixes, force the type. you can suffix a string literal with c, w or d, which, force the type. char literals make no reference to suffixes Benjamin Shropshire
39 1 Dyslexic representation of the Avogadro constant. It is 6.022e23 and not 6.023e22 as presented in the book.   Horia Toma
40 1 This chapter's sole preoccupation This section's sole preoccupation Patrick O'Brien
42 1 left-hand side operator left-hand side operand Zbigniew Radosz
44 1 text mentions "least significant" and "most significant" byte and uses lsByte and hsByte use msByte instead of hsByte Patrick O'Brien
44 1 Figure 2.3: Implicit integral conversions. The figure shows both integrals and floating-point types. Geert Fannes
48 1 Error: can only declare type aliases within static if conditionals or static asserts Possibly clarify these requirements for declaring aliases inside of is(), though compiler message is clear enough. Darkfeign
49 1 Bullet 4 mentions "A kind is one of the following keywords: ..." and is missing "return" while it does appear in table 2.4. Also, the order of keywords mentioned and table listing is not the same (is there any ordering/grouping?).   Michal Mocny
49 1 "A kind is one of..." "A kind can be one of..." There also seem to be a few mismatches with the online documentation, e.g. the inout keyword. Andreas Guðmundsson
50 1 "evaluating postincrement or postdecrement increments" "evaluating postincrement or postdecrement modifies" Eli Sternheim
50 1 If the indexing expression is on the left-hand side of an assignment operation (e.g., arr[i] = e) and a is an associative array arr is an associative array, not "a" Andrej Mitrovic
50 1 Section The text implies that "arr[i] is the ith (zero-based) element of... associative array arr", which is incorrect. Rephrase Michal Mocny
53 1 (see the definition of nonzero 46) "on page" should be inserted Geert Fannes
54 1 ... so 7 % 3 yields 1 and -7 / 3 yields -1. ... so 7 % 3 yields 1 and -7 % 3 yields -1. Andrew Nwawudu
56 1 Section 2.3.11 In the first code block table["hello"] = 0; should be = 1;   Michal Mocny
57 1 a is c && writefln("Indeed... not the same"); a is c && writeln("Indeed... not the same"); Andrej Mitrovic
58 1 std.c.fenv core.stdc.fenv (also correct the index) Patrick O'Brien
60 1 1. If a and b have the same type, ... 2. else if a and b are integrals, ... 6. else try implicitly converting a to b's type and b to a's type; 1. If b and c have the same type, ... 2. else if b and c are integrals, ... 6. else try implicitly converting b to c's type and c to b's type; Cassio Neri
60 1 a notch tighter a notch above Patrick O'Brien
60 1 numbered items 2 and 3 use "integral" as a noun should be "integral type" as elsewhere in the book Patrick O'Brien
62 1 Increment/Decrement Preincrement/predecrement Patrick O'Brien
63 1 In-place exponentiation is missing   Zbigniew Radosz
63 1 modulo modulus Patrick O'Brien
67 1 a colon present by itself is not a statement a semicolon present by itself is not a statement Andrew C Edwards
68 1 2nd example on page Text says "If you instead want to bind the else to the first if..." but the braces in the example that follows bind it to the second if. Jonathan M Davis
68 1 The enum syntax is used without having been introduced.   Michal Mocny
69 1 See, the numeric type... See, the Numeric type... Patrick O'Brien
69 1 introduced inside a pair of { and } braces introduced inside an additional pair of { and } braces Patrick O'Brien
70 1 ...for example, we could define numeric globally ... ...for example, we could define Numeric globally ... Karim Naqvi
70 1 Perhaps it would be good to mention static if {} else static if {} else {} chain.   Zbigniew Radosz
72 1 This arguably suboptimal behavior was decided in order to... This arguably suboptimal behavior was chosen in order to... Patrick O'Brien
74 1

"Any and all of ‹decl-expr›, ‹expr₁› and ‹expr₂› can be missing;"

In fact , if missing, must be replaced by a semicolon. Martin von Gagern
75 1 Chapter 12 will deal with the latter case, Chapter 12 will deal with the last case, Andrew Talbot
76 1 ref counts on and exact match of representation ref counts on an exact match of representation Jonathan M Davis
76 1 ...ref counts on and exact match... Replace "and" with "an" Geert Fannes
78 1 Both statements accept an optional label, which allows specifying which exact state­ment to effect. Both statements accept an optional label, which allows specifying which exact state­ment to affect. Patrick O'Brien
80 1 The Pascal-inspired with statement allows working on a specific object comfortably. The Pascal-inspired with statement allows code to work on a specific object comfortably. Patrick O'Brien
81 1 Should explain what happens with locals hidden by the "with" statement.   Michal Mocny
82 1 All controlled statements must be block statements; that is, they must be enclosed by braces. The statement is incorrect and should be removed. C++ has that restriction. D does not. (more detail) Jonathan M Davis
82 1 The first type that is or a class derived from it The first type that is or a superclass of it Simen Kjaeraas
82 1 strings known during compilation in D expressions strings known during compilation into D expressions Russel Winder
84 1 too large tables may actually become slower very large tables may actually become slower Patrick O'Brien
87 1 The lowering of scope(failure) is almost identical to that of scope(exit) The lowering of scope(failure) is almost identical to that of scope(success) Eitan Frachtenberg
88 1 std.file.rename(... -> Error: undefined identifier 'file' add std.file to import list. Darkfeign
88 1 std.contracts std.exception  
89 1 Bibentry [12] links to D 1.0 assembler.   Michal Mocny
90 1 In the "for" statement description, "a value declaration" is mentioned twice.   Zbigniew Radosz
94 1 int.init = 0 int.init == 0 Patrick O'Brien
94 1 After the code block foreach ( ref ... ), you write "The ref informs the compiler that we want to reflect assignment...". I think the word "reflect" is a poor work choice, since, although grammatically correct, one could easily deduce that ref stands for "reflect", and don't think that is correct.   Michal Mocny
98 1 "... the hashed area is inaccessible to it." Replace "hashed" with "hatched". The hatched area is only visible as blank squares on the Kindle version, and barely visible on paper. Paul Jurczak
101 1

Array expansion explanation suggests in a[] == ++i the right-hand side expression will be evaluated for each individual assignment,but that's not the case.

Text should clarify that scalars are only evaluated once in array expressions. Similarly, the case when the right-hand side slice is shorter than the left-hand side should be clarified. Shachar Shemesh
103 1 so write "no palindrome" and bail out. so write "not palindrome" and bail out. Andrew C Edwards
103 1 Only if all tests succeed and args got shorter than two elements (the program considers arrays of zero or one element palindromes), the program prints "palindrome" and exits. Only if all tests succeed and args get shorter than two elements (the program considers arrays of zero or one element palindromes), [will/does] the program print "palindrome" and exit. Andrew C Edwards
103 1 "Expanding" section does not explain how to have two reference to the same array even if the array does expand Should e.g. illustrate the use of a pointer? David Vickrey
104 1 "...guaranteed good average performance..." is vague Text should specify whether it's O(1), an implementation detail, etc. In the latter case, for cases that need the amortized O(1) guarantee, it would be nice to know whether an insert would trigger an expansion, allowing some manual control over the amount of expansion (say, by assignment to length).
Shachar Shemesh
106 1 The two "// Shrink" comments on the page are on the assert() lines. However they should be moved each one line above, because that's where the shrinking occurs.
Roberto C. B. Ballona, David Berger
109 1 Section 4.2.3 -- the 2nd box mentions that assigning a slice to int[6] copies by value, but it would be clearer if the text above said this as well (keep in mind that it's not until the next section, 4.2.4, where we find out that int[N] has value semantics).   David Vickrey
112 1 "...there's one array to keep per column." "...there's one array to keep per row." Jaewon Jung
114 1 Second paragraph: "[associative arrays]... possible to map a value of a different type..." I would change that to "of another type" since types need not necessarily be different.   Michal Mocny
114 1 Section 4.4.1 first paragraph, last sentence "The type of aa.length is size_t" -- this statement was just said in the first sentence.   Michal Mocny
115 1 "Unicode allocates no valid characters in the range 0xD800 through 0xDBFF" The upper bound of the range should be 0xDFFF. Martin von Gagern
116 1 last line of example 1: assert(a2["Sam"] == 3.5; // versa should read: assert(a1["Sam"] == 3.5; // versa Andrew C Edwards
117 1 it is preferable to iterate with foreach instead of fetching keys of values it is preferable to iterate with foreach instead of fetching keys or values Alix Pexton
117 1 "The program above will print" "The program above might print" because the order of keys is undetermined. See also the related assert. David Vickrey
117 1 assert(keys == [ -1.5, 0.5, -0.5 ]); may fail because the storage order is implementation defined. Perhaps use sort on the keys. Lambert Clara
117 1 "...must define two special methods, opHash and opCmp." "...must define two special methods, toHash and opCmp."  H.S. Teoh
117 1 User-defined types do not need to define opHash and opCmp, they have default implementations. Also, technically opCmp is not needed since druntime no longer uses trees. opEquals is only called if e.g. two hash tables are being compared.   Peter Williams
124 1 [H][a][l][l][å][,][ ][V][ä][r][d][!] [H][a][l][l][å][,][ ][V][ä][r][l][d][!] (värd means worth, not world) Simen Kjaeraas
124 1 As such, the pointer does not have information on whether the chunk starts and ends. Please rephrase. Geert Fannes
125 1 "apt as cursors" "act as cursors" Zbigniew Radosz
125 1 "of an array with a.ptr" "of an array arr with arr.ptr" Eli Sternheim
129 1 Table 4.5 does not include a.byKey() and a.byValue().   Alix Pexton
129 1 In first table row replace t1, ti with k1, ki respectively   Jaewon Jung
133 1 Unittests only check for length - they should check for actual content assert(a[0 $ - find(a, 3).length] [ 1, 2 ]); Paul Jurczak
136 1 "// Returns divisor by value" "// Returns quotient by value" Zbigniew Radosz
143 1 "For our two find versions, the corresponding if clauses are never true for the same arguments" That's too strong - a type may define opEquals to compare a T and a T[], which would undo the assertion. Martin von Gagern
143 1 The first unittest fails due to representational differences between float and double. Use e.g. int and long Abid H. Mujtaba
143 1 "For our two find versions, the corresponding if clauses are never true for the same arguments." This may be misunderstood as find(x, x). Paul Jurczak
144 1 Three equally specialized functions: either could be called Three equally specialized functions: each could be called Andrew Talbot
146 1 In paragraph starting with "Now, what happens when transmogrify(int)..." The three references to "transmogrify(int)" should be replaced with "transmogrify(uint)". Jaewon Jung
146 1 The transmogrify(uint) overload in calvin.d is ... The transmogrify(uint) overload in hobbes.d is ... Cassio Neri
148 1 First code snipped is missing an import import hobbes; Andrej Mitrovic
148 1 Second code snippet: missing alias to susie. The code must alias all modules with overloads. alias susie.transmogrify transmogrify; Andrej Mitrovic
149 1 'assert(b == [-5, 3, -4]);' could be added to the unittest   Zbigniew Radosz
150 1 This example does not compile: 
auto f = (int i) {};
assert(is(f == function));
There are two errors here, one in the book and one in the compiler. The book should use typeof(f) instead of f. Track bug-related information at Paul Jurczak
153 1

d = finder(10);

assert(d[1, 3, 5, 7, 9]) == []);

Better written as:

assert(finder(10)([1, 3, 5, 7, 9]) == []);

Paul Jurczak
158 1



Paul Jurczak
161 1 to!string(arg0), to!string(arg1), to!string(arg2), to!string(arg3) to!string(a0), to!string(a1), to!string(a2), to!string(a3) Andrew C Edwards
162 1 forwards four, not two, arguments to write forwards four, not three, arguments to write


Roberto C. B. Ballona
163 1 Last paragraph before Please insert explanation on why tuples do not have literals. Geert Fannes
174 1 regular variables for m, a and b. regular variables for m, a and c. Andrew Talbot
179 1 The third box from the top seems like an internal unit test for the example above it (use of __traits(compiles, …)).   David Nadlinger
181 1 assert(t.a == 0.4 && isnan(t.b)); assert(t.a == 0.4 && isNaN(t.b)); Andrew Talbot
182 1 auto t = new Test(5);

...should be followed by assert(t.b == 5);

Benedek Thaler
185 1 The code below efficiently initializes a fixed size array with 0.0, 0.1, 0.2,..., 1.28: The code below efficiently initializes a fixed size array with 0.0, 0.1, 0.2,..., 12.7: Alix Pexton
188 1 Last line in the first example: assert( is null); assert( !is null); Andrej Mitrovic
189 1 initialization orderHere's how the ordering works. Here's how the ordering works. The extra words are an index term that spilled into the main text. Alix Pexton
189 1 MA imports MB. Then A's static class constructors run before B's.

MB imports MA. Then B's static class constructors run before A's.

MA imports MB. Then B's static class constructors run before A's.

MB imports MA. Then A's static class constructors run before B's.

Andrej Mitrovic
191 1 auto color = c.bgColor();   // call a contact method auto color = c.bgColor();   // call a friend method Andrej Mitrovic
191 1 (in this case, currentBgColor) currentReminder is also a state variable introduced by Friend. Geert Fannes
196 1 being scope inside a class being scope inside a class Andrew Talbot
198 1 "If you've used Java and C#, final is immediately recognizable because it has the same semantics in those languages." Only Java has final, C# instead has the equivalent keyword sealed. Q.
199 1 class PostUltimateWidget : Widget { ... } class PostUltimateWidget : UltimateWidget { ... } Alix Pexton
208 1 Last line of example 2: return text == that.text; return text == that2.text; Andrej Mitrovic
208 1 tw == w && w != tw breaks reflexivity In fact it breaks symmetry. Jens Mueller
210 1

"x <= y is the same as !(y > x)"

"x <= y is the same as !(y < x)" Zbigniew Radosz
215 1 Last line of example 2: override void doUntransmogrify() { ... } This method does not override any interface methods, change to: void doUntransmogrify() { ... } Andrej Mitrovic
216 1 enforce() is undefined Missing import std.exception; Andrej Mitrovic
216 1 "...goes to Transmogrify.thereAndBack, or..." "...goes to Transmogrifier.thereAndBack, or..." Jaewon Jung
217 1 Example 2 BrokenInTwoWays should implement Transmogrifier. Simen Kjaeraas
219 1 class Rectangle : RectangularShape The Rectangle class has already been defined as the Base class for all the derived classes in the example. A different name should be used for the class that implements RectangularShape. Andrej Mitrovic
220 1 It is mentioned that "you can reuse the abstract keyword in a manner similar to a protection specifier (§6.7.1 on page 200)" and follow it with an example of an "abstract { ... }" block. However, using blocks to specify such an attribute scope has not been mentioned before in the book and comes as a surprise. Especially, it is not mentioned in §6.7.1 on page 200. This caused some confusion on my part.    Andreas Kirsch
228 1 Then we define Sprite3 to implement ObservantActor and VisualActor: Then we define Sprite3 to implement HyperObservantActor and VisualActor: Alix Pexton
232 1 StorableShape example does not compile Refer to for details. Joseph Rushton Wakeling
234 1 The discussion of Parameterized Classes and Interfaces doesn't mention anywhere the need to import std.array to gain access to the empty, back, and popBack functions as used in StackImpl. Add std.array; to the first line. Andrew C Edwards
235 1 Java and C# use heterogeneous translation for their parametrized types. As far as I know Java uses homogeneous translation. The Integer in LinkedList is erased, and LinkedList doesn't even compile. Enrico Kravina
244 1

"The presence of at least one constructor disables all of the field-oriented constructors discussed above"

Field initialization with {} syntax was never discussed.

Shachar Shemesh
248 1 …, again this(this) is invoked for the field w of field w2. …, again this(this) is invoked for the field w1 of field w2. David Nadlinger
248 1 // this(this) called for b.w // this(this) called for b.w1 Andrej Mitrovic
249 1 // this(this) for d.w2.w // this(this) for d.w2.w1 Andrej Mitrovic
256 1 Discuss whether opAssign should take const ref or auto ref   Ashish Myles
263 1 First code example assumes that int.sizeof == size_t.sizeof Make c of type size_t or change the last assert in fun. (Beware of alignment issues, too.) Timon Gehr
267 1 Figure 7.2 Hatched area is barely visible. Geert Fannes
267 1 "hashed areas", "hashed bytes" "hatched areas", "hatched bytes" Andrew Talbot
269 1 You may use align with an entire class definition: You may use align with an entire struct definition: Ashish Miles
270 1 specify the desired initializer in brackets specify the desired initializer in braces Andrew Talbot
271 1 std.contracts std.exception  
271 1 many uses of union actually use sounds awkward, rephrase Andrew Talbot
271 1 manipulation manipulations Andrew Talbot
272 1 Tag._void Tag._tvoid Jonathan Amsterdam
273 1 void f(ref double x) void fun(ref double x) Andrej Mitrovic
276 1 You refer to a mixin expression as "the not-yet-introduced element above is ....". The mixin expression has been introduced on page 47 in fact. The index also only mentions page 267 for the "mixin expression". The reference to page 47 is part of the general "mixin" index entry. Maybe the "mixin expression" index entry can be changed to include the reference to page 47 as well, or maybe you could merge everything into a single "mixin" index entry, and update the text.   Andreas Kirsch
278 1

Add note about "adding" to alias after its definition. It was not entirely clear that an alias also covers overloads not yet defined at the time of the alias.

  Shachar Shemesh
279 1 struct /* or class */ Select2(bool cond, T1, T2) { // Or class struct Select2(bool cond, T1, T2) { // Or class Alix Pexton
287 1

const was actually introduced by C++ circa 1983, and migrated to C as part of ANSI C. The book suggests it was the other way around.

  Shachar Shemesh
288 1 immutable expresses absolute, context-dependent immutability. immutable expresses absolute, context-independent immutability. Jonathan M Davis
288 1 immutable expresses absolute, context-dependent immutability replace "dependent" with "independent" Geert Fannes
289 1 missing closing parenthesis: static assert(is(typeof(origin.x) == immutable(int)); static assert(is(typeof(origin.x) == immutable(int))); Andrej Mitrovic
290 1 ds[1] = 4.5; // ? ds.payload[1] = 4.5; // ? Andrej Mitrovic
294 1
Nit: In the immutable constructor for List, you can do it using a loop just by iterating backwards through data[] and keeping track of the tail (just the loop version of what the recursion is doing).  Arguably less elegant, but probably more efficient (and arguably simpler).
  David Vickrey
295 1 "Arrays and pointers that refer to types that have no mutable indiraction have no mutable indirection." This is okay for the base case of the algorithm but not for the recursive step. Text should clarify that. Jaewon Jung
300 1 "enforce" is used without having been defined   Shachar Shemesh
307 1 § 9.4 discussed nothrow functions § 5.11.2 discussed nothrow functions Alix Pexton
309 1 catch Exception e, while e = != null catch Throwable e, while e = !is null Andrej Mitrovic
309 1 code: import std.contracts, throw new CustomException("fun", x); import std.exception, throw new CustomException("x is less than 0: ", "fun", x); Andrej Mitrovic
318 1 std.contracts std.exception  
318 1 throw new CustomException("fun", x); throw new CustomException("Negative value ", "fun", x); Michal Mocny
325 1 D defines such a function in module std.contracts D defines such a function in module std.exception Andrej Mitrovic
326 1 import std.contracts; import std.exception; Andrej Mitrovic
327 1 std.contracts std.exception  
327 1 ..standard library function std.contracts.enforce(false), import std.contracts ..standard library function std.exception.enforce(false), import std.exception Andrej Mitrovic
330 1 // Require str // Require spec Jonathan Amsterdam
335 1 void push (T value) in { assert(!empty); } void push (T value) Alix Pexton
336 1 final void push (T value) { enforce(!empty); pushImpl(value); enforce(value == topImpl()); } final void push (T value) { pushImpl(value); enforce(value == topImpl()); } Alix Pexton
336 1 Replace assert with enforce in pop()   Zbigniew Radosz
338 1 In the enumeration of the items that a module may start with, comments are missing. A module may start with a comment which has '/' as its first character (that character, being ASCII, doesn't affect adversely the autodetection process). Vladimir Panteleev
340 1 importThe order of importing modules is irrelevant. The order of importing modules is irrelevant. Alix Pexton
345 1 Add an index entry here for import, static   Jonathan M Davis
357 1 else if (info.dwMajorVerson == 6 && info.dwMinorVersion == 0) { winVersion = WinVersion.preVista; } else { winVersion = WinVersion.preVista; else if (info.dwMajorVerson == 6 && info.dwMinorVersion == 0) { winVersion =; } else { winVersion = WinVersion.postVista; Alix Pexton
357 1 The initialization of OSVERSIONINFOEX with a constant is confusing.   Michal Mocny
356 1 "entire applications may be written entirely in SafeD." "entire applications may be written in SafeD." Eli Sternheim
357 1 Cut and paste error in the first code example - all assignments are preVista.   Jaewon Jung
360 1 Using PreFinalRelease is correct, but it would be nice to replace it with FinalRelease to integrate with the previous example.   Andrew Talbot
361 1 Attempting to set a version in both the command line and a source file is, again, in error. Attempting to set a version in both the command line and a source file is, again, an error. Alix Pexton
361 1 No mention of the global debug flag.   Andrei Alexandrescu (on behalf of JRM)
361 1 The debug was defined The debug declaration was defined Jonathan Amsterdam
362 1 std.contracts in the standard modules summary table This should be replaced with std.exception Andrej Mitrovic
368 1 Missing semicolon in opUnary method mixin(op ~ "value;"); Andrej Mitrovic
368 1 Unary "-" should throw on int.min   Timon Gehr
370 1 In the first gray box, the struct is named T, but T is also the name of the template parameters in the opCast.   David Vickrey
372 1 Broken return statements in opBinary "Addition", "Subtraction" and "Multiplication" All three should be fixed with: return CheckedInt(result); Andrej Mitrovic
379 1 The method names substitute "slice" for "array" throughout Replace "array" with "index" Geert Fannes
382 1 inorder traversal of the tree preorder traversal of the tree Eric Lawless
383 1 // Calls object.opApply(k, v) Comment is mistaken because opApply passes a delegate, too. Michal Mocny
384 1 static if (op == "+") { return opSubtract(rhs); } static if (op == "-") { return opSubtract(rhs); } Eric Lawless
385 1

underscoresToCamelCase does not compile on latest dmd (toupper unknown and unknown import), and is not runnable at compile time.

  Shachar Shemesh
386 1 a.opDispatch!"do_something_cool"(5, 6) has a trailing quote that needs to be removed. By the way, opDispatch is ridiculously cool. Michal Mocny
387 1

Variant opDispatch(string m, Args)(Args args...) {

should have the "..." in the variadic list:

Variant opDispatch(string m, Args...)(Args args) {

 Jose Sevilla Ruiz
387 1

Variant(Dynamic, Variant[]) {

The "delegate" keyword is required, and the "..." must be present in the signature.

delegate Variant(Dynamic, Variant[]...) {

387 1

obj.addMethod(“sayHello”, Variant(Dynamic, Variant[]) { writeln(“Hello World!”); return Variant(); });

obj.addMethod(“sayHello”, delegate Variant(Dynamic self, Variant[] args…) { writeln(“Hello World!”); return Variant(); });

Better yet, the writeln call should be writeln(args[0]) and the invocation should be obj.printMsg("Hello, world!") to illustrate how parameter passing works.

Jose Sevilla Ruiz
389 1 a.opIndexUnary(b1, b2, ..., bk) a.opIndexUnary""(b1, b2, ..., bk)  Jaewon Jung
389 1  'a[] a.opSlice()' / 'a[] a.opSliceUnary!""()' items are missing in Table 12.1.   Jaewon Jung
393 1 Also, the speed gap between processing elements and memory is also increasing. "also" occurs twice Eli Sternheim
401 1 Main thread: 999 \ Secondary thread: 999 Main thread: 99 \ Secondary thread: 99 Andrew Talbot
401 1 The example starting at the bottom of page 401 needs to import std.exception. Also, on dmd 2.051 the example throws an exception at runtime "std.concurrency.MessageMismatch: Unexpected message type" after printing all messages.   Martin Waite
406 1 The example doesn't need std.algorithm.   Andrew Talbot
406 1 foreach (immutable(ubyte)[] buffer; stdin.byChunk(bufferSize)) send(tid, buffer); foreach (buffer; stdin.byChunk(bufferSize)) send(tid, buffer.idup) Andrew Talbot
407 1 tgt.write(buffer); stdout.rawWrite(buffer); Andrew Talbot
407 1 "... and fileWriter defined on the facing page ..." In fact fileWriter is defined on the same page.  
409 1 (OwnerTerminated) { running = false; } (OwnerTerminated unused) { running = false; }    

Christopher Jordan-Squire

410 1 // Inside std.concurrency
void setMaxMailboxSize(Tid tid, size_t messages,
   bool(Tid) onCrowdingDoThis);
// Inside std.concurrency
void setMaxMailboxSize(Tid tid, size_t messages,
   bool function(Tid) onCrowdingDoThis);
Jos van Uden
413 1 Anyway, real is meant mostly for high-precision temporary results and not for data interchange, so it makes little sense to want to share it anyway. "Anyway" occurs twice Eli Sternheim
415 1 std.contracts std.exception  
418 1 For consistency with the example on page 415, balance() should be a property in the example at the bottom of this page, too.   Andrew Talbot
419 1 no address of a field can escape a synchronized address. no address of a field can escape a synchronized (class/object/method/...). Alix Pexton
419 1 There are shared classes and shared structs, and then synchronized classes. Could there be synchronized structs? Michal Mocny
422 1 setMutex setSameMutex Jonathan Amsterdam
428 1 typeof(return) has not been described before.   Amaury Sechet (deadalnix)
428 1 "... pop may find the queue empty ..." "... pop may find the stack empty ..."  
429 1 The code for lock-free list is wrong. In Harris' original paper you mentioned in the book, List::search() function, which used both in List::insert() and List::delete(), plays a key role in the algorithm. That part is broken or missing in your code.   Jaewon Jung
449 1 "import, static" is listed as appearing on page 347. In fact it appears on page 345. Jonathan M. Davis
index 1 idup, @disable, and auto ref are not in the index   Ashish Myles, Andrew Talbot
index 1 On page 459, the Index entry for "static, obligatory joke about overuse
of" lists page 345, but in fact the joke is in the footnote at the bottom
of page 68. 
index 1 There should be an entry in the index for binary "!" as template instantiation.   David Chapman

Contact Andrei to add a new erratum.