TDPL Errata
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 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".
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) |
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 |
8 | 1 | In splitter(strip(line)), strip is redundant | G.J. Schreuder | |
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 http://d.puremagic.com/issues/show_bug.cgi?id=8035 | 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 |
31 |
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 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 |
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 | ...is introduced inside a pair of { and } braces | ...is 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 statement to effect. | Both statements accept an optional label, which allows specifying which exact statement 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 http://d.puremagic.com/issues/show_bug.cgi?id=11012 | 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 |
industry-strength |
industrial-strength |
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 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 |
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(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. 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 http://d.puremagic.com/issues/show_bug.cgi?id=10996 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 = 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 | 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 = 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 |
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. |
Observer | |
index | 1 | There should be an entry in the index for binary "!" as template instantiation. | David Chapman |
Contact Andrei to add a new erratum.