digitalmars.D - Errors in TDPL
- Jonathan M Davis (48/48) Jun 21 2010 Okay. I am in no way trying to say anything negative about TDPL. In fact...
- bearophile (6/8) Jun 21 2010 How do you write this?
- Adam Ruppe (3/5) Jun 21 2010 foreach(i; retro(iota(0, 10))) { }
- bearophile (100/101) Jun 21 2010 Oh, right! Or even just:
- Andrei Alexandrescu (16/21) Jun 21 2010 Nice work.
- Leandro Lucarella (9/16) Jun 21 2010 I'm scared, I've heard that in C++ so many times... =)
- Andrei Alexandrescu (5/14) Jun 21 2010 Particularly in conjunction with iostreams. Their slow speed has been an...
- Norbert Nemec (5/14) Jun 23 2010 Writing an efficient library is a complex task. No language will ever
- Alix Pexton (12/60) Jun 21 2010 Good Idea!
- =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= (13/17) Jun 21 2010 't =
- BCS (6/8) Jun 21 2010 That would be a god idea if the feature were strictly for lazy (no cost ...
- Alix Pexton (5/35) Jun 22 2010 This is the "trick" I was refering to, from a post by the programmer
- Andrei Alexandrescu (5/9) Jun 21 2010 lazy is quite, no, _very_ ill-defined. Walter and I decided to not
- Ellery Newcomer (4/4) Jun 21 2010 I was biting my tongue on the subject, but on page 73 the grammar for
- Andrei Alexandrescu (3/7) Jun 21 2010 Can't help that, sorry...
- Jonathan M Davis (7/17) Jun 22 2010 Well, while I, personally, would put a semicolon there (it feels naked t...
- Andrei Alexandrescu (17/34) Jun 22 2010 Walter, was that intentional? The grammar has no semicolon but the
- bearophile (9/11) Jun 22 2010 This compiles, is this a solitary semicolon statement?
- Andrei Alexandrescu (6/13) Jun 22 2010 Yes. It shouldn't compile. Walter and I agreed that solitary semicolons
- bearophile (6/14) Jun 22 2010 I have had to use a LABEL:; in D code, to implement a finite state machi...
- Don (3/18) Jun 23 2010 I think the ; is part of the label statement. If not, it should be
- Lars T. Kyllingstad (11/29) Jun 23 2010 This does not compile:
- Andrei Alexandrescu (4/23) Jun 23 2010 Fortunately there's no label statement. A label is a distinct entity and...
- Jonathan M Davis (14/37) Jun 22 2010 I have zero problem requiring a semicolon (I'd prefer it actually), but ...
- Rick Trelles (11/11) Jun 23 2010 Saving a keystroke, if it is in sound and clear way, is a plus.
- Andrei Alexandrescu (9/20) Jun 23 2010 We've all seen that requiring "{}" after the likes of if, while etc. are...
- Alix Pexton (11/38) Jun 23 2010 I find that the "}while(..." style is the best way to highlight that you...
- bearophile (4/6) Jun 23 2010 Pascal-like languages use repeat-until, but I prefer the C do-while beca...
- eles (21/27) Jun 23 2010 D...
- Jonathan M Davis (13/19) Jun 23 2010 Quality prevails over compatibility when the quality gain is deemed to
- eles (16/28) Jun 24 2010 I did not try to start a polemic, but to give something to think about....
- Andrei Alexandrescu (3/45) Jun 23 2010 Walter agreed to fix do-while to require a semicolon.
- bearophile (5/6) Jun 23 2010 Good. This was the relative bug:
- Rory McGuire (8/10) Jun 23 2010 +1
- Jonathan M Davis (31/46) Jun 23 2010 It's not that bad.
- Walter Bright (5/10) Jun 23 2010 For reference for this discussion, the current grammar does not require ...
- Andrei Alexandrescu (6/16) Jun 23 2010 I mistakingly assumed D followed C in that regard. Given the argument
- Alix Pexton (3/24) Jun 23 2010 ++vote
- Simen kjaeraas (4/8) Jun 24 2010 Yes
- Lars T. Kyllingstad (3/24) Jun 24 2010 Absolutely.
- Spacen Jasset (8/8) Jun 21 2010 I am only on page ten, I believe I saw a minor typo somewhere in the
- Andrei Alexandrescu (4/12) Jun 21 2010 Thanks for your note. The current text uses "chose", i.e. the past tense...
- Spacen Jasset (2/19) Jun 21 2010 heh. I can't read. I loose a cookie.
- Andrei Alexandrescu (11/12) Jun 21 2010 [snip]
- Jonathan M Davis (8/13) Jun 21 2010 Well, I didn't want to post on the main D list and come across as saying...
- torhu (4/6) Jun 21 2010 For those of us who have still only got the pdf version, is that the
- Andrei Alexandrescu (4/11) Jun 21 2010 The PDF on Rough Cuts is identical to the printed book. Please report
- Jonathan M Davis (9/9) Jun 21 2010 On page 82 of TDPL, it's talking about try/catch/finally statements, and...
- Andrei Alexandrescu (3/12) Jun 21 2010 That's a surprise to me. Walter, is that intentional?
- Walter Bright (5/21) Jun 22 2010 They do not require braces, they just require that the controlling state...
- biozic (2/24) Jun 22 2010 Not always: http://d.puremagic.com/issues/show_bug.cgi?id=4024
- Walter Bright (2/31) Jun 22 2010 Bugs in the compiler aren't errors in TDPL!
- biozic (3/35) Jun 22 2010 I totally agree. I was saying that the requirement for braces was not
- Bill Baxter (6/18) Jun 22 2010 Will you fix all the god-awful puns too if we add those to the list? :-...
- Andrei Alexandrescu (3/26) Jun 22 2010 If my puns suck I sure want to know which!
- Bill Baxter (10/42) Jun 22 2010 .
- Graham Fawcett (3/30) Jun 22 2010 Awful puns, you say? Now I have to buy a copy!
- Jonathan M Davis (4/31) Jun 22 2010 Aw. Those were awesome. Of course, I love puns, so I'm not about to comp...
- bearophile (39/41) Jun 21 2010 I suggest to focus on the most important case, integer/uint indexes (and...
- Andrei Alexandrescu (58/99) Jun 21 2010 Thanks. Hmm. I redefined iota as follows:
- Brad Roberts (2/13) Jun 21 2010 If you would, file bugs with reduced tests and I'll work on the inliner.
- BCS (4/4) Jun 21 2010 On page 6 it say: "the code sample above also introduced the if statemen...
- Andrei Alexandrescu (4/6) Jun 21 2010 Could you please add that to the errata?
- bearophile (120/126) Jun 22 2010 New timings:
- Andrei Alexandrescu (4/7) Jun 22 2010 Absolutely. I wrote that test to simplify my life, but in the final
- Byron Heads (3/3) Jun 22 2010 On pg. 12 you define a recursive binary search, you forgot to pass value...
- Andrei Alexandrescu (3/6) Jun 22 2010 Saw the erratum you posted - thanks!
- Alix Pexton (4/4) Jun 24 2010 Can someone sanity check me on the code on pages 334-5?
- Jonathan M Davis (4/11) Jun 24 2010 It has to be an error. If you couldn't push onto an empty stack, then yo...
- Alix Pexton (4/15) Jun 24 2010 That's what I thought, but it's there in the example over the page as
- Jonathan M Davis (6/26) Jun 24 2010 I haven't look at it in detail yet, but it definitely looks like it's a
- Alix Pexton (16/16) Jun 24 2010 Does anyone else feel that the following is a fair clarification?
Okay. I am in no way trying to say anything negative about TDPL. In fact, from what I've read so far, it's absolutely fantastic and quite possibly the most entertaining programming book that I've read in addition to being quite informative about D. However, no one's perfect (Andrei included), and there are bound to be errors in the book which didn't get caught. My thought was that we could point out any errors that we've found so that Andrei can get them fixed in future printings and/or we can find out that they aren't actually errors. The only errors that I've found so far have been omissions in the list of keywords on page 31. I'm listing them according to my understanding of whether they're still keywords, since I think that some have been removed as keywords or at least are no longer supposed to be keywords. Definitely should be there -------------------------- immutable lazy pure nothrow shared I _think_ that it's supposed to be there ---------------------------------------- cent ucent I think that they might not supposed to be keywords anymore ----------------------------------------------------------- cdouble cfloat creal delete idouble ifloat ireal foreach_reverse Everything under "definitely" appears to be used in TDPL as keywords but not listed as them. cent and ucent aren't listed, but as far as I know are still keywords (albeit not implemented yet). The ones that are missing which I think have been removed are still listed in the online docs' list of keywards but not in the book. IIRC, the c/i floating points got moved to phobos; according to TDPL, delete was deprecated (though I hadn't picked up on that); and I believe that foreach_reverse has been deprecated in favor of using the combination of foreach and retro. So, TDPL is missing at least some keywords in its list, and the online docs have too many. In any case, I figured that it would be helpful if any errors in TDPL could be pointed out, since it could be helpful to Andrei and could be helpful to those reading it if the error isn't obvious. However, I certainly do _not_ want to in any way indicate displeasure with the book. It's quite good. It's just that it does appear to have some errors in it that snuck through. - Jonathan M Davis
Jun 21 2010
Jonathan M Davis: An online Errata Corrige will be very useful.and I believe that foreach_reverse has been deprecated in favor of using the combination of foreach and retro.How do you write this? foreach_reverse (i; 0 .. 10) Bye, bearophile
Jun 21 2010
On 6/21/10, bearophile <bearophileHUGS lycos.com> wrote:How do you write this? foreach_reverse (i; 0 .. 10)foreach(i; retro(iota(0, 10))) { } ?
Jun 21 2010
Adam Ruppe:foreach(i; retro(iota(0, 10))) { }Oh, right! Or even just: foreach (i; retro(iota(10))) {} But abstraction has a cost, see below. I have written three test programs. ---------------- // test1 import std.c.stdio: printf; void main() { enum int N = 100_000_000; int count; for (int i; i < N; i++) count++; printf("%d\n", count); } Asm of the inner code of the test1, opt version: 5: inc ECX inc EAX cmp EAX,05F5E100h jb L5 ---------------- // test2 import std.c.stdio: printf; void main() { enum int N = 100_000_000; int count; foreach_reverse (i; 0 .. N) count++; printf("%d\n", count); } Asm of the inner code of the test2, opt version: LF: dec ECX inc EDX mov EAX,ECX inc EAX jg LF ---------------- // test3 import std.c.stdio: printf; import std.range: iota, retro; void main() { enum int N = 100_000_000; int count; foreach (i; retro(iota(N))) count++; printf("%d\n", count); } Asm of the inner code of the test3, opt version: L6A: inc EBX lea EAX,010h[ESP] call near ptr _D3std5range145__T4TakeTS3std5range112__T8SequenceVAyaa27_612e6669656c645b305d202b206e202a20612eD0677AACB4B6BC826B92E7DBB9E1E359 cmp dword ptr 020h[ESP],0 jne L6A _D3std5range145__T4TakeTS3std5range112__T8SequenceVAyaa27_612e6669656c645b305d202b206e202a20612eD0677AACB4B6BC826B92E7DBB9E1E359 comdat L0: sub ESP,01Ch mov ECX,offset FLAT:_D3std5range145__T4TakeTS3std5range112__T8SequenceVAyaa27_612e6669656c645b305d202b206e202a20612e0B5C6D6E0C89B8D48DF56A414048DB6F push EBX push ESI mov ESI,EAX mov EDX,010h[ESI] mov 0Ch[ESP],EAX neg EDX sbb EDX,EDX neg EDX xor DL,1 mov 010h[ESP],ECX je L46 mov EDX,ECX push dword ptr FLAT:_DATA[064h] push dword ptr FLAT:_DATA[060h] push 051Fh mov EAX,018h[ESP] mov EBX,018h[ESP] call EDX push EDX push EAX call near ptr _D3std9contracts7bailOutFAyaixAaZv L46: dec dword ptr 010h[ESI] pop ESI pop EBX add ESP,01Ch ret _D3std9contracts7bailOutFAyaixAaZv is extern. ------------------ Running time, best of 3, seconds: test1: 0.31 test1 opt: 0.07 test2: 0.31 test2 opt: 0.12 test3: 6.38 test3 opt: 0.52 not opt version = dmd (no other option) opt version = dmd -O -release -inline Compile times opt version, seconds: test1: 0.05 test2: 0.05 test3: 0.28 So with the current dmd compiler in the inner loop in a performance-critical routine you can't use foreach(retro(iota(N))). In future a D compiler can recognize and optimize such usage of foreach(iota()) and foreach(retro(iota())) as ShedSkin does with usage of xrange()/range() in a loop. Bye, bearophile
Jun 21 2010
On 06/21/2010 04:06 PM, bearophile wrote:Adam Ruppe:Nice work. iota() currently uses the formula initial + i * step to compute the ith element. This is to make sure that iota works properly with floating point numbers as well as integers. We should specialize iota for integrals to use increment, which should count for some efficiency gains (currently the optimizer cannot figure out the equivalence, so it generates the multiply and add in the loop). If efficiency is still sub-par, retro could detect that it's working with iota and generate specialized code. That's not too difficult; for integers, retro(iota(a, b)) could actually be a rewrite to iota(b - 1, a, -1). Figuring out all corner cases, steps greater than 1, and what to do for floating point numbers is doable but not trivial either, and works against modularity. Anyway, it does look like it's all about an implementation matter. Andreiforeach(i; retro(iota(0, 10))) { }Oh, right! Or even just: foreach (i; retro(iota(10))) {} But abstraction has a cost, see below. I have written three test programs.
Jun 21 2010
Andrei Alexandrescu, el 21 de junio a las 17:43 me escribiste:If efficiency is still sub-par, retro could detect that it's working with iota and generate specialized code. That's not too difficult; for integers, retro(iota(a, b)) could actually be a rewrite to iota(b - 1, a, -1). Figuring out all corner cases, steps greater than 1, and what to do for floating point numbers is doable but not trivial either, and works against modularity. Anyway, it does look like it's all about an implementation matter.I'm scared, I've heard that in C++ so many times... =) -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- HOMBRE DESNUDO AMENAZA A LOS VECINOS CON UNA "KATANA" DESDE SU BALCON -- Crónica TV
Jun 21 2010
On 06/21/2010 06:35 PM, Leandro Lucarella wrote:Andrei Alexandrescu, el 21 de junio a las 17:43 me escribiste:Particularly in conjunction with iostreams. Their slow speed has been an implementation issue for, what, 26 years and still going strong. :o) Fortunately, in the case of iota, it's pretty clear what needs to be done. AndreiIf efficiency is still sub-par, retro could detect that it's working with iota and generate specialized code. That's not too difficult; for integers, retro(iota(a, b)) could actually be a rewrite to iota(b - 1, a, -1). Figuring out all corner cases, steps greater than 1, and what to do for floating point numbers is doable but not trivial either, and works against modularity. Anyway, it does look like it's all about an implementation matter.I'm scared, I've heard that in C++ so many times... =)
Jun 21 2010
On 22/06/10 00:35, Leandro Lucarella wrote:Andrei Alexandrescu, el 21 de junio a las 17:43 me escribiste:Writing an efficient library is a complex task. No language will ever change that. The beauty of D is that this complexity can be hidden from the user (unlike in C++ where error messages become increasingly ugly).If efficiency is still sub-par, retro could detect that it's working with iota and generate specialized code. That's not too difficult; for integers, retro(iota(a, b)) could actually be a rewrite to iota(b - 1, a, -1). Figuring out all corner cases, steps greater than 1, and what to do for floating point numbers is doable but not trivial either, and works against modularity. Anyway, it does look like it's all about an implementation matter.I'm scared, I've heard that in C++ so many times... =)
Jun 23 2010
On 21/06/2010 20:09, Jonathan M Davis wrote:Okay. I am in no way trying to say anything negative about TDPL. In fact, from what I've read so far, it's absolutely fantastic and quite possibly the most entertaining programming book that I've read in addition to being quite informative about D. However, no one's perfect (Andrei included), and there are bound to be errors in the book which didn't get caught. My thought was that we could point out any errors that we've found so that Andrei can get them fixed in future printings and/or we can find out that they aren't actually errors. The only errors that I've found so far have been omissions in the list of keywords on page 31. I'm listing them according to my understanding of whether they're still keywords, since I think that some have been removed as keywords or at least are no longer supposed to be keywords. Definitely should be there -------------------------- immutable lazy pure nothrow shared I _think_ that it's supposed to be there ---------------------------------------- cent ucent I think that they might not supposed to be keywords anymore ----------------------------------------------------------- cdouble cfloat creal delete idouble ifloat ireal foreach_reverse Everything under "definitely" appears to be used in TDPL as keywords but not listed as them. cent and ucent aren't listed, but as far as I know are still keywords (albeit not implemented yet). The ones that are missing which I think have been removed are still listed in the online docs' list of keywards but not in the book. IIRC, the c/i floating points got moved to phobos; according to TDPL, delete was deprecated (though I hadn't picked up on that); and I believe that foreach_reverse has been deprecated in favor of using the combination of foreach and retro. So, TDPL is missing at least some keywords in its list, and the online docs have too many. In any case, I figured that it would be helpful if any errors in TDPL could be pointed out, since it could be helpful to Andrei and could be helpful to those reading it if the error isn't obvious. However, I certainly do _not_ want to in any way indicate displeasure with the book. It's quite good. It's just that it does appear to have some errors in it that snuck through. - Jonathan M DavisGood Idea! I must admit I skipped over that table, didn't look overly interesting as tables go (><) but good catch! There is only one mention of lazy evaluation in the index and it doesn't mention the lazy k/w at all. I seem to remember Andrei dislikes it, but also that there is another way to get function params to be evaluated lazily without using it. immutable, nothrow, pure and shared are definitely oversights though. I've not spotted anything D-specific myself yet, I'm not a particularly speedy reader ^^ A...
Jun 21 2010
Dnia 21-06-2010 o 21:57:49 Alix Pexton <alix.DOT.pexton gmail.dot.com> = napisa=B3(a):There is only one mention of lazy evaluation in the index and it doesn='t =mention the lazy k/w at all. I seem to remember Andrei dislikes it, bu=t =also that there is another way to get function params to be evaluated ==lazily without using it.Yeah, speaking of which - what happened to that proposal*? *The proposal AFAIR was (correct me if wrong): if a function has a = parameterless delegate as a parameter, then on the call site any = expression in the delegate slot is implicitly turned into a delegate. I = = think the delegate ought to be pure to make the magic happen. Yeah, speaking of which - do/will we have pure delegates? Tomek
Jun 21 2010
Hello Tomek,I think the delegate ought to be pure to make the magic happen.That would be a god idea if the feature were strictly for lazy (no cost unless you need it) evaluation but there are other use that need to be able to cause side effects. -- ... <IXOYE><
Jun 21 2010
On 21/06/2010 21:51, Tomek Sowiñski wrote:Dnia 21-06-2010 o 21:57:49 Alix Pexton <alix.DOT.pexton gmail.dot.com> napisa³(a):This is the "trick" I was refering to, from a post by the programmer formerly known as downs... Amusing D facts: typesafe variadic arrays are lazy!There is only one mention of lazy evaluation in the index and it doesn't mention the lazy k/w at all. I seem to remember Andrei dislikes it, but also that there is another way to get function params to be evaluated lazily without using it.Yeah, speaking of which - what happened to that proposal*? *The proposal AFAIR was (correct me if wrong): if a function has a parameterless delegate as a parameter, then on the call site any expression in the delegate slot is implicitly turned into a delegate. I think the delegate ought to be pure to make the magic happen. Yeah, speaking of which - do/will we have pure delegates? TomekDid you know the following code compiles?A...It's true! :)module test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }
Jun 22 2010
On 06/21/2010 02:57 PM, Alix Pexton wrote:There is only one mention of lazy evaluation in the index and it doesn't mention the lazy k/w at all. I seem to remember Andrei dislikes it, but also that there is another way to get function params to be evaluated lazily without using it.lazy is quite, no, _very_ ill-defined. Walter and I decided to not mention it in the book and leave room for either a better definition of lazy or a feature that obviates it. Andrei
Jun 21 2010
I was biting my tongue on the subject, but on page 73 the grammar for the do while loop has a semicolon at the end. AAHHHHHHHHHHHHH!!!!!!!! THERE IS NOOOOOOO SEMICOLON AT THE END. Wow. Sorry. This is a pet peeve of mine.
Jun 21 2010
On 06/21/2010 03:32 PM, Ellery Newcomer wrote:I was biting my tongue on the subject, but on page 73 the grammar for the do while loop has a semicolon at the end. AAHHHHHHHHHHHHH!!!!!!!! THERE IS NOOOOOOO SEMICOLON AT THE END. Wow. Sorry. This is a pet peeve of mine.Can't help that, sorry... Andrei
Jun 21 2010
Andrei Alexandrescu wrote:On 06/21/2010 03:32 PM, Ellery Newcomer wrote:Well, while I, personally, would put a semicolon there (it feels naked to me without one), dmd doesn't actually seem to require it. But TDPL says that the semicolon is required. So, it does appear to be an error in the text. Of course, there's no helping his pet peeve regardless, but the semicolon doesn't appear to be required. - Jonathan M DavisI was biting my tongue on the subject, but on page 73 the grammar for the do while loop has a semicolon at the end. AAHHHHHHHHHHHHH!!!!!!!! THERE IS NOOOOOOO SEMICOLON AT THE END. Wow. Sorry. This is a pet peeve of mine.Can't help that, sorry... Andrei
Jun 22 2010
On 06/22/2010 04:14 PM, Jonathan M Davis wrote:Andrei Alexandrescu wrote:Walter, was that intentional? The grammar has no semicolon but the example does. That makes the example wrong because you agreed there is no solitary semicolon statement in D, and TDPL does mention that. IMHO the semicolon makes for more robust code. Consider: do { ... lotsa code ... } while (fun(i)) ++i; A maintainer might see the while and conclude that ++i; was meant to be the loop, indent it, and call it a day. The absence of the semicolon thus created a contextual dependency on the presence of the "do" keyword upstream. Walter, can we require a semicolon please? AndreiOn 06/21/2010 03:32 PM, Ellery Newcomer wrote:Well, while I, personally, would put a semicolon there (it feels naked to me without one), dmd doesn't actually seem to require it. But TDPL says that the semicolon is required. So, it does appear to be an error in the text. Of course, there's no helping his pet peeve regardless, but the semicolon doesn't appear to be required. - Jonathan M DavisI was biting my tongue on the subject, but on page 73 the grammar for the do while loop has a semicolon at the end. AAHHHHHHHHHHHHH!!!!!!!! THERE IS NOOOOOOO SEMICOLON AT THE END. Wow. Sorry. This is a pet peeve of mine.Can't help that, sorry... Andrei
Jun 22 2010
Andrei Alexandrescu:you agreed there is no solitary semicolon statement in D,<This compiles, is this a solitary semicolon statement? void main() { goto FOO; FOO:; }Walter, can we require a semicolon please?+1 Bye, bearophile
Jun 22 2010
On 06/22/2010 04:53 PM, bearophile wrote:Andrei Alexandrescu:Yes. It shouldn't compile. Walter and I agreed that solitary semicolons are useless (you can always use {} as an empty statement and that actually makes things clearer to everyone), but it's a low-priority issue so he hasn't implemented that yet. Andreiyou agreed there is no solitary semicolon statement in D,<This compiles, is this a solitary semicolon statement? void main() { goto FOO; FOO:; }
Jun 22 2010
Andrei:I have had to use a LABEL:; in D code, to implement a finite state machine. So I guess I'll have to write it like this: LABEL: {} Bye, bearophilevoid main() { goto FOO; FOO:; }Yes. It shouldn't compile. Walter and I agreed that solitary semicolons are useless (you can always use {} as an empty statement and that actually makes things clearer to everyone),
Jun 22 2010
bearophile wrote:Andrei:I think the ; is part of the label statement. If not, it should be removed entirely.I have had to use a LABEL:; in D code, to implement a finite state machine. So I guess I'll have to write it like this: LABEL: {} Bye, bearophilevoid main() { goto FOO; FOO:; }Yes. It shouldn't compile. Walter and I agreed that solitary semicolons are useless (you can always use {} as an empty statement and that actually makes things clearer to everyone),
Jun 23 2010
On Wed, 23 Jun 2010 11:56:12 +0200, Don wrote:bearophile wrote:This does not compile: void main() { goto Lfoo; Lfoo: } test.d(5): found '}' instead of statement It seems to me like it should be valid code, but I'm not sure it's worth making it a special case. -LarsAndrei:I think the ; is part of the label statement. If not, it should be removed entirely.I have had to use a LABEL:; in D code, to implement a finite state machine. So I guess I'll have to write it like this: LABEL: {} Bye, bearophilevoid main() { goto FOO; FOO:; }Yes. It shouldn't compile. Walter and I agreed that solitary semicolons are useless (you can always use {} as an empty statement and that actually makes things clearer to everyone),
Jun 23 2010
On 06/23/2010 04:56 AM, Don wrote:bearophile wrote:Fortunately there's no label statement. A label is a distinct entity and may precede any statement. AndreiAndrei:I think the ; is part of the label statement. If not, it should be removed entirely.I have had to use a LABEL:; in D code, to implement a finite state machine. So I guess I'll have to write it like this: LABEL: {} Bye, bearophilevoid main() { goto FOO; FOO:; }Yes. It shouldn't compile. Walter and I agreed that solitary semicolons are useless (you can always use {} as an empty statement and that actually makes things clearer to everyone),
Jun 23 2010
Andrei Alexandrescu wrote:Walter, was that intentional? The grammar has no semicolon but the example does. That makes the example wrong because you agreed there is no solitary semicolon statement in D, and TDPL does mention that. IMHO the semicolon makes for more robust code. Consider: do { ... lotsa code ... } while (fun(i)) ++i; A maintainer might see the while and conclude that ++i; was meant to be the loop, indent it, and call it a day. The absence of the semicolon thus created a contextual dependency on the presence of the "do" keyword upstream. Walter, can we require a semicolon please? AndreiI have zero problem requiring a semicolon (I'd prefer it actually), but I believe that a lone semicolon is generally a perfectly valid statement in D as long as it's not where optional braces could be. Per the grammar: Statement: ; NonEmptyStatement ScopeBlockStatement I believe that all the constructs with optional braces have a ScopBlockStatement for their body and therefore can't have a lone semicolon. But a statement by itself can be a lone semicolon. Though why you'd do that, I don't know. The only place that I've run into that being useful has been with macros (which don't exist in D). - Jonathan M Davis
Jun 22 2010
Saving a keystroke, if it is in sound and clear way, is a plus. At least the option to save the keystroke should be maintained. I don't see now any advantages in using a pair of braces over a single semicolon for a null statement, but why not keep it both ways? I never liked the semicolon after while() but surely it wouldn't hurt to interpret it as a null statement for those who are used to it. By the way, I always glue the closing bracket to while do{ . . . }while( . . . ) // plus ";" if coding in C Rick Trelles
Jun 23 2010
On 06/23/2010 02:11 AM, Rick Trelles wrote:Saving a keystroke, if it is in sound and clear way, is a plus. At least the option to save the keystroke should be maintained. I don't see now any advantages in using a pair of braces over a single semicolon for a null statement, but why not keep it both ways?We've all seen that requiring "{}" after the likes of if, while etc. are very beneficial for readability. Then why not generalize that? As far as I can tell the only vestigial use of the lone ";" is with labels that don't precede any instruction (a very rare case). At this point, ";" needs more justification to stay than to go.I never liked the semicolon after while() but surely it wouldn't hurt to interpret it as a null statement for those who are used to it. By the way, I always glue the closing bracket to while do{ . . . }while( . . . ) // plus ";" if coding in C Rick TrellesThat's great, except for those who enjoy "brace on its own line" formatting style. For those, the "}while" would look jarring. Andrei
Jun 23 2010
On 23/06/2010 16:24, Andrei Alexandrescu wrote:On 06/23/2010 02:11 AM, Rick Trelles wrote:I find that the "}while(..." style is the best way to highlight that you are looking a a do...while and not a regular while loop, that it is jarring is exactly the point ^^ Making the the semicolon on the end a requirement helps if you are familiar with D and know it is not allowed on a regular while, but the less enlightened might see a classic bug pattern where there isn't one and try to "maintain" it away >< In some ways I think it was a mistake in to reuse while in the first place, but that was a decision that was made a loong time before D... A...Saving a keystroke, if it is in sound and clear way, is a plus. At least the option to save the keystroke should be maintained. I don't see now any advantages in using a pair of braces over a single semicolon for a null statement, but why not keep it both ways?We've all seen that requiring "{}" after the likes of if, while etc. are very beneficial for readability. Then why not generalize that? As far as I can tell the only vestigial use of the lone ";" is with labels that don't precede any instruction (a very rare case). At this point, ";" needs more justification to stay than to go.I never liked the semicolon after while() but surely it wouldn't hurt to interpret it as a null statement for those who are used to it. By the way, I always glue the closing bracket to while do{ . . . }while( . . . ) // plus ";" if coding in C Rick TrellesThat's great, except for those who enjoy "brace on its own line" formatting style. For those, the "}while" would look jarring. Andrei
Jun 23 2010
Alix Pexton:In some ways I think it was a mistake in to reuse while in the first place, but that was a decision that was made a loong time before D...Pascal-like languages use repeat-until, but I prefer the C do-while because the condition in repeat-until is the opposite of the one you use in a while loop, and every time I use repeat-until I have to remember what's the correct stopping condition to write. Bye, bearophile
Jun 23 2010
== Quote from bearophile (bearophileHUGS lycos.com)'s articleAlix Pexton:firstIn some ways I think it was a mistake in to reuse while in theD...place, but that was a decision that was made a loong time beforePascal-like languages use repeat-until, but I prefer the C do-whilebecause the condition in repeat-until is the opposite of the one you use in a while loop, and every time I use repeat-until I have to remember what's the correct stopping condition to write. Quite the oposite here. When I have a loop like that, I think rather about the exit condition (so in terms of "repeat/until"). This is why I often write: do{ //code } while(!([exit_condition_here])); I also think re-using while() in the do ... while loop is a mistake, exactly because of difficulties arising in code maintenance. I would like to have another keyword for that, or maybe the "repeat/ until" loop all-together. It is a shame that compatibility issues prevail over quality and improvement. Ditching the do...while loop could be unacceptable now, but why do not propose a better alternative mechanism? That way, we would have both compatibility and quality. elesBye, bearophile
Jun 23 2010
eles wrote:It is a shame that compatibility issues prevail over quality and improvement. Ditching the do...while loop could be unacceptable now, but why do not propose a better alternative mechanism? That way, we would have both compatibility and quality. elesQuality prevails over compatibility when the quality gain is deemed to exceed the problems incurred by losing compatibility. In this case, do-while works just fine. Lots of people are used to using it and have never even heard of repeat-until, having never used Pascal or any other language that used it. At this point, C's influence far outweights Pascal's. Also, AFAIK, do-while is not generally a major source of bugs. As such, while another construct might be better, since the current one isn't much of a problem, it's not worth breaking compatibility. If it were shown that do- while was a big problem, then it might be. But at this point, do-while works just fine, so it's not worth changing it. - Jonathan M Davis
Jun 23 2010
I did not try to start a polemic, but to give something to think about. There are more opinions on the matter and, as you may see, mine differs of yours. Is not a tragedy. However, I think one should be more aware when supporting habit per se. Maybe adding "until" as an aliasing for "while not" would you seem more acceptable? Or, at least, accepting "do{/* code */}aslongas(/*condition*/);" as an alternative "do{/* code */}while(/*condition*/);" would be less disruptive? That way, people could use "do/while", but this will open the door for "do/ aslongas", if this is considered suitable. This will also avoid ambiguous cases like pointed out in this thread (i.e. the danger of interpreting "while(/ *condition*/;i++" as a ";" bug). This will break no compatibility. Robustness of relying solely on the code indentation ("}while();" instead of "while();") is not persuasive for me. Why dismissing an opportunity to avoid a potential bug? eles == Quote from Jonathan M Davis (jmdavisProg gmail.com)'s articleQuality prevails over compatibility when the quality gain is deemed to exceed the problems incurred by losing compatibility. In this case, do-while works just fine. Lots of people are used to using it and have never even heard of repeat-until, having never used Pascal or any other language that used it. At this point, C's influence far outweights Pascal's. Also, AFAIK, do-while is not generally a major source of bugs. As such, while another construct might be better, since the current one isn't much of a problem, it's not worth breaking compatibility. If it were shown that do- while was a big problem, then it might be. But at this point, do-while works just fine, so it's not worth changing it. - Jonathan M Davis
Jun 24 2010
On 06/23/2010 05:44 PM, Alix Pexton wrote:On 23/06/2010 16:24, Andrei Alexandrescu wrote:Walter agreed to fix do-while to require a semicolon. AndreiOn 06/23/2010 02:11 AM, Rick Trelles wrote:I find that the "}while(..." style is the best way to highlight that you are looking a a do...while and not a regular while loop, that it is jarring is exactly the point ^^ Making the the semicolon on the end a requirement helps if you are familiar with D and know it is not allowed on a regular while, but the less enlightened might see a classic bug pattern where there isn't one and try to "maintain" it away >< In some ways I think it was a mistake in to reuse while in the first place, but that was a decision that was made a loong time before D... A...Saving a keystroke, if it is in sound and clear way, is a plus. At least the option to save the keystroke should be maintained. I don't see now any advantages in using a pair of braces over a single semicolon for a null statement, but why not keep it both ways?We've all seen that requiring "{}" after the likes of if, while etc. are very beneficial for readability. Then why not generalize that? As far as I can tell the only vestigial use of the lone ";" is with labels that don't precede any instruction (a very rare case). At this point, ";" needs more justification to stay than to go.I never liked the semicolon after while() but surely it wouldn't hurt to interpret it as a null statement for those who are used to it. By the way, I always glue the closing bracket to while do{ . . . }while( . . . ) // plus ";" if coding in C Rick TrellesThat's great, except for those who enjoy "brace on its own line" formatting style. For those, the "}while" would look jarring. Andrei
Jun 23 2010
Andrei Alexandrescu:Walter agreed to fix do-while to require a semicolon.Good. This was the relative bug: http://d.puremagic.com/issues/show_bug.cgi?id=4374 Bye, bearophile
Jun 23 2010
On Tue, 22 Jun 2010 23:37:59 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Walter, can we require a semicolon please?+1 With the semi colon missing its as bad as: for (;i<100;i++); writeln(i); esp. with large amount of codeAndreiRory
Jun 23 2010
Rory McGuire wrote:On Tue, 22 Jun 2010 23:37:59 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:It's not that bad. for(; i < 100; ++i); writeln(i); would be a bug (if it were legal) because you'd expect the writeln() to be part of the loop when it isn't. The loop wouldn't be run like you'd expect it to, and it's hard to catch. do { ... } while(test) does not have that problem. The problem you run into is this: do { ... } while(test) { ... } If you're _really_ not paying attention, you'd think that the second set of braces started a while loop. But since you'd have to have way more spacing than makes sense for it to happen, it becomes way more obvious and is not the same level of problem. However, I do think that it _is_ a problem, and the above example could definitely be confusing if you're just quickly scanning over code. I don't see any real reason to allow the lack of semicolon, and I do think that it's a problem, but I don't think that it's a problem on the same level as allowing a semicolon to be used as an empty body for an if statement or loop. - Jonathan M DavisWalter, can we require a semicolon please?+1 With the semi colon missing its as bad as: for (;i<100;i++); writeln(i); esp. with large amount of codeAndreiRory
Jun 23 2010
Jonathan M Davis wrote:Well, while I, personally, would put a semicolon there (it feels naked to me without one), dmd doesn't actually seem to require it. But TDPL says that the semicolon is required. So, it does appear to be an error in the text. Of course, there's no helping his pet peeve regardless, but the semicolon doesn't appear to be required.For reference for this discussion, the current grammar does not require it: http://www.digitalmars.com/d/2.0/statement.html#DoStatement The C grammar does require it: do statement while ( expression ) ;
Jun 23 2010
On 06/23/2010 11:40 AM, Walter Bright wrote:Jonathan M Davis wrote:I mistakingly assumed D followed C in that regard. Given the argument stated in this thread (that absent semicolons require more context to be absorbed while reading), do you agree that D should make the semicolon required? AndreiWell, while I, personally, would put a semicolon there (it feels naked to me without one), dmd doesn't actually seem to require it. But TDPL says that the semicolon is required. So, it does appear to be an error in the text. Of course, there's no helping his pet peeve regardless, but the semicolon doesn't appear to be required.For reference for this discussion, the current grammar does not require it: http://www.digitalmars.com/d/2.0/statement.html#DoStatement The C grammar does require it: do statement while ( expression ) ;
Jun 23 2010
On 23/06/2010 17:51, Andrei Alexandrescu wrote:On 06/23/2010 11:40 AM, Walter Bright wrote:++vote A...Jonathan M Davis wrote:I mistakingly assumed D followed C in that regard. Given the argument stated in this thread (that absent semicolons require more context to be absorbed while reading), do you agree that D should make the semicolon required? AndreiWell, while I, personally, would put a semicolon there (it feels naked to me without one), dmd doesn't actually seem to require it. But TDPL says that the semicolon is required. So, it does appear to be an error in the text. Of course, there's no helping his pet peeve regardless, but the semicolon doesn't appear to be required.For reference for this discussion, the current grammar does not require it: http://www.digitalmars.com/d/2.0/statement.html#DoStatement The C grammar does require it: do statement while ( expression ) ;
Jun 23 2010
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I mistakingly assumed D followed C in that regard. Given the argument stated in this thread (that absent semicolons require more context to be absorbed while reading), do you agree that D should make the semicolon required?Yes -- Simen
Jun 24 2010
On Wed, 23 Jun 2010 11:51:40 -0500, Andrei Alexandrescu wrote:On 06/23/2010 11:40 AM, Walter Bright wrote:Absolutely. -LarsJonathan M Davis wrote:I mistakingly assumed D followed C in that regard. Given the argument stated in this thread (that absent semicolons require more context to be absorbed while reading), do you agree that D should make the semicolon required?Well, while I, personally, would put a semicolon there (it feels naked to me without one), dmd doesn't actually seem to require it. But TDPL says that the semicolon is required. So, it does appear to be an error in the text. Of course, there's no helping his pet peeve regardless, but the semicolon doesn't appear to be required.For reference for this discussion, the current grammar does not require it: http://www.digitalmars.com/d/2.0/statement.html#DoStatement The C grammar does require it: do statement while ( expression ) ;
Jun 24 2010
I am only on page ten, I believe I saw a minor typo somewhere in the preface, that's all so far. I look forward to pondering the rest in the coming days. oh yes. Preface "D is a language that attempts to consistently do the right thing within the constraints it choose: sys...." etc missing s, I gues.
Jun 21 2010
On 06/21/2010 05:35 PM, Spacen Jasset wrote:I am only on page ten, I believe I saw a minor typo somewhere in the preface, that's all so far. I look forward to pondering the rest in the coming days. oh yes. Preface "D is a language that attempts to consistently do the right thing within the constraints it choose: sys...." etc missing s, I gues.Thanks for your note. The current text uses "chose", i.e. the past tense of "to choose", so I think it is correct. Andrei
Jun 21 2010
Andrei Alexandrescu wrote:On 06/21/2010 05:35 PM, Spacen Jasset wrote:heh. I can't read. I loose a cookie.I am only on page ten, I believe I saw a minor typo somewhere in the preface, that's all so far. I look forward to pondering the rest in the coming days. oh yes. Preface "D is a language that attempts to consistently do the right thing within the constraints it choose: sys...." etc missing s, I gues.Thanks for your note. The current text uses "chose", i.e. the past tense of "to choose", so I think it is correct. Andrei
Jun 21 2010
On 06/21/2010 02:09 PM, Jonathan M Davis wrote:Okay. I am in no way trying to say anything negative about TDPL.[snip] You are being too kind about this :o). Of course we need an errata list. I was hoping I'd need to set it up later, but hey, that's a sign people actually are reading the book and care about keeping everything in check. I started an errata list in form of a community wiki at http://www.erdani.com/tdpl/errata and primed the errata with your report. Thanks very much! I'll see to it that future printings fix the issues in the errata list. Andrei
Jun 21 2010
Andrei Alexandrescu wrote:On 06/21/2010 02:09 PM, Jonathan M Davis wrote:Well, I didn't want to post on the main D list and come across as saying that the new book is full of errors and sucks. wIt really is quite an entertaining read (for a programming book anyway) with talk of jumping through rings of syntactic fire, describing casts as well-intended genies, and plenty of other humourous descriptions. And, of course, it's quite instructive along the way. Now if I can only get my co-workers to read it... - Jonathan M DavisOkay. I am in no way trying to say anything negative about TDPL.[snip] You are being too kind about this :o).
Jun 21 2010
On 22.06.2010 00:39, Andrei Alexandrescu wrote:I started an errata list in form of a community wiki at http://www.erdani.com/tdpl/errataFor those of us who have still only got the pdf version, is that the same text as the printed one? Should we report errors in the pdf version, or wait until we get the printed edition?
Jun 21 2010
On 06/21/2010 06:30 PM, torhu wrote:On 22.06.2010 00:39, Andrei Alexandrescu wrote:The PDF on Rough Cuts is identical to the printed book. Please report straight in the errata. AndreiI started an errata list in form of a community wiki at http://www.erdani.com/tdpl/errataFor those of us who have still only got the pdf version, is that the same text as the printed one? Should we report errors in the pdf version, or wait until we get the printed edition?
Jun 21 2010
On page 82 of TDPL, it's talking about try/catch/finally statements, and it says that "all controlled statement must be block statements; that is they must be enclosed with braces." However, dmd does not seem to require that try/catch/finally blocks have braces, which is what I would expect that sentence to mean. C++ has that restriction for reasons that I don't understand, but as far as I can tell, D does not - certainly dmd doesn't appear to require it. Is the statement correct but refers to something else, or is it in error? - Jonathan M Davis
Jun 21 2010
On 06/21/2010 08:47 PM, Jonathan M Davis wrote:On page 82 of TDPL, it's talking about try/catch/finally statements, and it says that "all controlled statement must be block statements; that is they must be enclosed with braces." However, dmd does not seem to require that try/catch/finally blocks have braces, which is what I would expect that sentence to mean. C++ has that restriction for reasons that I don't understand, but as far as I can tell, D does not - certainly dmd doesn't appear to require it. Is the statement correct but refers to something else, or is it in error? - Jonathan M DavisThat's a surprise to me. Walter, is that intentional? Andrei
Jun 21 2010
Andrei Alexandrescu wrote:On 06/21/2010 08:47 PM, Jonathan M Davis wrote:They do not require braces, they just require that the controlling statement not be a single ;. In the grammar, this is a ScopeStatement, which is a NonEmptyStatement or a BlockStatement. http://www.digitalmars.com/d/2.0/statement.html#ScopeStatementOn page 82 of TDPL, it's talking about try/catch/finally statements, and it says that "all controlled statement must be block statements; that is they must be enclosed with braces." However, dmd does not seem to require that try/catch/finally blocks have braces, which is what I would expect that sentence to mean. C++ has that restriction for reasons that I don't understand, but as far as I can tell, D does not - certainly dmd doesn't appear to require it. Is the statement correct but refers to something else, or is it in error? - Jonathan M DavisThat's a surprise to me. Walter, is that intentional?
Jun 22 2010
Le 22/06/10 10:54, Walter Bright a écrit :Andrei Alexandrescu wrote:Not always: http://d.puremagic.com/issues/show_bug.cgi?id=4024On 06/21/2010 08:47 PM, Jonathan M Davis wrote:They do not require braces, they just require that the controlling statement not be a single ;. In the grammar, this is a ScopeStatement, which is a NonEmptyStatement or a BlockStatement. http://www.digitalmars.com/d/2.0/statement.html#ScopeStatementOn page 82 of TDPL, it's talking about try/catch/finally statements, and it says that "all controlled statement must be block statements; that is they must be enclosed with braces." However, dmd does not seem to require that try/catch/finally blocks have braces, which is what I would expect that sentence to mean. C++ has that restriction for reasons that I don't understand, but as far as I can tell, D does not - certainly dmd doesn't appear to require it. Is the statement correct but refers to something else, or is it in error? - Jonathan M DavisThat's a surprise to me. Walter, is that intentional?
Jun 22 2010
biozic wrote:Le 22/06/10 10:54, Walter Bright a écrit :Bugs in the compiler aren't errors in TDPL!Andrei Alexandrescu wrote:Not always: http://d.puremagic.com/issues/show_bug.cgi?id=4024On 06/21/2010 08:47 PM, Jonathan M Davis wrote:They do not require braces, they just require that the controlling statement not be a single ;. In the grammar, this is a ScopeStatement, which is a NonEmptyStatement or a BlockStatement. http://www.digitalmars.com/d/2.0/statement.html#ScopeStatementOn page 82 of TDPL, it's talking about try/catch/finally statements, and it says that "all controlled statement must be block statements; that is they must be enclosed with braces." However, dmd does not seem to require that try/catch/finally blocks have braces, which is what I would expect that sentence to mean. C++ has that restriction for reasons that I don't understand, but as far as I can tell, D does not - certainly dmd doesn't appear to require it. Is the statement correct but refers to something else, or is it in error? - Jonathan M DavisThat's a surprise to me. Walter, is that intentional?
Jun 22 2010
Le 22/06/10 15:53, Walter Bright a écrit :biozic wrote:I totally agree. I was saying that the requirement for braces was not always intentional :SLe 22/06/10 10:54, Walter Bright a écrit :Bugs in the compiler aren't errors in TDPL!Andrei Alexandrescu wrote:Not always: http://d.puremagic.com/issues/show_bug.cgi?id=4024On 06/21/2010 08:47 PM, Jonathan M Davis wrote:They do not require braces, they just require that the controlling statement not be a single ;. In the grammar, this is a ScopeStatement, which is a NonEmptyStatement or a BlockStatement. http://www.digitalmars.com/d/2.0/statement.html#ScopeStatementOn page 82 of TDPL, it's talking about try/catch/finally statements, and it says that "all controlled statement must be block statements; that is they must be enclosed with braces." However, dmd does not seem to require that try/catch/finally blocks have braces, which is what I would expect that sentence to mean. C++ has that restriction for reasons that I don't understand, but as far as I can tell, D does not - certainly dmd doesn't appear to require it. Is the statement correct but refers to something else, or is it in error? - Jonathan M DavisThat's a surprise to me. Walter, is that intentional?
Jun 22 2010
On Mon, Jun 21, 2010 at 3:39 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 06/21/2010 02:09 PM, Jonathan M Davis wrote:Will you fix all the god-awful puns too if we add those to the list? :-) Just kidding, I'm sure suffering through them helps build character or something. --bbOkay. I am in no way trying to say anything negative about TDPL.[snip] You are being too kind about this :o). Of course we need an errata list. I was hoping I'd need to set it up later, but hey, that's a sign people actually are reading the book and care about keeping everything in check. I started an errata list in form of a community wiki at http://www.erdani.com/tdpl/errata and primed the errata with your report. Thanks very much! I'll see to it that future printings fix the issues in the errata list.
Jun 22 2010
On 06/22/2010 01:45 PM, Bill Baxter wrote:On Mon, Jun 21, 2010 at 3:39 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:If my puns suck I sure want to know which! AndreiOn 06/21/2010 02:09 PM, Jonathan M Davis wrote:Will you fix all the god-awful puns too if we add those to the list? :-) Just kidding, I'm sure suffering through them helps build character or something.Okay. I am in no way trying to say anything negative about TDPL.[snip] You are being too kind about this :o). Of course we need an errata list. I was hoping I'd need to set it up later, but hey, that's a sign people actually are reading the book and care about keeping everything in check. I started an errata list in form of a community wiki at http://www.erdani.com/tdpl/errata and primed the errata with your report. Thanks very much! I'll see to it that future printings fix the issues in the errata list.
Jun 22 2010
On Tue, Jun 22, 2010 at 11:52 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 06/22/2010 01:45 PM, Bill Baxter wrote:.On Mon, Jun 21, 2010 at 3:39 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> =A0wrote:On 06/21/2010 02:09 PM, Jonathan M Davis wrote:Okay. I am in no way trying to say anything negative about TDPL.[snip] You are being too kind about this :o). Of course we need an errata list=k.I was hoping I'd need to set it up later, but hey, that's a sign people actually are reading the book and care about keeping everything in chec=nI started an errata list in form of a community wiki at http://www.erdani.com/tdpl/errata and primed the errata with your report. Thanks very much! I'll see to it that future printings fix the issues i=:-)the errata list.Will you fix all the god-awful puns too if we add those to the list? =A0=They're fine. I'm just kidding. "A pun is the lowest form of humor-- if you didn't think of it first." -- Oscar Levant --bbJust kidding, I'm sure suffering through them helps build character or something.If my puns suck I sure want to know which! Andrei
Jun 22 2010
On Tue, 22 Jun 2010 11:45:39 -0700, Bill Baxter wrote:On Mon, Jun 21, 2010 at 3:39 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Awful puns, you say? Now I have to buy a copy! GrahamOn 06/21/2010 02:09 PM, Jonathan M Davis wrote:Will you fix all the god-awful puns too if we add those to the list? :-) Just kidding, I'm sure suffering through them helps build character or something.Okay. I am in no way trying to say anything negative about TDPL.[snip] You are being too kind about this :o). Of course we need an errata list. I was hoping I'd need to set it up later, but hey, that's a sign people actually are reading the book and care about keeping everything in check. I started an errata list in form of a community wiki at http://www.erdani.com/tdpl/errata and primed the errata with your report. Thanks very much! I'll see to it that future printings fix the issues in the errata list.
Jun 22 2010
Bill Baxter wrote:On Mon, Jun 21, 2010 at 3:39 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Aw. Those were awesome. Of course, I love puns, so I'm not about to complain about them unless they're really bad, and Andrei's were good. - Jonathan M DavisOn 06/21/2010 02:09 PM, Jonathan M Davis wrote:Will you fix all the god-awful puns too if we add those to the list? :-) Just kidding, I'm sure suffering through them helps build character or something. --bbOkay. I am in no way trying to say anything negative about TDPL.[snip] You are being too kind about this :o). Of course we need an errata list. I was hoping I'd need to set it up later, but hey, that's a sign people actually are reading the book and care about keeping everything in check. I started an errata list in form of a community wiki at http://www.erdani.com/tdpl/errata and primed the errata with your report. Thanks very much! I'll see to it that future printings fix the issues in the errata list.
Jun 22 2010
Andrei Alexandrescu:That's not too difficult; for integers, retro(iota(a, b)) could actually be a rewrite to iota(b - 1, a, -1).<This is good. In my dlibs the xchain converts xchain(xchain(x, y), z) and similar into xchain(x, y, z).Figuring out all corner cases, steps greater than 1, and what to do for floating point numbers is doable but not trivial either, and works against modularity.<I suggest to focus on the most important case, integer/uint indexes (and +1 or -1 increment). My post has shown some different problems: - A longer compilation time (and binary size) - A 1/10 performance when the code is compiled in standard way, this is bad - a smaller performance when the code is compiled in optimized mode. The asm of the opt version shows calls to two or more functions inside the loop, and one of those functions is not so small, this probably reduces performance more than an extra inlined product. So in my opinion getting rid of those calls (inlining them) is more important if you want a faster retro(iota). ------------------------ I have added your last version: // test4 import std.c.stdio: printf; import std.range: iota; void main() { enum int N = 100_000_000; int count; foreach (i; iota(N - 1, 0, -1)) count++; printf("%d\n", count); } Running time, best of 3, seconds: test1: 0.31 test1 opt: 0.07 test2: 0.31 test2 opt: 0.12 test3: 6.38 test3 opt: 0.52 test4: 4.70 test4 opt: 1.25 not opt version = dmd (no other option) opt version = dmd -O -release -inline Compile times opt version, seconds: test1: 0.05 test2: 0.05 test3: 0.28 test4: 0.29 The compilation time is the same, the not-opt test4 is faster than not-opt test3, but opt test4 is quite slower than opt test3. Bye, bearophile
Jun 21 2010
On 06/21/2010 08:28 PM, bearophile wrote:Andrei Alexandrescu:Thanks. Hmm. I redefined iota as follows: struct Iota(N, S) if ((isIntegral!N || isPointer!N) && isIntegral!S) { private N current, pastLast; private S step; this(N current, N pastLast, S step) { enforce(step != 0 && current != pastLast); this.current = current; this.step = step; if (step > 0) { this.pastLast = pastLast - 1; this.pastLast -= (this.pastLast - current) % step; } else { this.pastLast = pastLast + 1; this.pastLast += (this.pastLast - current) % step; } this.pastLast += step; } bool empty() const { return current == pastLast; } N front() { return current; } alias front moveFront; void popFront() { current += step; } N back() { return pastLast - step; } alias back moveBack; void popBack() { pastLast -= step; } Iota save() { return this; } N opIndex(size_t n) { return current + step * n; } size_t length() { return (pastLast - current) / step; } } Iota!(CommonType!(B, E), S) iota(B, E, S)(B begin, E end, S step) if (is(typeof((E.init - B.init) + 1 * S.init))) { return Iota!(CommonType!(B, E), S)(begin, end, step); } I optimized things such that the commonly used path (many calls to empty, front, and popFront) is as fast as possible. The initial work will be amortized for most loops. On my machine, test4 is still 2x slower than foreach_reverse in an optimized build. The disassembly reveals that the compiler refuses to inline some calls, which is disappointing as their bodies are very simple. AndreiThat's not too difficult; for integers, retro(iota(a, b)) could actually be a rewrite to iota(b - 1, a, -1).<This is good. In my dlibs the xchain converts xchain(xchain(x, y), z) and similar into xchain(x, y, z).Figuring out all corner cases, steps greater than 1, and what to do for floating point numbers is doable but not trivial either, and works against modularity.<I suggest to focus on the most important case, integer/uint indexes (and +1 or -1 increment). My post has shown some different problems: - A longer compilation time (and binary size) - A 1/10 performance when the code is compiled in standard way, this is bad - a smaller performance when the code is compiled in optimized mode. The asm of the opt version shows calls to two or more functions inside the loop, and one of those functions is not so small, this probably reduces performance more than an extra inlined product. So in my opinion getting rid of those calls (inlining them) is more important if you want a faster retro(iota). ------------------------ I have added your last version: // test4 import std.c.stdio: printf; import std.range: iota; void main() { enum int N = 100_000_000; int count; foreach (i; iota(N - 1, 0, -1)) count++; printf("%d\n", count); } Running time, best of 3, seconds: test1: 0.31 test1 opt: 0.07 test2: 0.31 test2 opt: 0.12 test3: 6.38 test3 opt: 0.52 test4: 4.70 test4 opt: 1.25 not opt version = dmd (no other option) opt version = dmd -O -release -inline Compile times opt version, seconds: test1: 0.05 test2: 0.05 test3: 0.28 test4: 0.29 The compilation time is the same, the not-opt test4 is faster than not-opt test3, but opt test4 is quite slower than opt test3. Bye, bearophile
Jun 21 2010
On 6/21/2010 8:12 PM, Andrei Alexandrescu wrote:I optimized things such that the commonly used path (many calls to empty, front, and popFront) is as fast as possible. The initial work will be amortized for most loops. On my machine, test4 is still 2x slower than foreach_reverse in an optimized build. The disassembly reveals that the compiler refuses to inline some calls, which is disappointing as their bodies are very simple. AndreiIf you would, file bugs with reduced tests and I'll work on the inliner.
Jun 21 2010
On page 6 it say: "the code sample above also introduced the if statement" but none of them do. -- ... <IXOYE><
Jun 21 2010
On 06/21/2010 10:01 PM, BCS wrote:On page 6 it say: "the code sample above also introduced the if statement" but none of them do.Could you please add that to the errata? http://erdani.com/tdpl/errata Andrei
Jun 21 2010
Andrei:I optimized things such that the commonly used path (many calls to empty, front, and popFront) is as fast as possible. The initial work will be amortized for most loops.<New timings: Running time, best of 3, seconds: test1: 0.31 test1 opt: 0.07 test2: 0.31 test2 opt: 0.12 test3: 6.38 test3 opt: 0.52 test3: 3.78 (new iota) test3 opt: 0.29 (new iota) test4: 4.70 test4 opt: 1.25 test4: 2.03 (new iota) test4 opt: 0.27 (new iota) Compile times opt version, seconds: test1: 0.05 test2: 0.05 test3: 0.28 test4: 0.23 (new iota) test4: 0.29 test4: 0.24 (new iota) (The difference in compile time between 0.29 and 0.23 is probably not significant. The difference between 0.05 and 0.23 is significant.) In my opinion the non-opt runtime timings too are important, because you can't compile code every time in opt mode. The normal for/foreach gives some performance even with no optmized compilation. It's good to optimize retro() so it can recognize the iota() argument and return just another iota().On my machine, test4 is still 2x slower than foreach_reverse in an optimized build.<As you see on mine in an optimized build it's a bit slower than 2x than foreach_reverse and more than 4x slower than a normal for loop.The disassembly reveals that the compiler refuses to inline some calls, which is disappointing as their bodies are very simple.<The code inside the loop here is very simple, it's just a variable (register) inc. In this case, in an optimized build GCC is able to optimize away the whole for loop. In my opinion a good D2 compiler has to to do the same with a foreach(retro(iota)) :-) If I am not wrong this is the inner loop of test4 with the new iota in opt build: L3F: mov ECX,018h[ESP] inc EBX add 010h[ESP],ECX mov EDX,010h[ESP] cmp EDX,014h[ESP] jne L3F It's not very good, but it's better than before. All those memory loads and stores are not necessary in this loop, they waste time. There is a call to this function, but it's before the call: _D3std5range13__T4IotaTiTiZ4Iota6__ctorMFNciiiZS3std5range13__T4IotaTiTiZ4Iota comdat L0: sub ESP,0Ch mov ECX,offset FLAT:_D3std5range13__T4IotaTiTiZ4Iota6__ctorMFNciiiZS3std5range13__T4IotaTiTiZ4Iota14__dgliteral607MFZAxa push EBX push EBP mov EBP,020h[ESP] push ESI mov ESI,EAX push EDI mov EDI,020h[ESP] test EDI,EDI mov 014h[ESP],EAX mov 018h[ESP],ECX je L28 cmp EBP,024h[ESP] jne L2C L28: xor EDX,EDX jmp short L31 L2C: mov EDX,1 L31: xor DL,1 je L5A push dword ptr FLAT:_DATA[054h] mov EDX,ECX push dword ptr FLAT:_DATA[050h] push 084Dh mov EAX,020h[ESP] mov EBX,020h[ESP] call EDX push EDX push EAX call near ptr _D3std9contracts7bailOutFAyaixAaZv L5A: test EDI,EDI mov [ESI],EBP mov 8[ESI],EDI jle L77 mov EDX,024h[ESP] dec EDX mov EAX,EDX mov 4[ESI],EDX sub EAX,EBP cdq idiv EDI sub 4[ESI],EDX jmp short L89 L77: mov ECX,024h[ESP] inc ECX mov EAX,ECX mov 4[ESI],ECX sub EAX,EBP cdq idiv EDI add 4[ESI],EDX L89: add 4[ESI],EDI mov EAX,ESI pop EDI pop ESI pop EBP pop EBX add ESP,0Ch ret 0Ch It's a lot of code, that's the iota constructor. The _D3std9contracts7bailOutFAyaixAaZv is probably the enforce or part of it. Doubling the loop size (N), the running time becomes about double, so such call to the constructor is not taking a lot of time (because there are no loops in the constructor). ------------------- I have seen that iota() contains: this(N current, N pastLast, S step) { enforce(step != 0 && current != pastLast); Indeed this throws: import std.range; void main() { int count; foreach (x; iota(10, 10, 1)) count++; } While his Python code gives no output:...for x in xrange(10, 10, 1): print x... In my opinion an empty loop is a valid loop, just as this is valid both syntactically and logically: for (int i = 10; i < 10; i++) {} for (int i = 20; i < 10; i++) {} So I suggest to replace that line in the iota() costructor with: enforce(step != 0); And then create an empty generator if pastLast <= current (and the step is 1). Bye, bearophilefor x in xrange(20, 10, 1): print x
Jun 22 2010
On 06/22/2010 07:18 AM, bearophile wrote:So I suggest to replace that line in the iota() costructor with: enforce(step != 0); And then create an empty generator if pastLast<= current (and the step is 1).Absolutely. I wrote that test to simplify my life, but in the final version iota should accept empty ranges. Andrei
Jun 22 2010
On pg. 12 you define a recursive binary search, you forgot to pass value on the recursive call. -B
Jun 22 2010
On 06/22/2010 11:16 AM, Byron Heads wrote:On pg. 12 you define a recursive binary search, you forgot to pass value on the recursive call. -BSaw the erratum you posted - thanks! Andrei
Jun 22 2010
Can someone sanity check me on the code on pages 334-5? Does the method push really need !empty in its in contract? I might not be fully awake yet >< A...
Jun 24 2010
Alix Pexton wrote:Can someone sanity check me on the code on pages 334-5? Does the method push really need !empty in its in contract? I might not be fully awake yet >< A...It has to be an error. If you couldn't push onto an empty stack, then you'd never be able to put anything on the stack. - Jonathan M Davis
Jun 24 2010
On 24/06/2010 09:09, Jonathan M Davis wrote:Alix Pexton wrote:That's what I thought, but it's there in the example over the page as well, so I though maybe I was missing something >< A...Can someone sanity check me on the code on pages 334-5? Does the method push really need !empty in its in contract? I might not be fully awake yet>< A...It has to be an error. If you couldn't push onto an empty stack, then you'd never be able to put anything on the stack. - Jonathan M Davis
Jun 24 2010
Alix Pexton wrote:On 24/06/2010 09:09, Jonathan M Davis wrote:I haven't look at it in detail yet, but it definitely looks like it's a copy-paste error, and it makes no sense for a push function to insist that something have already been pushed before you can push anything onto the stack. - Jonathan M DavisAlix Pexton wrote:That's what I thought, but it's there in the example over the page as well, so I though maybe I was missing something >< A...Can someone sanity check me on the code on pages 334-5? Does the method push really need !empty in its in contract? I might not be fully awake yet>< A...It has to be an error. If you couldn't push onto an empty stack, then you'd never be able to put anything on the stack. - Jonathan M Davis
Jun 24 2010
Does anyone else feel that the following is a fair clarification? Page 396 ... This means that communicating processors "forget" the exact order in which data was written: one tread writes x and then y and for a while another thread sees the new y but only the old x. vvv This means that communicating processors "forget" the exact order in which data was written: one tread writes to x and then to y and for a while another thread sees the new value of y but only the old value of x. ... Once I got my head around what is being claimed, I realised that it is correct as it appears, but it took me several reading to get there. It might just be because I'm a bit of a concurrency novice, but I'm sure I'm not the only one with a copy of tDPL ^^ A...
Jun 24 2010