Errors in TDPL
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
Re: Errors in TDPL
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
Re: Errors in TDPL
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 Davis Good 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...
Re: Errors in TDPL
On 6/21/10, bearophile wrote: > How do you write this? > foreach_reverse (i; 0 .. 10) foreach(i; retro(iota(0, 10))) { } ?
Re: Errors in TDPL
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. AAH THERE IS NOOO SEMICOLON AT THE END. Wow. Sorry. This is a pet peeve of mine.
Re: Errors in TDPL
Dnia 21-06-2010 o 21:57:49 Alix Pexton napisał(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, 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? Tomek
Re: Errors in TDPL
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] callnear 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 pushEBX pushESI 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 pushdword ptr FLAT:_DATA[064h] pushdword ptr FLAT:_DATA[060h] push051Fh mov EAX,018h[ESP] mov EBX,018h[ESP] callEDX pushEDX pushEAX callnear 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
Re: Errors in TDPL
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.
Re: Errors in TDPL
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
Re: Errors in TDPL
On 06/21/2010 04:06 PM, bearophile wrote: 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. 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. Andrei
Re: Errors in TDPL
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. AAH THERE IS NOOO SEMICOLON AT THE END. Wow. Sorry. This is a pet peeve of mine. Can't help that, sorry... Andrei
Re: Errors in TDPL
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
Re: Errors in TDPL
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
Re: Errors in TDPL
Andrei Alexandrescu wrote: 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 heh. I can't read. I loose a cookie.
Re: Errors in TDPL
Andrei Alexandrescu wrote: > 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). 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 Davis
Re: Errors in TDPL
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/errata For 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?
Re: Errors in TDPL
On 06/21/2010 06:30 PM, torhu wrote: 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/errata For 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? The PDF on Rough Cuts is identical to the printed book. Please report straight in the errata. Andrei
Re: Errors in TDPL
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
Re: Errors in TDPL
On 06/21/2010 06:35 PM, Leandro Lucarella wrote: 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... =) 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. Andrei
Re: Errors in TDPL
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
Re: Errors in TDPL
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
Re: Errors in TDPL
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. -- ... <
Re: Errors in TDPL
On page 6 it say: "the code sample above also introduced the if statement" but none of them do. -- ... <
Re: Errors in TDPL
On 06/21/2010 08:28 PM, bearophile wrote: 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 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. Andrei
Re: Errors in TDPL
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. > > > Andrei If you would, file bugs with reduced tests and I'll work on the inliner.
Re: Errors in TDPL
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 Davis That's a surprise to me. Walter, is that intentional? Andrei
Re: Errors in TDPL
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
Re: Errors in TDPL
On 21/06/2010 21:51, Tomek Sowiński wrote: Dnia 21-06-2010 o 21:57:49 Alix Pexton napisał(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, 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? Tomek 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! > > Did you know the following code compiles? > > > > 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! "); > > > } > > It's true! :) A...
Re: Errors in TDPL
Andrei Alexandrescu wrote: 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 Davis That's a surprise to me. Walter, is that intentional? 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#ScopeStatement
Re: Errors in TDPL
Le 22/06/10 10:54, Walter Bright a écrit : Andrei Alexandrescu wrote: 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 Davis That's a surprise to me. Walter, is that intentional? 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#ScopeStatement Not always: http://d.puremagic.com/issues/show_bug.cgi?id=4024
Re: Errors in TDPL
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 pushEBX pushEBP mov EBP,020h[ESP] pushESI mov ESI,EAX pushEDI mov EDI,020h[ESP] testEDI,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 pushdword ptr FLAT:_DATA[054h] mov EDX,ECX pushdword ptr FLAT:_DATA[050h] push084Dh mov EAX,020h[ESP] mov EBX,020h[ESP] callEDX pushEDX pushEAX callnear ptr _D3std9contracts7bailOutFAyaixAaZv L5A:testEDI,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 idivEDI 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 idivEDI 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 ... >>> >>> for x i
Re: Errors in TDPL
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
Re: Errors in TDPL
biozic wrote: Le 22/06/10 10:54, Walter Bright a écrit : Andrei Alexandrescu wrote: 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 Davis That's a surprise to me. Walter, is that intentional? 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#ScopeStatement Not always: http://d.puremagic.com/issues/show_bug.cgi?id=4024 Bugs in the compiler aren't errors in TDPL!
Re: Errors in TDPL
Le 22/06/10 15:53, Walter Bright a écrit : biozic wrote: Le 22/06/10 10:54, Walter Bright a écrit : Andrei Alexandrescu wrote: 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 Davis That's a surprise to me. Walter, is that intentional? 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#ScopeStatement Not always: http://d.puremagic.com/issues/show_bug.cgi?id=4024 Bugs in the compiler aren't errors in TDPL! I totally agree. I was saying that the requirement for braces was not always intentional :S
Re: Errors in TDPL
On pg. 12 you define a recursive binary search, you forgot to pass value on the recursive call. -B
Re: Errors in TDPL
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. -B Saw the erratum you posted - thanks! Andrei
Re: Errors in TDPL
On Mon, Jun 21, 2010 at 3:39 PM, Andrei Alexandrescu wrote: > 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. 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. --bb
Re: Errors in TDPL
On 06/22/2010 01:45 PM, Bill Baxter wrote: On Mon, Jun 21, 2010 at 3:39 PM, Andrei Alexandrescu wrote: 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. 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. If my puns suck I sure want to know which! Andrei
Re: Errors in TDPL
On Tue, 22 Jun 2010 11:45:39 -0700, Bill Baxter wrote: > On Mon, Jun 21, 2010 at 3:39 PM, Andrei Alexandrescu > wrote: >> 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. > > 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. Awful puns, you say? Now I have to buy a copy! Graham
Re: Errors in TDPL
Bill Baxter wrote: > On Mon, Jun 21, 2010 at 3:39 PM, Andrei Alexandrescu > wrote: >> 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. > > 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. > > --bb 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 Davis
Re: Errors in TDPL
On Tue, Jun 22, 2010 at 11:52 AM, Andrei Alexandrescu wrote: > On 06/22/2010 01:45 PM, Bill Baxter wrote: >> >> On Mon, Jun 21, 2010 at 3:39 PM, Andrei Alexandrescu >> wrote: >>> >>> 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. >> >> 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. > > If my puns suck I sure want to know which! > > Andrei 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 --bb
Re: Errors in TDPL
Andrei Alexandrescu wrote: > 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. AAH >> THERE IS NOOO SEMICOLON AT THE END. >> >> Wow. Sorry. This is a pet peeve of mine. > > Can't help that, sorry... > > Andrei 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 Davis
Re: Errors in TDPL
On 06/22/2010 04:14 PM, Jonathan M Davis wrote: Andrei Alexandrescu wrote: 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. AAH THERE IS NOOO SEMICOLON AT THE END. Wow. Sorry. This is a pet peeve of mine. Can't help that, sorry... Andrei 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 Davis 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? Andrei
Re: Errors in TDPL
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
Re: Errors in TDPL
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? > > > Andrei I 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
Re: Errors in TDPL
On 06/22/2010 04:53 PM, bearophile wrote: 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:; } 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. Andrei
Re: Errors in TDPL
Andrei: > > void 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), 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, bearophile
Re: Errors in TDPL
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
Re: Errors in TDPL
On 22/06/10 00:35, Leandro Lucarella wrote: 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... =) 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).
Re: Errors in TDPL
On Tue, 22 Jun 2010 23:37:59 +0200, Andrei Alexandrescu 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 code Andrei Rory
Re: Errors in TDPL
bearophile wrote: Andrei: void 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), 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, bearophile I think the ; is part of the label statement. If not, it should be removed entirely.
Re: Errors in TDPL
On Wed, 23 Jun 2010 11:56:12 +0200, Don wrote: > bearophile wrote: >> Andrei: void 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), >> >> 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, >> bearophile > > I think the ; is part of the label statement. If not, it should be > removed entirely. 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. -Lars
Re: Errors in TDPL
On 06/23/2010 04:56 AM, Don wrote: bearophile wrote: Andrei: void 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), 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, bearophile I think the ; is part of the label statement. If not, it should be removed entirely. Fortunately there's no label statement. A label is a distinct entity and may precede any statement. Andrei
Re: Errors in TDPL
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 Trelles That's great, except for those who enjoy "brace on its own line" formatting style. For those, the "}while" would look jarring. Andrei
Re: Errors in TDPL
Rory McGuire wrote: > On Tue, 22 Jun 2010 23:37:59 +0200, Andrei Alexandrescu > 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 code > >> Andrei > > Rory 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 Davis
Re: Errors in TDPL
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 ) ;
Re: Errors in TDPL
On 06/23/2010 11:40 AM, Walter Bright wrote: 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 ) ; 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? Andrei
Re: Errors in TDPL
On 23/06/2010 16:24, Andrei Alexandrescu wrote: 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 Trelles That's great, except for those who enjoy "brace on its own line" formatting style. For those, the "}while" would look jarring. Andrei 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...
Re: Errors in TDPL
On 23/06/2010 17:51, Andrei Alexandrescu wrote: On 06/23/2010 11:40 AM, Walter Bright wrote: 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 ) ; 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? Andrei ++vote A...
Re: Errors in TDPL
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
Re: Errors in TDPL
On 06/23/2010 05:44 PM, Alix Pexton wrote: On 23/06/2010 16:24, Andrei Alexandrescu wrote: 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 Trelles That's great, except for those who enjoy "brace on its own line" formatting style. For those, the "}while" would look jarring. Andrei 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... Walter agreed to fix do-while to require a semicolon. Andrei
Re: Errors in TDPL
== Quote from bearophile (bearophileh...@lycos.com)'s article > 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. 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. eles > Bye, > bearophile
Re: Errors in TDPL
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
Re: Errors in TDPL
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. > > eles Quality 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
Re: Errors in TDPL
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 (jmdavisp...@gmail.com)'s article > Quality 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
Re: Errors in TDPL
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...
Re: Errors in TDPL
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
Re: Errors in TDPL
On 24/06/2010 09:09, Jonathan M Davis wrote: 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 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...
Re: Errors in TDPL
Alix Pexton wrote: > On 24/06/2010 09:09, Jonathan M Davis wrote: >> 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 > > 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... 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 Davis
Re: Errors in TDPL
Andrei Alexandrescu 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
Re: Errors in TDPL
On Wed, 23 Jun 2010 11:51:40 -0500, Andrei Alexandrescu wrote: > On 06/23/2010 11:40 AM, Walter Bright wrote: >> 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 ) ; > > 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? Absolutely. -Lars
Re: Errors in TDPL
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...