Main Page
Errata for "The D Programming Language" book
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 all.zip 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 email Andrei. Editing of this page has been disabled due to spamming. 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".
| Page | Current text | Correction | Submitter | |
|---|---|---|---|---|
| xxv | 1 | justfy | justify | Björn Fahller |
| 5 | 1 | %i for integers | %d for integers | Andrei Alexandrescu (on behalf of Roel) |
| 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. | Andrei Alexandrescu (on behalf of Caligo) |
| 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 |
| 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 |
| 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 |
| 17 | 1 | better makes a copy of it | better make a copy of it | Philip Zigoris |
| 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 |
| 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 | 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 |
| 26 | 1 | In D, slicing could never occur. | This should probably be: In D, C++'s damaging slicing could never occur. | Andrej Mitrovic |
| 31 | 1 | List of keywords | Keywords immutable, lazy, pure, nothrow, and shared are missing (more detail) | Jonathan M Davis |
| 36 | 1 | The ASCII values for backspace, formfeed, line feed and carriage return seem to be given in octal. | Jos | |
| 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 |
| 44 | 1 | Figure 2.3: Implicit integral conversions. | The figure shows both integrals and floating-point types. | Geert Fannes |
| 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 2.3.5.4. 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 |
| 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 |
| 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 |
| 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 | |
| 68 | 1 | In the second code block, the last angle bracket is misplaced and should come before the else. | Geert Fannes | |
| 70 | 1 | ...for example, we could define numeric globally ... | ...for example, we could define Numeric globally ... | Karim Naqvi |
| 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 |
| 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 <Ek> that is <Ex> or a class derived from it | The first type <Ek> that is <Ex> or a superclass of it | Simen Kjaeraas |
| 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 |
| 89 | 1 | Bibentry [12] links to D 1.0 assembler. | Michal Mocny | |
| 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 | |
| 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 |
| 106 | 1 | auto array = new int[10] ; array. length += 1000; // Grow |
auto array = new int[10] ; array. length += 1000; // Grow |
Roberto C. B. Ballona |
| 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 | |
| 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 |
| 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 | "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 | |
| 144 | 1 | Three equally specialized functions: either could be called | Three equally specialized functions: each could be called | Andrew Talbot |
| 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 |
| 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 5.10.2.2 | 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 |
| 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(b1.data is null); | assert(b1.data !is null); | Andrej Mitrovic |
| 189 | 1 | initialization orderHere's how the ordering works. | Here's how the ordering works. (can't see where the extra words originated) | 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 |
| 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 |
| 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 |
| 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 |
| 228 | 1 | Then we define Sprite3 to implement ObservantActor and VisualActor: | Then we define Sprite3 to implement HyperObservantActor and VisualActor: | Alix Pexton |
| 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<Integer> is erased, and LinkedList<int> doesn't even compile. | Enrico Kravina |
| 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 |
| 267 | 1 | Figure 7.2 | Hatched area is barely visible. | Geert Fannes |
| 267 | 1 | "hashed areas", "hashed bytes" | "hatched areas", "hatched bytes" | Andrew Talbot |
| 270 | 1 | specify the desired initializer in brackets | specify the desired initializer in braces | Andrew Talbot |
| 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 |
| 279 | 1 | struct /* or class */ Select2(bool cond, T1, T2) { // Or class | struct Select2(bool cond, T1, T2) { // Or class | Alix Pexton |
| 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 |
| 307 | 1 | § 9.4 discussed nothrow functions | § 5.11.2 discussed nothrow functions | Alix Pexton |
| 309 | 1 | catch Exception e, while e = e.next != null | catch Throwable e, while e = e.next !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 | 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 | ..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 |
| 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 |
| 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 = WinVersion.vista; } 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 |
| 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 semicolons in two opUnary methods | return CheckedInt(mixin(op ~ "value;")); mixin(op ~ "value;"); | Andrej Mitrovic |
| 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 |
| 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 |
| 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.write(buffer); | Andrew Talbot |
| 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 |
| 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 |
| 413 | 1 | Last six lines of code have wrong tab sizes. | 2 spaces instead of 3 | Eli Sternheim |