Errors in TDPL

2010-06-21 Thread Jonathan M Davis
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

2010-06-21 Thread bearophile
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

2010-06-21 Thread Alix Pexton

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

2010-06-21 Thread Adam Ruppe
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

2010-06-21 Thread Ellery Newcomer
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

2010-06-21 Thread Tomek Sowiński
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

2010-06-21 Thread bearophile
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

2010-06-21 Thread Spacen Jasset
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

2010-06-21 Thread Andrei Alexandrescu

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

2010-06-21 Thread Andrei Alexandrescu

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

2010-06-21 Thread Andrei Alexandrescu

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

2010-06-21 Thread Andrei Alexandrescu

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

2010-06-21 Thread Andrei Alexandrescu

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

2010-06-21 Thread Spacen Jasset

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

2010-06-21 Thread Jonathan M Davis
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

2010-06-21 Thread torhu

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

2010-06-21 Thread Andrei Alexandrescu

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

2010-06-21 Thread Leandro Lucarella
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

2010-06-21 Thread Andrei Alexandrescu

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

2010-06-21 Thread bearophile
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

2010-06-21 Thread Jonathan M Davis
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

2010-06-21 Thread BCS

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

2010-06-21 Thread BCS
On page 6 it say: "the code sample above also introduced the if statement" 
but none of them do. 


--
... <





Re: Errors in TDPL

2010-06-21 Thread Andrei Alexandrescu

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

2010-06-21 Thread Brad Roberts
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

2010-06-21 Thread Andrei Alexandrescu

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

2010-06-21 Thread Andrei Alexandrescu

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

2010-06-22 Thread Alix Pexton

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

2010-06-22 Thread Walter Bright

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

2010-06-22 Thread biozic

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

2010-06-22 Thread bearophile
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

2010-06-22 Thread Andrei Alexandrescu

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

2010-06-22 Thread Walter Bright

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

2010-06-22 Thread biozic

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

2010-06-22 Thread Byron Heads
On pg. 12 you define a recursive binary search, you forgot to pass value 
on the recursive call.

-B



Re: Errors in TDPL

2010-06-22 Thread Andrei Alexandrescu

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

2010-06-22 Thread Bill Baxter
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

2010-06-22 Thread Andrei Alexandrescu

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

2010-06-22 Thread Graham Fawcett
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

2010-06-22 Thread Jonathan M Davis
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

2010-06-22 Thread Bill Baxter
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

2010-06-22 Thread Jonathan M Davis
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

2010-06-22 Thread Andrei Alexandrescu

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

2010-06-22 Thread bearophile
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

2010-06-22 Thread Jonathan M Davis
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

2010-06-22 Thread Andrei Alexandrescu

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

2010-06-22 Thread bearophile
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

2010-06-22 Thread Rick Trelles

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

2010-06-23 Thread Norbert Nemec

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

2010-06-23 Thread Rory McGuire
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

2010-06-23 Thread Don

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

2010-06-23 Thread Lars T. Kyllingstad
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

2010-06-23 Thread Andrei Alexandrescu

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

2010-06-23 Thread Andrei Alexandrescu

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

2010-06-23 Thread Jonathan M Davis
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

2010-06-23 Thread Walter Bright

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

2010-06-23 Thread Andrei Alexandrescu

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

2010-06-23 Thread Alix Pexton

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

2010-06-23 Thread Alix Pexton

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

2010-06-23 Thread bearophile
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

2010-06-23 Thread Andrei Alexandrescu

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

2010-06-23 Thread eles
== 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

2010-06-23 Thread bearophile
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

2010-06-23 Thread Jonathan M Davis
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

2010-06-24 Thread eles
 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

2010-06-24 Thread Alix Pexton

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

2010-06-24 Thread Jonathan M Davis
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

2010-06-24 Thread Alix Pexton

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

2010-06-24 Thread Jonathan M Davis
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

2010-06-24 Thread Simen kjaeraas

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

2010-06-24 Thread Lars T. Kyllingstad
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

2010-06-24 Thread Alix Pexton

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...