I hope Andrei appreciated my efforts :-) - The non-alphabetical index page 439 is a good idea. - The page thickness is OK for me.
-------------------- More comments on Chapter 1: Page 17: using null to represent empty arrays is not good. In D there is [] that's better for this. P 18: "foo in associativeArray" returns a pointer. So can this work in SafeD too? Maybe it can be accepted by SafeD is the pointer is not used and just tested if it's null or not. P 22: In this code: Object.factory("stats." ~ arg); This code is OK, but in my code I'd like to apply the DRY principle and use something similar to (that keeps workins even if I change the name fo the module): Object.factory(__traits(thisModuleName) ~ arg); This currently works, but it's not nice: Object.factory(split(to!string({class C {}; return new C;}()), ".")[0] ~ ".Foo"); (Probably there are already better ways to do it, but all of them, including the __traits one can't be used in the first pages of the book, so the book page is OK). -------------------- Chapter 2: P 35: adjacent string concatenation: this is bug-prone, see: http://d.puremagic.com/issues/show_bug.cgi?id=3827 P 38, first code example: the D strings contain immutable chars as the text says, but the book has to show this gotcha, that true immutable strings as Python ones don't have (this code runs): void main() { string s = "Hello"; s.length += 1; } P 49: the explanations on is() don't seem complete: is ( Type Identifier : TypeSpecialization, TemplateParameterList ) is ( Type Identifier == TypeSpecialization, TemplateParameterList ) But I think this is for the better, that syntax becomes unreadable. P 50: The part 2.3.5.3 on function calls is good. I hope dmd will eventually do what is written here. P 55: part 2.3.9: there's an error, the concat (~) is not an addition because it's not commutative, generally: (s1 ~ s2) != (s2 ~ s1) P 56, usage examples of 'in': - LDC has shown to be able to optimize away to nearby associative array lookups in all situations (and storing the pointer for a much later usage is not a common usage pattern), and the usage of pointers in SafeD is not easy to do. So consider returning a more clean boolean and improving the compiler instead. - I have just filed this bug: http://d.puremagic.com/issues/show_bug.cgi?id=4463 - For being an usage example it is OK. In D1 I have avoided that if/else using: typedef double Double1 = 0.0; So you can just increment the default double initialization. Now you can probably use: static struct Double2 { double d = 0.0; alias d this; } But there's a bug and Double2 can't be used yet as associative array value. P 57: a small note can be added for the equality among associative arrays. P 58 part 2.3.12.2: Thanks to Don too those FP exceptions can be loud, this helps debug code (I can even appreciate the severeExceptions to be switched on on default in nonrelease builds): import std.math: FloatingPointControl; void main() { FloatingPointControl fpctrl; fpctrl.enableExceptions(FloatingPointControl.severeExceptions); double x; double y = x * 2.0; } P 59: using void with && and || is a ugly hack, if I find a line like this in production code I kill it with fire. This is not a good example to be present in the D2 reference book: line == "#\n" && writeln("..."); P 60: this is another bad example, it's a cute trick, but it's bad for production code: (predicate ? x : y) += 5 P 61: this is so hard to read that I don't want to see anything similar even in small script-like programs. The D compiler can even disallow such long chains: int c = (a = b, b = 7, 8); Bye, bearophile