Re: dmd 2.029 release

2009-04-28 Thread Walter Bright

Georg Wrede wrote:

Walter Bright wrote:

I see I was being too obscure.
See Colossus, the Forbin Project http://us.imdb.com/title/tt0064177/


Heh, by an incredible coincidence, it aired here a couple of weeks ago. 
Maybe that's why I felt the reference too obvious to comment on.


I think it is an overlooked classic.


Re: dmd 2.029 release

2009-04-27 Thread renoX

Nick Sabalausky a écrit :
bearophile bearophileh...@lycos.com wrote in message 
news:gsipn1$1bn...@digitalmars.com...

Andrei Alexandrescu:

If it were an error, I wouldn't let it go.

It's an error. It will lead to troubles.



Sometimes it is an error, but there are times when it isn't:

[cut]

Call List In Psuedo-Japanese:
For Each Person Where Name=Smith: SmithSan {LoopIndex}'s DenwaBango: 
{Phone}

-

So then the report creation code:

-
foreach(int i, Person p; people.subset(customReport.whereClause))
writefln(customReport.formatStr, i, p.id, p.first, p.last, p.phone, 
p.zip);

-

That would be very difficult/limiting if every arg had to be used in the 
format string.


Mmmh, is {LoopIndex} correct? It should be {i} I think and I would argue 
that this format string should generate an error (something better than 
a runtime exception would be nice but I'm not sure that this is possible).


That said I agree that both are needed, so why not have either two 
different function or a function parameter which change the behaviour of 
the format string interpretation?


By default writefln would complain if there is a possibility of an 
unused parameter, but you could do
writefln(customReport.formatStr, i, p.id, p.first, p.last, p.phone, 
p.zip, allowUnused=true);


(Incidentally, this example also demonstrates why I consider C#/Tango-style 
string formatting superior to C/Phobos-style) 


I think that named format string are much superior to positional format 
string as they are easier to read/write..


BR,
renoX


Re: dmd 2.029 release

2009-04-27 Thread Walter Bright

Don wrote:
Actually, looking through the DMD source it becomes obvious that goto is 
really not a problem at all. The lack of comments is much more of a 
problem. (Especially with files with names like e2ir.c.


e2ir = Expression To Intermediate Representation


What the heck 
is fltables.c, cdxxx.c, elxxx.c ?). Even so, it's mostly not that 
difficult to understand.


Those are generated by optabgen.exe.


Re: dmd 2.029 release

2009-04-27 Thread Walter Bright

Georg Wrede wrote:
Yeah. But now I'm getting a bad conscience, this is beginning to look 
like Walter-bashing... :-)


Don't worry, I'm immune to that. Back in 1984 or so during a code review 
at work, a colleague grepped for goto and presented a listing of all the 
gotos with the comment about what a piece of crap my code was.


A lot of what I use goto for Andrei has demonstrated can be replaced 
with scope guards and his enforce template.


Re: dmd 2.029 release

2009-04-27 Thread Walter Bright

Georg Wrede wrote:

Walter Bright wrote:

Lutger wrote:

what the hell...this code can't be human.


I was replaced by Colossus years ago.


Michael A. Jackson wouldn't approve 1175 gotos in 113 files.



I see I was being too obscure.
See Colossus, the Forbin Project http://us.imdb.com/title/tt0064177/


Re: dmd 2.029 release

2009-04-27 Thread Christopher Wright

Walter Bright wrote:

Georg Wrede wrote:

Walter Bright wrote:

Lutger wrote:

what the hell...this code can't be human.


I was replaced by Colossus years ago.


Michael A. Jackson wouldn't approve 1175 gotos in 113 files.



I see I was being too obscure.
See Colossus, the Forbin Project http://us.imdb.com/title/tt0064177/


To clarify: you are *not* 80 feet high and protector of Rhodes?


Re: dmd 2.029 release

2009-04-27 Thread Sean Kelly

Stewart Gordon wrote:

Walter Bright wrote:

Stewart Gordon wrote:
Walter, how often do you update your working copy from the SVN? 
Obviously less than once every 2 releases.


As far as I know, it is current. Everything got checked in.


So how has the fix for
http://d.puremagic.com/issues/show_bug.cgi?id=2580
(and probably others) not been included?


The code fix for this is in.  You can see it in 
dmd/src/compiler/dmd/dmain2.d: rt_init().  I haven't updated the 
documentation yet though (this last release took me a bit by 
surprise)--I'll take care of that before the next release.


Re: dmd 2.029 release

2009-04-27 Thread Nick Sabalausky
renoX reno...@free.fr wrote in message news:49f56a74.4000...@free.fr...
 Nick Sabalausky a écrit :
 bearophile bearophileh...@lycos.com wrote in message 
 news:gsipn1$1bn...@digitalmars.com...
 Andrei Alexandrescu:
 If it were an error, I wouldn't let it go.
 It's an error. It will lead to troubles.


 Sometimes it is an error, but there are times when it isn't:
 [cut]
 Call List In Psuedo-Japanese:
 For Each Person Where Name=Smith: SmithSan {LoopIndex}'s DenwaBango: 
 {Phone}
 -

 So then the report creation code:

 -
 foreach(int i, Person p; people.subset(customReport.whereClause))
 writefln(customReport.formatStr, i, p.id, p.first, p.last, p.phone, 
 p.zip);
 -

 That would be very difficult/limiting if every arg had to be used in the 
 format string.

 Mmmh, is {LoopIndex} correct? It should be {i} I think and I would argue 
 that this format string should generate an error (something better than a 
 runtime exception would be nice but I'm not sure that this is possible).


That was just for illustrative purposes.


 (Incidentally, this example also demonstrates why I consider 
 C#/Tango-style string formatting superior to C/Phobos-style)

 I think that named format string are much superior to positional format 
 string as they are easier to read/write..


Actually, I was referring to the ability to specify them out-of-order, 
repeat them, etc. (I didn't realize that Phobos's writef had recently gained 
that ability). To my knowledge, C#/Tango string formatting don't actually 
support named strings, only numerical ones. I was just using names for 
illustrative purposes, and (unclearly) implying that the app would translate 
those named formats into numerical ones before passing them along to the 
string output function.




Re: dmd 2.029 release [OT]

2009-04-25 Thread BCS

Hello Nick,


I guess if you really hate having it not kill the app then the
program could just not /have/ a x button.


You've got to be kidding me, that would be just as bad. Why would I
want to have a program get rid of the standard exit mechanism?


If you basicly never want to exit it? (see below)


Whever I come across an app like that, the first thing I do is open
the task manager and kill it, and then immediately uninstall it.



I'll grant there are only very few cases where I want it, but in those cases 
I wouldn't have the program at all unless I wanted it running *all the time*. 
If I found myself killing/restarting the program more than rarely, I'd git 
rid of it and find one I don't have to do that with. For those apps, I basically 
never want to actually close them (even less often than I reboot) and on 
the few occasions when I do, I'm willing to do file-exit-Yes I really 
do sequence.


As an example of a program that works this way that I'll bet you don't mind: 
The volume control in the system tray. I'm not even sure if there /is/ a 
way to close it all the way.


To put it objectively: say the program take 10 sec to reload and 90% of the 
time (I'd bet that's low) that I click the x button, it was a mistake (bad 
mouse control, reflex go way action, whatever). From that it can take 90 
seconds to close the program before tuning off the x button is a net loss 
(as long as it's easy to figure out how to really kill it).


We may have to agree to disagree; I use a few programs where having the x 
button kill them would be a bad thing IMHO. You disagreeing really doesn't 
matter to me. 





Re: dmd 2.029 release

2009-04-25 Thread U u
Tomas Lindquist Olsen Wrote:

 On Mon, Apr 20, 2009 at 2:47 PM, Saaa em...@needmail.com wrote:
  Using D1 feels especially retarded today :(
 
 
 Why retarded ?
 I think because of new features
*cough* featurism *cough*


Re: dmd 2.029 release

2009-04-25 Thread U u
Tomas Lindquist Olsen Wrote:

 On Mon, Apr 20, 2009 at 2:47 PM, Saaa em...@needmail.com wrote:
  Using D1 feels especially retarded today :(
 
 
 Why retarded ?
 I think because of new features
*cough* featurism *cough*


Re: dmd 2.029 release [OT]

2009-04-24 Thread Georg Wrede

Steven Schveighoffer wrote:

On Thu, 23 Apr 2009 14:32:13 -0400, Georg Wrede georg.wr...@iki.fi wrote:
I mean, who's such a nutcase that he forgets halfway in the dragging, 
what it is he's dragging?


It might be useful if you accidentally start dragging the wrong thing, 
and then realize because you are dragging the wrong picture/text/etc.


But my point was really: you complained that you couldn't see the target 
because the picture is covering it.  My experience is that I can clearly 
see the target because the picture is translucent (I can see the target 
underneath the picture).



My complaint was about doing stuff just because you can. The dragging 
was just the first gross example that crossed my mind.


(I'm on a slow graphics card. Besides, it hasn't bothered me enough to 
start investigating. Heck, for all I know, I could configure it away.)


Re: dmd 2.029 release [OT]

2009-04-24 Thread Georg Wrede

Jarrett Billingsley wrote:

On Thu, Apr 23, 2009 at 2:32 PM, Georg Wrede georg.wr...@iki.fi wrote:


(OT: an excellent example of this It's Done Because We Noticed We Could
stuff is in Firefox. When a picture is a link to another page, and you want
to drag that to the tab area, the entire picture is dragged with the mouse.
Now, how the hell am I supposed to hit the small tab area when the large
picture covers half of my Firefox??

Sure it looks good, and the computer owner can brag to the guy in the next
cubicle, etc. But there should be some obvious or useful *purpose* for
dragging entire pictures where a mouse pointer would be clearer, cleaner,
easier for the user, and use less computer cycles.

I mean, who's such a nutcase that he forgets halfway in the dragging, what
it is he's dragging?


Middle-click.


Yeah.

But I still don't see the glamouros advantages in dragging whole pictures.

And I often drag stuff to existing tabs. A good example is when browsing 
http://apod.nasa.gov/apod/ap090424.html where I usually end up with a 
dozen tabs in no time.


Re: dmd 2.029 release [OT]

2009-04-24 Thread Georg Wrede

Steven Schveighoffer wrote:

On Thu, 23 Apr 2009 14:32:13 -0400, Georg Wrede georg.wr...@iki.fi wrote:

Steven Schveighoffer wrote:
On Thu, 23 Apr 2009 12:09:20 -0400, Georg Wrede georg.wr...@iki.fi 
So now I have to learn to remember to grab bigger pictures near some 
edge. And I really can't see *any* valid benefit for having to drag 
the picture. I'd rather have it the old way, where the mouse pointer 
simply changes shape, so you know you're dragging. Damn, damn...)
 On my system, dragging the image drags a translucent copy of the 
image, so I can still see where my mouse pointer is aimed.  Maybe you 
don't have enough colors enabled on your screen?


Sure it looks good, and the computer owner can brag to the guy in the 
next cubicle, etc. But there should be some obvious or useful 
*purpose* for dragging entire pictures where a mouse pointer would be 
clearer, cleaner, easier for the user, and use less computer cycles.


I mean, who's such a nutcase that he forgets halfway in the dragging, 
what it is he's dragging?


One thing that does annoy me is if you are doing this over a slow RDP 
link, the eye candy isn't worth it.


I was never a huge fan of application themes.  I don't mind a theme for 
the whole system (as long as it's simple), but I don't want iTunes to 
look different just because it can.  I think it has been discussed 
before that most video editors have the slickest GUI, with real-looking 
knobs and led's, but the video editing part of it is buggy as hell.


You're the first one to comment on the actual issue!!! :-)

Those video editors, iTunes and such look like they're programmed by 
12-year olds. Somewhere there should be an adult saying what not to do!


I bet the guy who did this never expected that whole-picture dragging 
actually uses more electricity in your computer. When every Firefox user 
(and the others who have to implement this too, so as not to look 
inferior!) in the whole world drags whole pictures, the combined 
increase in world electric usage rises well above his day-job salary.


Greenpeace ought to shoot him.


Re: dmd 2.029 release [OT]

2009-04-24 Thread Georg Wrede

Nick Sabalausky wrote:
Steven Schveighoffer schvei...@yahoo.com wrote in message 
news:op.usux6bskeav...@steves.networkengines.com...
I was never a huge fan of application themes.  I don't mind a theme for 
the whole system (as long as it's simple), but I don't want iTunes to look 
different just because it can.


That's one of my biggest pet peeves about modern software. I can't really do 
the subject justice without delving into a giant pile of expletives. 


It took me some serious browsing before I found a non-obtrusive skin for 
gmplayer. And I hated to have to do that. It should have been the default.


But worse still is when they decide to go and piss all over not just standard 
looks, but also standard behaviors. Like how the Win build of iTunes will 
still ignore/eat any click that brings it to the foreground. If I wanted 
that behavior I'd be running a Mac.


That's a good thing with many *nix GUIs. You can have several 
overlapping windows, and even do stuff in the non-top ones. But they 
really should respect the target GUIs way of doing things, when porting.


The absolute worst of all though is when an app (*cough* skype *cough*) 
decides that close and the 'close' button should mean don't close 
anything at all, but minimize to tray instead. That should be a firing 
squad offense ;) Joking aside though, any of these are guaranteed ways to 
make me lose any and all respect for a piece of software and its developers, 
especially if they're arrogant enough to provide no way to turn such things 
off.


Yeah, the biggest motivation (next to being graphical per se) for GUIs 
was uniform app behavior. That way you only would need to learn the 
common basics, and then, ostensibly, you could use any new app right off 
the bat. (In the bad old days, you really had to learn to use every app, 
one at a time.)


Re: dmd 2.029 release [OT]

2009-04-24 Thread Nick Sabalausky
BCS n...@anon.com wrote in message 
news:a6268ff50558cb926917215...@news.digitalmars.com...
 Hello Christopher,

 Nick Sabalausky wrote:

 The absolute worst of all though is when an app (*cough* skype
 *cough*) decides that close and the 'close' button should mean
 don't close anything at all, but minimize to tray instead. That
 should be a firing squad offense ;)

 I'd be killing my IM client constantly if not for that feature. I
 pretty much expect it of any application that's meant to be running
 for a long time and only rarely needing user interaction (such as a
 bittorrent client).


 yah, for some programs you rarely want to close the program but often want 
 to close the UI.


That's called Minimize. 




Re: dmd 2.029 release

2009-04-24 Thread Simen Kjaeraas

grauzone wrote:


void streamOut(T, R)(T object, R range)
{
foreach(x; a) range.put(x);
range.put(b);
range.put(c);
}


So, um... what is a b c and T object?


In my opinion, this is a confusing example. I believe it was meant to be:

void streamOut(T, R)(T object, R range)
{
 foreach(x; object.a) range.put(x);
 range.put(object.b);
 range.put(object.c);
}

So, streamOut is a free function, which it normally would not be. Now, consider 
this:

struct foo {
 int[] a;
 bool b;
 char c;

 void streamOut(R)(R range) {
   foreach(x; a) range.put(x);
   range.put(b);
   range.put(c);
 }
}

I believe this is what you'd normally do.

Do note that I might have misinterpreted it all, as Andrei's code would not do 
what I have outlined above, I only feel it makes the most sense.

--
 Simen


Re: dmd 2.029 release

2009-04-24 Thread grauzone

Simen Kjaeraas wrote:

grauzone wrote:


void streamOut(T, R)(T object, R range)
{
foreach(x; a) range.put(x);
range.put(b);
range.put(c);
}


So, um... what is a b c and T object?


In my opinion, this is a confusing example. I believe it was meant to be:

void streamOut(T, R)(T object, R range)
{
 foreach(x; object.a) range.put(x);
 range.put(object.b);
 range.put(object.c);
}

So, streamOut is a free function, which it normally would not be. Now, 
consider this:


struct foo {
 int[] a;
 bool b;
 char c;

 void streamOut(R)(R range) {
   foreach(x; a) range.put(x);
   range.put(b);
   range.put(c);
 }
}

I believe this is what you'd normally do.

Do note that I might have misinterpreted it all, as Andrei's code would 
not do what I have outlined above, I only feel it makes the most sense.


Yeah OK, but what about virtual functions? Not having it virtual is a 
real disadvantage, because subclass-parts aren't automatically dumped. 
What exactly is R, and why is it simpler than a Sink delegate? A Sink 
delegate is as simple as it gets, and what else than a string do you 
want to output? (Hint: this is probably not supposed to be a 
serialization framework.)


One thing that I could imagine that put() automatically takes care of 
formatting various data types into a string. Okay, where can I pass 
format specifiers? What if put() can't deal with the type? Or does it 
call std.string.format() anyway? Then why the indirection through the 
string? Why not call format() directly? (Yes, format() needs to be able 
to output using a sink instead of returning a string.)


Oh by the way, unlike a weird template, sink works with virtual methods, 
too.


I have the impression Andrei wants to cast everything into ranges 
instead of adhering to KISS.



--
 Simen


Re: dmd 2.029 release

2009-04-24 Thread grauzone

Andrei Alexandrescu wrote:

grauzone wrote:

Simen Kjaeraas wrote:
Do note that I might have misinterpreted it all, as Andrei's code 
would not do what I have outlined above, I only feel it makes the 
most sense.


Yeah OK, but what about virtual functions? Not having it virtual is a 
real disadvantage, because subclass-parts aren't automatically dumped.


Streaming out is a virtual function that takes a classic interface 
object. (I explained that in two posts.)


There were a lot of posts in this thread. From what I've gathered, what 
you said wasn't really concrete. Not as concrete as the sink proposals.


What exactly is R, and why is it simpler than a Sink delegate? A Sink 
delegate is as simple as it gets, and what else than a string do you 
want to output? (Hint: this is probably not supposed to be a 
serialization framework.)


It is simpler than a Sink delegate because the delegate is not simple; 
it's simplistic. You can't use std.algorithm with a delegate, it only 
accepts one type (meaning it is very inefficient if you have multiple 
types to output) - it's essentially a non-design.


At some point, you need to format it to a string anyway. And it's 
probably not favorable to move that code into some deeply buried library 
code, because then you don't have full control over formatting. Anyway, 
I don't quite understand what you want to do. We were talking abou 
improving toString, right?


One thing that I could imagine that put() automatically takes care of 
formatting various data types into a string. Okay, where can I pass 
format specifiers? What if put() can't deal with the type? Or does it 
call std.string.format() anyway? Then why the indirection through the 
string? Why not call format() directly? (Yes, format() needs to be 
able to output using a sink instead of returning a string.)


I'd spend more time on explaining that but I fear you want more to 
convince yourself and others that output streams are no good and that 
your non-design is simpler, than actually getting answers to your 
questions.


It's not my design, and I didn't even come up with that proposal. Come 
on, I know my tone and my posts is bitchy as hell, but flaming is not 
really what I'm up to.


Oh by the way, unlike a weird template, sink works with virtual 
methods, too.


I have the impression Andrei wants to cast everything into ranges 
instead of adhering to KISS.


I want to adhere to KISS, and therefore I want to support output ranges 
with e.g. strings and files. If you don't take the time to look at 
ranges as you yourself said, then why do you spend time commenting on 
them? Shouldn't things go the other way?


Oh, I look at the Phobos docs as it seems necessary. But I still might 
not know to the fullest how the pieces fit together and so on.




Andrei


Re: dmd 2.029 release

2009-04-24 Thread Andrei Alexandrescu

grauzone wrote:

Simen Kjaeraas wrote:
Do note that I might have misinterpreted it all, as Andrei's code 
would not do what I have outlined above, I only feel it makes the most 
sense.


Yeah OK, but what about virtual functions? Not having it virtual is a 
real disadvantage, because subclass-parts aren't automatically dumped.


Streaming out is a virtual function that takes a classic interface 
object. (I explained that in two posts.)


What exactly is R, and why is it simpler than a Sink delegate? A Sink 
delegate is as simple as it gets, and what else than a string do you 
want to output? (Hint: this is probably not supposed to be a 
serialization framework.)


It is simpler than a Sink delegate because the delegate is not simple; 
it's simplistic. You can't use std.algorithm with a delegate, it only 
accepts one type (meaning it is very inefficient if you have multiple 
types to output) - it's essentially a non-design.


One thing that I could imagine that put() automatically takes care of 
formatting various data types into a string. Okay, where can I pass 
format specifiers? What if put() can't deal with the type? Or does it 
call std.string.format() anyway? Then why the indirection through the 
string? Why not call format() directly? (Yes, format() needs to be able 
to output using a sink instead of returning a string.)


I'd spend more time on explaining that but I fear you want more to 
convince yourself and others that output streams are no good and that 
your non-design is simpler, than actually getting answers to your questions.


Oh by the way, unlike a weird template, sink works with virtual methods, 
too.


I have the impression Andrei wants to cast everything into ranges 
instead of adhering to KISS.


I want to adhere to KISS, and therefore I want to support output ranges 
with e.g. strings and files. If you don't take the time to look at 
ranges as you yourself said, then why do you spend time commenting on 
them? Shouldn't things go the other way?



Andrei


Re: dmd 2.029 release [OT]

2009-04-24 Thread BCS

Reply to Nick,


BCS n...@anon.com wrote in message
news:a6268ff50d58cb92d952e5b...@news.digitalmars.com...


Hello Nick,


BCS n...@anon.com wrote in message
news:a6268ff50558cb926917215...@news.digitalmars.com...

yah, for some programs you rarely want to close the program but
often want to close the UI.


That's called Minimize.


It can be, OTOH I might want the UI process killed without killing
the main program. Another point is the other side of the assertion,
you rarely want to close the program as in 90% of the time even
when I hit the x button, I don't actually want to close the program.


The whole point of the 'x' button is the close the program. Always has
been. If I didn't want to close the program, I wouldn't push it.


Are you saying you never make mistakes? There are program out there that 
90% of the time when I hit the x button it was a mistake and in that cases 
I think it to be a good design to work around it. I guess if you really hate 
having it not kill the app then the program could just not /have/ a x button.



If you want to hide/kill the UI without closing the program, that's
minimize. True, minimizing to the taskbar doesn't kill the UI
process/thread (assuming it even is a separate process/thread), but in
the rare cases where the distinction of UI process running/killed
actually matters, the program can still do that through a minimize to
tray. And while neither minimize nor close truly mean minimize to
tray, clearly minimize is FAR closer in both wording and behavior.
Any way you look at it, having a close button that doesn't close
the app is like having a cancel button that prints, or a save
button that plays music.



Your missing my point. I don't want to re-task the button but make it not 
do something that most of the time is not what I want.





Re: dmd 2.029 release [OT]

2009-04-24 Thread Steven Schveighoffer

On Fri, 24 Apr 2009 14:00:19 -0400, Nick Sabalausky a...@a.a wrote:


BCS n...@anon.com wrote in message
news:a6268ff50d58cb92d952e5b...@news.digitalmars.com...

Hello Nick,


BCS n...@anon.com wrote in message
news:a6268ff50558cb926917215...@news.digitalmars.com...


yah, for some programs you rarely want to close the program but often
want to close the UI.


That's called Minimize.



It can be, OTOH I might want the UI process killed without killing the
main program. Another point is the other side of the assertion, you
rarely want to close the program as in 90% of the time even when I hit
the x button, I don't actually want to close the program.



The whole point of the 'x' button is the close the program. Always has  
been.

If I didn't want to close the program, I wouldn't push it. If you want to
hide/kill the UI without closing the program, that's minimize. True,
minimizing to the taskbar doesn't kill the UI process/thread (assuming it
even is a separate process/thread), but in the rare cases where the
distinction of UI process running/killed actually matters, the program  
can
still do that through a minimize to tray. And while neither minimize  
nor
close truly mean minimize to tray, clearly minimize is FAR closer  
in
both wording and behavior. Any way you look at it, having a close  
button
that doesn't close the app is like having a cancel button that  
prints,

or a save button that plays music.


Yahoo messenger's X button behavior:

click on it - Although the main window has been closed, Yahoo! Messenger  
will continue to run in the system tray...


With a checkbox that says Show this message in the future.

That's perfect for me.  YM also has an option to automatically remove the  
taskbar button when minimized (so minimized does the behavior you want it  
to do).


-Steve


Re: dmd 2.029 release [OT]

2009-04-24 Thread Christopher Wright

BCS wrote:
I guess if you 
really hate having it not kill the app then the program could just not 
/have/ a x button.


Your window manager does not support such windows.


Re: dmd 2.029 release

2009-04-23 Thread Georg Wrede

Don wrote:

Georg Wrede wrote:

Don wrote:

Georg Wrede wrote:

Walter Bright wrote:

Lutger wrote:

what the hell...this code can't be human.


I was replaced by Colossus years ago.


Michael A. Jackson wouldn't approve 1175 gotos in 113 files.


It'd be really funny to pass it through one of those code quality 
metrics, one of the ones with a ridiculously heavy penalty for using 
goto. I think it'd tell you that DMD source is almost the 
lowest-quality code on the planet. g


Yeah. But now I'm getting a bad conscience, this is beginning to look 
like Walter-bashing... :-)


I think those code quality metrics are ridiculous. The prejudice against 
'goto' is really just brainwashing and totally without basis.


Well, at the time, they had no choice. Unstructured code was the norm, 
and people who tangled themselves in spaghetti never noticed it's 
because of goto usage. Instead they just preceived programming as hard.


The language on my first computer was old fashioned BASIC, with line 
numbers and no named subroutines or structural elements. I felt that the 
effort needed to program was exponential to the number of lines. In 
hindsight, that must have been entirely because I'd had no higher 
education in programming, no notion of structuring the code (in any 
particular way), etc. But the absolutely worst thing was that one 
couldn't pass parameters to subroutines. (gosub lineNumber) And all 
variables were global.


In those days most programming was done in COBOL, by (essentially) 
non-programmers. (The idea of COBOL was, after all, to be usable by 
business people, not MSc programmers.) Jackson had to change not only 
the methodology, but before that, the concept and the motivation for 
using structured programming. That was the hard part, and it needed some 
serious evangelising and brainwashing, to overcome the inertia.


Unfortunately, that meant murdering, dismembering, and pulverizing any 
least hint of even thinking about using goto. And as with any paradigm 
shift, the disciples took it to religious extremes.



Here's a recent link from Andrew Koenig, who really should know better.

http://dobbscodetalk.com/index.php?option=com_myblogshow=What-Dijkstra-said-was-harmful-about-goto-statements.htmlItemid=29 

Can you see his fundamental mistake? He talks about the program (just 
as Dijkstra said), but it's just not relevant for C/C++/D/Pascal/...
or any other structured programming language. Wherever he says program 
you should substitute function. And then the force of the argument 
totally disappears.


Yes.

The problem with goto in an unstructured language is that when you see a 
label, you don't know where it came from. It could be anywhere in the 
entire program (maybe a million lines of code!) And that's a complete 
disaster. But in a structured language, you know it's from somewhere in 
the function.
And this is no different from any other control structure. You ALWAYS 
have to look at the whole scope you're in.


void foo(){
 int n;
bool b = true;
  while (b) {
if (n==4) {   /* when do we get here? You have to read the whole 
function to find out. Where does n get modified? */ }

:
:
:
  }
}

Heck, even in inline ASM in D, you can't write the kind of spaghetti 
code Dijkstra was complaining about. You always have local scope.


OTOH, getting the algorithm may become tedious even in small snippets. 
For example, here's Algorithm M, from /Fundamental Algorithms/, Knuth 
1969, page 95:


M1: int j=n; int k=n; int m=X[n];
M2: if(k==0) goto M6;
M3: if(X[k] = m) goto M5;
M4: j=k; m=X[k];
M5: k--; goto M2;
M6: ;

That's three gotos for six lines. How long did it take to fully figure 
out what it's doing? Way longer than if it were written in structured D, 
anyway.


Yet, I personally have been so affected by anti-goto brainwashing that 
I've never used goto in C, C++, or D. But I gradually realised that it 
was just brainwashing. I've never experienced any problem with goto in ASM.


Same here. Last time I used it was in Pascal, and boy, did I have a bad 
conscience. It felt like I was doing something Mom has forbidden.


Actually, looking through the DMD source it becomes obvious that goto 
is really not a problem at all. The lack of comments is much more of 
a problem. (Especially with files with names like e2ir.c. What the 
heck is fltables.c, cdxxx.c, elxxx.c ?). Even so, it's mostly 
not that difficult to understand.


I guess Walter has to keep alternating between ASM, C and D. And a lot 
of ASM coding is nothing more than a bunch of MOV and JMP stuff. And 
file naming conventions here look like what one typically finds in 
development code (before some pre-publishing guy has tidyed it up with 
a lot of global searchreplaces). And, after all, the C files never 
were meant to be public anyway.


Actually, the one interesting question might be, would rewriting this 
code in a structured fashion (I mean, removing the gotos) make it 
slower? (Not that I'd be 

Re: dmd 2.029 release

2009-04-23 Thread Andrei Alexandrescu
Masahiro Nakagawa wrote:
 I submitted this problem to bugzilla.
 http://d.puremagic.com/issues/show_bug.cgi?id=2882

Thanks! I fixed it and checked in std.random.

Andrei


Re: dmd 2.029 release

2009-04-23 Thread bearophile
This post is mostly for Andrei.
I have played with D2 a bit; probably I'll need months to digest it and its new 
Phobos2. While I explore Phobos I'll probably post some comments/bugs around 
here.

After reading this:
http://blogs.msdn.com/vcblog/archive/2009/04/22/decltype-c-0x-features-in-vc10-part-3.aspx
I have tried to write a toy implementation of it in D2 (not using Phobos2 yet):

import std.stdio: writeln;
import std.string: format;

struct Watts {
int _x;
int x() const { return this._x; }
Joules opMul(Seconds s) {
return Joules(this._x * s.x);
}
string toString() { return format(Watts(%s), this._x); }
}

struct Seconds {
int _x;
int x() const { return this._x; }
Joules opMul(Watts w) {
return Joules(this._x * w.x);
}
string toString() { return format(Seconds(%s), this._x); }
}

struct Joules {
int _x;
int x() const { return this._x; }
string toString() { return format(Joules(%s), this._x); }
}

auto map(alias f, TySeq1, TySeq2)(TySeq1 a1, TySeq2 a2) {
assert(a1.length == a2.length);
auto result = new typeof( f(a1[0], a2[0]) )[a1.length];
for (int i; i  a1.length; i++)
result[i] = f(a1[i], a2[i]);
return result;
}

void main() {
auto watts = [Watts(2), Watts(3), Watts(4)];
writeln(watts);

auto secs = [Seconds(5), Seconds(6), Seconds(7)];
writeln(secs);

auto result = map!( (x, y){ return x*y; } )(watts, secs);
writeln(result);
}

Few notes:
- Lacking struct inheritance I have duplicated code.
- This whole proggy is not difficult to write. It's simpler than the C++ one. 
But I think it's a bit less general.
- Here I have not used const in input arguments yet, nor the map of Phobos2.
- (x, y){ return x*y; } is one of the new template literals. Can I define it 
elsewhere, like in an alias? So far I have failed doing that.

Two things to improve:
1) All structs must have a default built-in opString, a good representation can 
be:
StructName(field_value1, field_value2, field_value1, ...).
It's not a perfect textual representation, but it's WAY better than the current 
one (currently it shows just the struct name).
(Printing the module name before the struct name is bad, most times is just 
noise)

2) The output of that program is:
Watts(2) Watts(3) Watts(4)
Seconds(5) Seconds(6) Seconds(7)
Joules(10) Joules(18) Joules(28)

I think a much better output is:
[Watts(2), Watts(3), Watts(4)]
[Seconds(5),  Seconds(6),  Seconds(7)]
[Joules(10),  Joules(18),  Joules(28)]

Note the space after the comma, it's a small detail but it improves readability 
significantly.
(This representation doesn't tell apart dynamic arrays from static ones, but I 
can live with this).



I don't remember if vector ops support user-defined opMul too, I have tried 
this code, but maybe I am doing something wrong:

...
Joules[3] result2;
result2[] = watts[] * secs[];
writeln(result2);
}

Bye,
bearophile


Re: dmd 2.029 release

2009-04-23 Thread Don

bearophile wrote:

This post is mostly for Andrei.
I have played with D2 a bit; probably I'll need months to digest it and its new 
Phobos2. While I explore Phobos I'll probably post some comments/bugs around 
here.

After reading this:
http://blogs.msdn.com/vcblog/archive/2009/04/22/decltype-c-0x-features-in-vc10-part-3.aspx
I have tried to write a toy implementation of it in D2 (not using Phobos2 yet):

import std.stdio: writeln;
import std.string: format;

struct Watts {
int _x;
int x() const { return this._x; }
Joules opMul(Seconds s) {
return Joules(this._x * s.x);
}
string toString() { return format(Watts(%s), this._x); }
}

struct Seconds {
int _x;
int x() const { return this._x; }
Joules opMul(Watts w) {
return Joules(this._x * w.x);
}
string toString() { return format(Seconds(%s), this._x); }
}

struct Joules {
int _x;
int x() const { return this._x; }
string toString() { return format(Joules(%s), this._x); }
}

auto map(alias f, TySeq1, TySeq2)(TySeq1 a1, TySeq2 a2) {
assert(a1.length == a2.length);
auto result = new typeof( f(a1[0], a2[0]) )[a1.length];
for (int i; i  a1.length; i++)
result[i] = f(a1[i], a2[i]);
return result;
}

void main() {
auto watts = [Watts(2), Watts(3), Watts(4)];
writeln(watts);

auto secs = [Seconds(5), Seconds(6), Seconds(7)];
writeln(secs);

auto result = map!( (x, y){ return x*y; } )(watts, secs);
writeln(result);
}

Few notes:
- Lacking struct inheritance I have duplicated code.
- This whole proggy is not difficult to write. It's simpler than the C++ one. 
But I think it's a bit less general.
- Here I have not used const in input arguments yet, nor the map of Phobos2.
- (x, y){ return x*y; } is one of the new template literals. Can I define it 
elsewhere, like in an alias? So far I have failed doing that.

Two things to improve:
1) All structs must have a default built-in opString, a good representation can 
be:
StructName(field_value1, field_value2, field_value1, ...).
It's not a perfect textual representation, but it's WAY better than the current 
one (currently it shows just the struct name).
(Printing the module name before the struct name is bad, most times is just 
noise)


No!
rant
toString() is one of the most dreadful features in D. Trying to slightly 
improve it is a waste of time -- the whole concept needs to be redone.
It's horribly inflexible, tedious, and hugely inefficient. What more 
could there be to hate?


- the object being called has no context. It doesn't know what format is 
desired, for example.
- you can't emulate formatting of built-in types, NOT EVEN int! You 
can't do left-align, pad with zeros, include + sign, display in hex.


- it's got no stream concept. Every object has to create and manage its 
own buffer, and nobody knows if anyone actually needs it.


It ought to be at least as simple as:

struct Foo(A, B, C){
A[10] a;
B b;
C c;
void toString(Sink sink){
   foreach(x; a) sink(x);
   sink(b);
   sink(c);
}
}
... but it's not, you have to create a silly buffer to put all your 
strings in, even if there are 200 million of them and your giant string 
is just going to be written to a file anyway.


I'd like to see version(debug) {} put around Object.toString(). It's a 
deathtrap feature that's got no business being used other than for 
debugging.

/rant




2) The output of that program is:
Watts(2) Watts(3) Watts(4)
Seconds(5) Seconds(6) Seconds(7)
Joules(10) Joules(18) Joules(28)

I think a much better output is:
[Watts(2), Watts(3), Watts(4)]
[Seconds(5),  Seconds(6),  Seconds(7)]
[Joules(10),  Joules(18),  Joules(28)]

Note the space after the comma, it's a small detail but it improves readability 
significantly.
(This representation doesn't tell apart dynamic arrays from static ones, but I 
can live with this).



I don't remember if vector ops support user-defined opMul too, I have tried 
this code, but maybe I am doing something wrong:

...
Joules[3] result2;
result2[] = watts[] * secs[];
writeln(result2);
}

Bye,
bearophile


Re: dmd 2.029 release

2009-04-23 Thread Don

bearophile wrote:

Don:
I really don't understand the backend. It's quite cryptic. Key acronyms 
are AE, CP and VBE. Then there's Bin, Bgen, Bkill, etc.

AE *might* be Available Expression (but what does that mean?)
CP might be Copy Propagation info
I've found that VBE = Very Busy Expression! (what does that mean?)


I suggest to add comments to the DMD source code every time a small mystery is 
revealed, to rename the files once a much better name is found, to improve and 
refactor the code every time it a good thing to do it. Every time you put your 
hand in the code you can improve the code locally and leave it better then 
before (this is the Scout principle in programming).
Then such patches/changes can be slowly folded back into DMD and with time the 
sources will improve and will become more readable. Once they can be understood 
better, further changes become faster and simpler.


I'd love to do that, but unfortunately it's not easy to get _any_ 
changes into DMD. Only Walter has write-access to it, and AFAIK he 
checks every line and enters it manually. Like Linus was famous for 
doing with the Linux kernel.




Bye,
bearophile


Re: dmd 2.029 release

2009-04-23 Thread grauzone

No!
rant
toString() is one of the most dreadful features in D. Trying to slightly 
improve it is a waste of time -- the whole concept needs to be redone.
It's horribly inflexible, tedious, and hugely inefficient. What more 
could there be to hate?


Hey, it's only meant for debugging! (At least I hope.)


Re: dmd 2.029 release

2009-04-23 Thread Simen Kjaeraas

Don wrote:

I'd like to see version(debug) {} put around Object.toString(). It's a  
deathtrap feature that's got no business being used other than for  
debugging.


That actually sounds like a good idea. Like you say, is has no use
outside of debugging, but while debugging, it's quite useful.

--
 Simen


Re: dmd 2.029 release

2009-04-23 Thread Masahiro Nakagawa
On Thu, 23 Apr 2009 18:09:06 +0900, Andrei Alexandrescu  
seewebsiteforem...@erdani.org wrote:



Masahiro Nakagawa wrote:

I submitted this problem to bugzilla.
http://d.puremagic.com/issues/show_bug.cgi?id=2882


Thanks! I fixed it and checked in std.random.


Wow!

std.random in svn works fine.

Thanks for your quick response.

--
tama repeate...@gmail.com
http://profile.livedoor.com/repeatedly/


Re: dmd 2.029 release

2009-04-23 Thread Denis Koroskin
On Thu, 23 Apr 2009 16:20:03 +0400, Don nos...@nospam.com wrote:

 bearophile wrote:
 This post is mostly for Andrei.
 I have played with D2 a bit; probably I'll need months to digest it and  
 its new Phobos2. While I explore Phobos I'll probably post some  
 comments/bugs around here.
  After reading this:
 http://blogs.msdn.com/vcblog/archive/2009/04/22/decltype-c-0x-features-in-vc10-part-3.aspx
 I have tried to write a toy implementation of it in D2 (not using  
 Phobos2 yet):
  import std.stdio: writeln;
 import std.string: format;
  struct Watts {
 int _x;
 int x() const { return this._x; }
 Joules opMul(Seconds s) {
 return Joules(this._x * s.x);
 }
 string toString() { return format(Watts(%s), this._x); }
 }
  struct Seconds {
 int _x;
 int x() const { return this._x; }
 Joules opMul(Watts w) {
 return Joules(this._x * w.x);
 }
 string toString() { return format(Seconds(%s), this._x); }
 }
  struct Joules {
 int _x;
 int x() const { return this._x; }
 string toString() { return format(Joules(%s), this._x); }
 }
  auto map(alias f, TySeq1, TySeq2)(TySeq1 a1, TySeq2 a2) {
 assert(a1.length == a2.length);
 auto result = new typeof( f(a1[0], a2[0]) )[a1.length];
 for (int i; i  a1.length; i++)
 result[i] = f(a1[i], a2[i]);
 return result;
 }
  void main() {
 auto watts = [Watts(2), Watts(3), Watts(4)];
 writeln(watts);
  auto secs = [Seconds(5), Seconds(6), Seconds(7)];
 writeln(secs);
  auto result = map!( (x, y){ return x*y; } )(watts, secs);
 writeln(result);
 }
  Few notes:
 - Lacking struct inheritance I have duplicated code.
 - This whole proggy is not difficult to write. It's simpler than the  
 C++ one. But I think it's a bit less general.
 - Here I have not used const in input arguments yet, nor the map of  
 Phobos2.
 - (x, y){ return x*y; } is one of the new template literals. Can I  
 define it elsewhere, like in an alias? So far I have failed doing that.
  Two things to improve:
 1) All structs must have a default built-in opString, a good  
 representation can be:
 StructName(field_value1, field_value2, field_value1, ...).
 It's not a perfect textual representation, but it's WAY better than the  
 current one (currently it shows just the struct name).
 (Printing the module name before the struct name is bad, most times is  
 just noise)

 No!
 rant
 toString() is one of the most dreadful features in D. Trying to slightly  
 improve it is a waste of time -- the whole concept needs to be redone.
 It's horribly inflexible, tedious, and hugely inefficient. What more  
 could there be to hate?

 - the object being called has no context. It doesn't know what format is  
 desired, for example.
 - you can't emulate formatting of built-in types, NOT EVEN int! You  
 can't do left-align, pad with zeros, include + sign, display in hex.

 - it's got no stream concept. Every object has to create and manage its  
 own buffer, and nobody knows if anyone actually needs it.

 It ought to be at least as simple as:

 struct Foo(A, B, C){
 A[10] a;
 B b;
 C c;
 void toString(Sink sink){
 foreach(x; a) sink(x);
 sink(b);
 sink(c);
 }
 }
 ... but it's not, you have to create a silly buffer to put all your  
 strings in, even if there are 200 million of them and your giant string  
 is just going to be written to a file anyway.


Absolutely agree, but Sink is not good, either. I have previously suggested the 
following design (but can't find my post anymore):

A signature of toString() should be as follows:

char[] toString(string format = null, char[] buffer = null);

Bonuses you get from that:
You don't have to change your code (aside from toString() returning mutable 
array now, but it is very easy to fix)
It allows you to avoid allocations - just pass a temporary buffer to use!
It allows you to use advanced formatting options

Example:

class Number {
private int _number;
char[] toString(string format = null, char[] buffer = null) {
Format format = Format.Decimal;
switch (format) {
case x: format = Format.Hexademical;
case X: format = Format.HexademicalUpperCase;
case b: format = Format.Binary;
// ...
}

return formatInteger(_number, format, buffer);
}

static char[] formatInteger(int value, Format format, char[] buffer)
{
// writes to buffer, resizing it
}
}

Cons: printf-style formatting works badly with this desing.
I belive it should be dropped anyway, in favor of a more flexible .NET-style 
formatting:

writefln(My name is {} and I'm 0x{X} years old, Denis, 22);

// calls name.toString(, buffer) and age.toString(X, buffer)
Result: My name is Denis and I'm 0x16 years old.

Here is another example:

MyArray myArray = new MyArray(10, 20, 30);

char[1024] buffer;
string.format(buffer, Array contents: [{{X}, }], myArray);

// calls myArray.toString({X}, , 

Re: dmd 2.029 release

2009-04-23 Thread Andrei Alexandrescu

Don wrote:

No!
rant
toString() is one of the most dreadful features in D. Trying to slightly 
improve it is a waste of time -- the whole concept needs to be redone.
It's horribly inflexible, tedious, and hugely inefficient. What more 
could there be to hate?


I agree.

- the object being called has no context. It doesn't know what format is 
desired, for example.
- you can't emulate formatting of built-in types, NOT EVEN int! You 
can't do left-align, pad with zeros, include + sign, display in hex.


- it's got no stream concept. Every object has to create and manage its 
own buffer, and nobody knows if anyone actually needs it.


Yah. std.stdio and std.format already uses streaming internally to some 
extent. I plan to make it entirely possible to dump a string and a 
binary representation of an object to a generic stream, without having 
to allocate any memory in the process.



It ought to be at least as simple as:

struct Foo(A, B, C){
A[10] a;
B b;
C c;
void toString(Sink sink){
   foreach(x; a) sink(x);
   sink(b);
   sink(c);
}
}
... but it's not, you have to create a silly buffer to put all your 
strings in, even if there are 200 million of them and your giant string 
is just going to be written to a file anyway.


Yes. The way it should be is not with sink, but with the standard output 
iterator method put().


void streamOut(T, R)(T object, R range)
{
foreach(x; a) range.put(x);
range.put(b);
range.put(c);
}

I'd like to see version(debug) {} put around Object.toString(). It's a 
deathtrap feature that's got no business being used other than for 
debugging.


Well toString is ok for casual uses, but I agree that true streaming 
mops the floor with it.



Andrei


Re: dmd 2.029 release

2009-04-23 Thread Steven Schveighoffer
On Thu, 23 Apr 2009 09:06:38 -0400, Andrei Alexandrescu  
seewebsiteforem...@erdani.org wrote:



It ought to be at least as simple as:
 struct Foo(A, B, C){
A[10] a;
B b;
C c;
void toString(Sink sink){
   foreach(x; a) sink(x);
   sink(b);
   sink(c);
}
}
... but it's not, you have to create a silly buffer to put all your  
strings in, even if there are 200 million of them and your giant string  
is just going to be written to a file anyway.


Yes. The way it should be is not with sink, but with the standard output  
iterator method put().


void streamOut(T, R)(T object, R range)
{
 foreach(x; a) range.put(x);
 range.put(b);
 range.put(c);
}


What is the T object for?

This has to go into object.d and be part of the runtime, where std.range  
doesn't exist.  There is nothing stopping you from calling:


streamOut(outputrange.put);

So I'd rather have a sink function.

And I wholeheartedly agree that we need this.  I've run into many  
situations where toString makes no sense.


-Steve


Re: dmd 2.029 release

2009-04-23 Thread Andrei Alexandrescu

Steven Schveighoffer wrote:
On Thu, 23 Apr 2009 09:06:38 -0400, Andrei Alexandrescu 
seewebsiteforem...@erdani.org wrote:



It ought to be at least as simple as:
 struct Foo(A, B, C){
A[10] a;
B b;
C c;
void toString(Sink sink){
   foreach(x; a) sink(x);
   sink(b);
   sink(c);
}
}
... but it's not, you have to create a silly buffer to put all your 
strings in, even if there are 200 million of them and your giant 
string is just going to be written to a file anyway.


Yes. The way it should be is not with sink, but with the standard 
output iterator method put().


void streamOut(T, R)(T object, R range)
{
 foreach(x; a) range.put(x);
 range.put(b);
 range.put(c);
}


What is the T object for?


Red herring. If streamOut is a member, no need for T.

This has to go into object.d and be part of the runtime, where std.range 
doesn't exist.  There is nothing stopping you from calling:


streamOut(outputrange.put);

So I'd rather have a sink function.


It must be a sink _object_ so it can hold its own state. And it must 
support put() so it integrates with statically-bound output ranges.


interface OutRange
{
void put(... a number of overloads ...);
}

And I wholeheartedly agree that we need this.  I've run into many 
situations where toString makes no sense.


Same here...


Andrei


Re: dmd 2.029 release

2009-04-23 Thread Steven Schveighoffer
On Thu, 23 Apr 2009 09:24:59 -0400, Andrei Alexandrescu  
seewebsiteforem...@erdani.org wrote:



Steven Schveighoffer wrote:
This has to go into object.d and be part of the runtime, where  
std.range doesn't exist.  There is nothing stopping you from calling:

 streamOut(outputrange.put);
 So I'd rather have a sink function.


It must be a sink _object_ so it can hold its own state. And it must  
support put() so it integrates with statically-bound output ranges.


interface OutRange
{
 void put(... a number of overloads ...);
}


I see now, yes I agree (I think that was don's original request anyways).   
That interface has to go in the runtime, though.


We may not be able to do this using templates... it has to be a virtual  
function in Object to be on-par with toString.  This means struct  
interfaces are a requirement if you want to use ranges :(


-Steve


Re: dmd 2.029 release

2009-04-23 Thread Frits van Bommel

Denis Koroskin wrote:

On Thu, 23 Apr 2009 16:20:03 +0400, Don nos...@nospam.com wrote:


struct Foo(A, B, C){
A[10] a;
B b;
C c;
void toString(Sink sink){
foreach(x; a) sink(x);
sink(b);
sink(c);
}
}
... but it's not, you have to create a silly buffer to put all your  
strings in, even if there are 200 million of them and your giant string  
is just going to be written to a file anyway.




Absolutely agree, but Sink is not good, either. I have previously suggested the 
following design (but can't find my post anymore):

A signature of toString() should be as follows:

char[] toString(string format = null, char[] buffer = null);

Bonuses you get from that:
You don't have to change your code (aside from toString() returning mutable 
array now, but it is very easy to fix)
It allows you to avoid allocations - just pass a temporary buffer to use!


It'll still allocate if the buffer isn't big enough.

I usually define something like void streamTo(Sink sink) in a base class if I 
want non-allocating output. Adding a format string to the parameter list should 
be easy, but I haven't needed it yet.
I then usually implement toString by passing an appending Sink to that method, 
just so Tango's formatting methods will be able to use it.




IMHO It'd be pretty nice for the standard formatting systems (both the Tango and 
Phobos ones) to just call a standard Object method taking (Sink sink, char[] 
format = null) on objects.


Backward compatibility might be tricky though, if you want to support both 
overriding and calling of toString(). (You can't have the default toString 
implementation call the format function *and* have the default format function 
implementation call toString)


Though I suppose you could take a delegate to toString in the default format 
method and see if the function pointer in it points to Object.toString, just 
calling sink(this.classinfo.name) if so (to emulate current behavior), and 
calling toString() if not...
(Or maybe the other way around; have Object.toString check if the format 
function was overridden, call it if so and return the classname if not)


Re: dmd 2.029 release

2009-04-23 Thread Georg Wrede

Don wrote:

bearophile wrote:

This post is mostly for Andrei.
I have played with D2 a bit; probably I'll need months to digest it 
and its new Phobos2. While I explore Phobos I'll probably post some 
comments/bugs around here.


After reading this:
http://blogs.msdn.com/vcblog/archive/2009/04/22/decltype-c-0x-features-in-vc10-part-3.aspx 

I have tried to write a toy implementation of it in D2 (not using 
Phobos2 yet):


import std.stdio: writeln;
import std.string: format;

struct Watts {

...


Two things to improve:
1) All structs must have a default built-in opString, a good 
representation can be:

StructName(field_value1, field_value2, field_value1, ...).
It's not a perfect textual representation, but it's WAY better than 
the current one (currently it shows just the struct name).
(Printing the module name before the struct name is bad, most times is 
just noise)


No!
rant
toString() is one of the most dreadful features in D. Trying to slightly 
improve it is a waste of time -- the whole concept needs to be redone.
It's horribly inflexible, tedious, and hugely inefficient. What more 
could there be to hate?


- the object being called has no context. It doesn't know what format is 
desired, for example.
- you can't emulate formatting of built-in types, NOT EVEN int! You 
can't do left-align, pad with zeros, include + sign, display in hex.


- it's got no stream concept. Every object has to create and manage its 
own buffer, and nobody knows if anyone actually needs it.


It ought to be at least as simple as:

struct Foo(A, B, C){
A[10] a;
B b;
C c;
void toString(Sink sink){
   foreach(x; a) sink(x);
   sink(b);
   sink(c);
}
}
... but it's not, you have to create a silly buffer to put all your 
strings in, even if there are 200 million of them and your giant string 
is just going to be written to a file anyway.


I'd like to see version(debug) {} put around Object.toString(). It's a 
deathtrap feature that's got no business being used other than for 
debugging.

/rant


First of all, printing stuff struct.toString() style is for two things:

 o  Debugging
 o  Small throwaway code snippets

The latter mainly being for two purposes:

 o  Testing quick concepts, trying out library functions, etc.
 o  For the newbie, when he's learning D, but not output formatting.

No Real Program uses this, because there you typically do proper 
formatting of the output anyway, and almost never print entire structs 
or objects as such. Instead, rather the information that they represent.




Second, since we have cool stuff in D, like templates, boxing, and other 
advanced things, then compared to them, it should not be a big deal to 
have automatic creation of toString for structs and objects. (This could 
even be on-demand, i.e. unless called, the toString is not created for 
an object/struct.)


Since the purpose of toString here is not Grand Style, it should suffice 
to just recursively print the struct with its possible substructs, etc.


This would relieve the programmer from the entire extra work, and it 
would also make objects look tidyer in source code.


Actually, this way, it would become trivial to print stuff:

myFancyStructWithInnerStructs st;
myRealCoolObject mo;
int i;
float f;
string s;

writeln(st,mo,i,f,s);

Here the programmer couldn't care less about looks and formatting, *as 
long as* the output is legible and clear.


And what luxury -- not having to update the toString function each time 
you change the class' structure! (That's a relief in the early stages of 
the program, when everything is alive and fluid, before one settles on 
the optimum structure.)


Naturally, if the programmer *does* supply a toString() method, then 
that'd be used instead.




Another way to do this would be to have a template function that writeln 
(but not writefln) calls, which introspects the printee, and prints it.


Re: dmd 2.029 release

2009-04-23 Thread Andrei Alexandrescu

Steven Schveighoffer wrote:
On Thu, 23 Apr 2009 09:24:59 -0400, Andrei Alexandrescu 
seewebsiteforem...@erdani.org wrote:



Steven Schveighoffer wrote:
This has to go into object.d and be part of the runtime, where 
std.range doesn't exist.  There is nothing stopping you from calling:

 streamOut(outputrange.put);
 So I'd rather have a sink function.


It must be a sink _object_ so it can hold its own state. And it must 
support put() so it integrates with statically-bound output ranges.


interface OutRange
{
 void put(... a number of overloads ...);
}


I see now, yes I agree (I think that was don's original request 
anyways).  That interface has to go in the runtime, though.


We may not be able to do this using templates... it has to be a virtual 
function in Object to be on-par with toString.  This means struct 
interfaces are a requirement if you want to use ranges :(


We're in good shape actually. OutRange as a dynamic interface and an 
implicit interface using .put against a struct will work just as well 
with templates. (The template doesn't care whether obj.put(x) is a 
virtual call or statically-bound call.)


Andrei


Re: dmd 2.029 release

2009-04-23 Thread Andrei Alexandrescu

Georg Wrede wrote:
Second, since we have cool stuff in D, like templates, boxing, and other 
advanced things, then compared to them, it should not be a big deal to 
have automatic creation of toString for structs and objects. (This could 
even be on-demand, i.e. unless called, the toString is not created for 
an object/struct.)


Since the purpose of toString here is not Grand Style, it should suffice 
to just recursively print the struct with its possible substructs, etc.


This would relieve the programmer from the entire extra work, and it 
would also make objects look tidyer in source code.


Did you know that this:

#!/home/andrei/bin/rdmd
import std.conv, std.stdio;

struct S1
{
int a = 42;
S2 b;
}

struct S2
{
int x = 4;
float y = 5.5;
}

void main()
{
writeln(to!string(S1()));
}

prints this

S1(42, S2(4, 5.5))

?


Andrei


Re: dmd 2.029 release

2009-04-23 Thread Frits van Bommel

Andrei Alexandrescu wrote:

Frits van Bommel wrote:
IMHO It'd be pretty nice for the standard formatting systems (both the 
Tango and Phobos ones) to just call a standard Object method taking 
(Sink sink, char[] format = null) on objects.


Probably we'll need that. You forgot the in though :o).


That's just because I'm thinking in D1, where it's optional :).


Re: dmd 2.029 release

2009-04-23 Thread Georg Wrede

Andrei Alexandrescu wrote:

Georg Wrede wrote:
Second, since we have cool stuff in D, like templates, boxing, and 
other advanced things, then compared to them, it should not be a big 
deal to have automatic creation of toString for structs and objects. 
(This could even be on-demand, i.e. unless called, the toString is not 
created for an object/struct.)


Since the purpose of toString here is not Grand Style, it should 
suffice to just recursively print the struct with its possible 
substructs, etc.


This would relieve the programmer from the entire extra work, and it 
would also make objects look tidyer in source code.


Did you know that this:

#!/home/andrei/bin/rdmd
import std.conv, std.stdio;

struct S1
{
int a = 42;
S2 b;
}

struct S2
{
int x = 4;
float y = 5.5;
}

void main()
{
writeln(to!string(S1()));
}

prints this

S1(42, S2(4, 5.5))


Wow!

What if writeln would automatically call to!string for any object or struct?



Re: dmd 2.029 release

2009-04-23 Thread Andrei Alexandrescu

Frits van Bommel wrote:

Andrei Alexandrescu wrote:

Steven Schveighoffer wrote:

So I'd rather have a sink function.


It must be a sink _object_ so it can hold its own state. And it must 
support put() so it integrates with statically-bound output ranges.


interface OutRange
{
void put(... a number of overloads ...);
}


What exactly is the problem with requiring the input to the sink to be a 
string (or actually const(char)[])?


You'd be forced to use intermediate strings for everything. I guess it's 
not a huge concern.


Requiring an overload for every basic type + Object would be quite 
cumbersome if you had to do it every time you want to send the output 
somewhere else. Also, it wouldn't work for structs and unions...
(Unless you plan to implement a default OutRange that converts 
everything it gets to strings and passes it on?)


I'm thinking of only allowing a few fundamental types and then have user 
code build the rest using them.



Andrei


Re: dmd 2.029 release

2009-04-23 Thread Andrei Alexandrescu

Georg Wrede wrote:

Wow!

What if writeln would automatically call to!string for any object or 
struct?


That's the plan, I didn't get around to it. I want to do it the right 
way, i.e. with general streams, not strings.


Andrei


Re: dmd 2.029 release

2009-04-23 Thread Denis Koroskin
On Thu, 23 Apr 2009 17:35:59 +0400, Frits van Bommel 
fvbom...@remwovexcapss.nl wrote:

 Denis Koroskin wrote:
 On Thu, 23 Apr 2009 16:20:03 +0400, Don nos...@nospam.com wrote:

 struct Foo(A, B, C){
 A[10] a;
 B b;
 C c;
 void toString(Sink sink){
 foreach(x; a) sink(x);
 sink(b);
 sink(c);
 }
 }
 ... but it's not, you have to create a silly buffer to put all your   
 strings in, even if there are 200 million of them and your giant  
 string  is just going to be written to a file anyway.

  Absolutely agree, but Sink is not good, either. I have previously  
 suggested the following design (but can't find my post anymore):
  A signature of toString() should be as follows:
  char[] toString(string format = null, char[] buffer = null);
  Bonuses you get from that:
 You don't have to change your code (aside from toString() returning  
 mutable array now, but it is very easy to fix)
 It allows you to avoid allocations - just pass a temporary buffer to  
 use!

 It'll still allocate if the buffer isn't big enough.


Of course, it allows you to avoid allocations, but it doesn't necessarily 
eliminate them.

 I usually define something like void streamTo(Sink sink) in a base  
 class if I want non-allocating output. Adding a format string to the  
 parameter list should be easy, but I haven't needed it yet.
 I then usually implement toString by passing an appending Sink to that  
 method, just so Tango's formatting methods will be able to use it.



 IMHO It'd be pretty nice for the standard formatting systems (both the  
 Tango and Phobos ones) to just call a standard Object method taking  
 (Sink sink, char[] format = null) on objects.


Sink is okay, but most my usages belong to one of the two scenarios:
1) I need a string representation of an Object - how is Sink useful here? I 
just want to call obj.toString() and get the result
2) I need to print it to stdout, thus I call writeln/Stdout(obj); - Sink is of 
no use here again.

That said, I have other use-cases, too, but never once I needed a custom Sink 
property.
Besides, having a Sink object is redundant and makes things more complex in 
most cases. Compare:

class Number
{
private int _number;

// My version
char[] toString(string format, char[] buffer = null) {
return std.string.format(buffer, format, _number); // use default 
formatter, buffer is provided to avoid allocations
}

// Your version
void toString(Sink sink, string format = null) {
// what should I do here? How do I avoid allocations? I have to 
duplicate code anyway
char[16] buffer;
buffer = std.string.format(buffer, format, _number);
sink(buffer);
}
}

How is that better than using external sink? Use composition! 
toString/streamOut can be implemented on top of my toString:

char[] buffer;
sink(object.toString(format, buffer)); // I believe explicit is better here

Also, this way sink is called directly an may be inlined.

Besides, why is it called toString(), if it doesn't give me an object's string 
representation???

 Backward compatibility might be tricky though, if you want to support  
 both overriding and calling of toString(). (You can't have the default  
 toString implementation call the format function *and* have the default  
 format function implementation call toString)


My version is (almost) backwards compatible.


Re: dmd 2.029 release

2009-04-23 Thread grauzone

Andrei Alexandrescu wrote:

grauzone wrote:
Yes. The way it should be is not with sink, but with the standard 
output iterator method put().


void streamOut(T, R)(T object, R range)
{
foreach(x; a) range.put(x);
range.put(b);
range.put(c);
}


Eh. Is a sink callback too simple and easy to use or what?


?


Why make it more complicated than it has to be?
Also, I don't know ranges, but your example doesn't seem to make much sense.


Andrei


Re: dmd 2.029 release

2009-04-23 Thread Tomas Lindquist Olsen
On Thu, Apr 23, 2009 at 2:37 PM, Don nos...@nospam.com wrote:
 bearophile wrote:

 Don:

 I really don't understand the backend. It's quite cryptic. Key acronyms
 are AE, CP and VBE. Then there's Bin, Bgen, Bkill, etc.
 AE *might* be Available Expression (but what does that mean?)
 CP might be Copy Propagation info
 I've found that VBE = Very Busy Expression! (what does that mean?)

 I suggest to add comments to the DMD source code every time a small
 mystery is revealed, to rename the files once a much better name is found,
 to improve and refactor the code every time it a good thing to do it. Every
 time you put your hand in the code you can improve the code locally and
 leave it better then before (this is the Scout principle in programming).
 Then such patches/changes can be slowly folded back into DMD and with time
 the sources will improve and will become more readable. Once they can be
 understood better, further changes become faster and simpler.

 I'd love to do that, but unfortunately it's not easy to get _any_ changes
 into DMD. Only Walter has write-access to it, and AFAIK he checks every line
 and enters it manually. Like Linus was famous for doing with the Linux
 kernel.


Glad to hear I'm not the only one with that impression...


Re: dmd 2.029 release

2009-04-23 Thread Andrei Alexandrescu

grauzone wrote:

Andrei Alexandrescu wrote:

grauzone wrote:
Yes. The way it should be is not with sink, but with the standard 
output iterator method put().


void streamOut(T, R)(T object, R range)
{
foreach(x; a) range.put(x);
range.put(b);
range.put(c);
}


Eh. Is a sink callback too simple and easy to use or what?


?


Why make it more complicated than it has to be?


I am making it simpler.

Also, I don't know ranges, but your example doesn't seem to make much 
sense.


s/but/consequently/


Andrei


Re: dmd 2.029 release

2009-04-23 Thread Daniel Keep


Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Thu, 23 Apr 2009 09:24:59 -0400, Andrei Alexandrescu
 seewebsiteforem...@erdani.org wrote:

 Steven Schveighoffer wrote:
 This has to go into object.d and be part of the runtime, where
 std.range doesn't exist.  There is nothing stopping you from calling:
  streamOut(outputrange.put);
  So I'd rather have a sink function.

 It must be a sink _object_ so it can hold its own state. And it must
 support put() so it integrates with statically-bound output ranges.

 interface OutRange
 {
  void put(... a number of overloads ...);
 }

 I see now, yes I agree (I think that was don's original request
 anyways).  That interface has to go in the runtime, though.

 We may not be able to do this using templates... it has to be a
 virtual function in Object to be on-par with toString.  This means
 struct interfaces are a requirement if you want to use ranges :(
 
 We're in good shape actually. OutRange as a dynamic interface and an
 implicit interface using .put against a struct will work just as well
 with templates. (The template doesn't care whether obj.put(x) is a
 virtual call or statically-bound call.)
 
 Andrei

We may not be able to do this using templates... it has to be a virtual
function in Object to be on-par with toString.

Note that toString is a virtual method.  You are proposing replacing
toString with a template.  You cannot have virtual template methods.
Ergo, new toString would be inaccessible without the actual type, and
certainly not at runtime.

  -- Daniel


Re: dmd 2.029 release

2009-04-23 Thread Georg Wrede

Don wrote:

Georg Wrede wrote:

Don wrote:

bearophile wrote:

This post is mostly for Andrei.
I have played with D2 a bit; probably I'll need months to digest it 
and its new Phobos2. While I explore Phobos I'll probably post some 
comments/bugs around here.


After reading this:
http://blogs.msdn.com/vcblog/archive/2009/04/22/decltype-c-0x-features-in-vc10-part-3.aspx 

I have tried to write a toy implementation of it in D2 (not using 
Phobos2 yet):


import std.stdio: writeln;
import std.string: format;

struct Watts {

...


Two things to improve:
1) All structs must have a default built-in opString, a good 
representation can be:

StructName(field_value1, field_value2, field_value1, ...).
It's not a perfect textual representation, but it's WAY better than 
the current one (currently it shows just the struct name).
(Printing the module name before the struct name is bad, most times 
is just noise)


No!
rant
toString() is one of the most dreadful features in D. Trying to 
slightly improve it is a waste of time -- the whole concept needs to 
be redone.
It's horribly inflexible, tedious, and hugely inefficient. What more 
could there be to hate?


- the object being called has no context. It doesn't know what format 
is desired, for example.
- you can't emulate formatting of built-in types, NOT EVEN int! You 
can't do left-align, pad with zeros, include + sign, display in hex.


- it's got no stream concept. Every object has to create and manage 
its own buffer, and nobody knows if anyone actually needs it.


It ought to be at least as simple as:

struct Foo(A, B, C){
A[10] a;
B b;
C c;
void toString(Sink sink){
   foreach(x; a) sink(x);
   sink(b);
   sink(c);
}
}
... but it's not, you have to create a silly buffer to put all your 
strings in, even if there are 200 million of them and your giant 
string is just going to be written to a file anyway.


I'd like to see version(debug) {} put around Object.toString(). It's 
a deathtrap feature that's got no business being used other than for 
debugging.

/rant


First of all, printing stuff struct.toString() style is for two things:

 o  Debugging
 o  Small throwaway code snippets

The latter mainly being for two purposes:

 o  Testing quick concepts, trying out library functions, etc.
 o  For the newbie, when he's learning D, but not output formatting.

No Real Program uses this, because there you typically do proper 
formatting of the output anyway, and almost never print entire structs 
or objects as such. Instead, rather the information that they represent.


How about something like BigInt? Why can't you just print it out?


?? Why couldn't you?

They're not stored as strings (not Janice's anyway), but I don't 
understand the question.


BTW to everyone, 'Sink' was not a proposal. I was just saying that 
almost anything's better than the current toString().


Re: dmd 2.029 release

2009-04-23 Thread Andrei Alexandrescu

Daniel Keep wrote:


Andrei Alexandrescu wrote:

Steven Schveighoffer wrote:

On Thu, 23 Apr 2009 09:24:59 -0400, Andrei Alexandrescu
seewebsiteforem...@erdani.org wrote:


Steven Schveighoffer wrote:

This has to go into object.d and be part of the runtime, where
std.range doesn't exist.  There is nothing stopping you from calling:
 streamOut(outputrange.put);
 So I'd rather have a sink function.

It must be a sink _object_ so it can hold its own state. And it must
support put() so it integrates with statically-bound output ranges.

interface OutRange
{
 void put(... a number of overloads ...);
}

I see now, yes I agree (I think that was don's original request
anyways).  That interface has to go in the runtime, though.

We may not be able to do this using templates... it has to be a
virtual function in Object to be on-par with toString.  This means
struct interfaces are a requirement if you want to use ranges :(

We're in good shape actually. OutRange as a dynamic interface and an
implicit interface using .put against a struct will work just as well
with templates. (The template doesn't care whether obj.put(x) is a
virtual call or statically-bound call.)

Andrei


We may not be able to do this using templates... it has to be a virtual
function in Object to be on-par with toString.

Note that toString is a virtual method.  You are proposing replacing
toString with a template.  You cannot have virtual template methods.
Ergo, new toString would be inaccessible without the actual type, and
certainly not at runtime.


The toStream that I have in mind is virtual and takes an interface of 
type OutRange as outlined above.


Andrei


Re: dmd 2.029 release

2009-04-23 Thread grauzone

Andrei Alexandrescu wrote:

grauzone wrote:

Andrei Alexandrescu wrote:

grauzone wrote:
Yes. The way it should be is not with sink, but with the standard 
output iterator method put().


void streamOut(T, R)(T object, R range)
{
foreach(x; a) range.put(x);
range.put(b);
range.put(c);
}


Eh. Is a sink callback too simple and easy to use or what?


?


Why make it more complicated than it has to be?


I am making it simpler.


How is it simpler?

sink(): simple delegate with the signature void delegate(char[] data);
output range: um what...? yeah, I know it has a put() method that 
takes... something. What exactly is it supposed to take in your example? 
Is streamOut() a method of the object to be dumped? What exact types to 
T and R have? (You need the exact type if streamOut is supposed to be a 
member function, and thus has to be virtual, so that you can it use like 
the Object.toString method.)


Also, I don't know ranges, but your example doesn't seem to make much 
sense.


s/but/consequently/


Probably. Just imagine you had to explain it to someone who's new to D. 
Actually, I _am_ new to D2.0.


So, um... what is a b c and T object?



Andrei


Re: dmd 2.029 release

2009-04-23 Thread Georg Wrede

Don wrote:

Georg Wrede wrote:

Don wrote:

Georg Wrede wrote:

Don wrote:

bearophile wrote:

This post is mostly for Andrei.
I have played with D2 a bit; probably I'll need months to digest 
it and its new Phobos2. While I explore Phobos I'll probably post 
some comments/bugs around here.


After reading this:
http://blogs.msdn.com/vcblog/archive/2009/04/22/decltype-c-0x-features-in-vc10-part-3.aspx 

I have tried to write a toy implementation of it in D2 (not using 
Phobos2 yet):


import std.stdio: writeln;
import std.string: format;

struct Watts {

...


Two things to improve:
1) All structs must have a default built-in opString, a good 
representation can be:

StructName(field_value1, field_value2, field_value1, ...).
It's not a perfect textual representation, but it's WAY better 
than the current one (currently it shows just the struct name).
(Printing the module name before the struct name is bad, most 
times is just noise)


No!
rant
toString() is one of the most dreadful features in D. Trying to 
slightly improve it is a waste of time -- the whole concept needs 
to be redone.
It's horribly inflexible, tedious, and hugely inefficient. What 
more could there be to hate?


- the object being called has no context. It doesn't know what 
format is desired, for example.
- you can't emulate formatting of built-in types, NOT EVEN int! You 
can't do left-align, pad with zeros, include + sign, display in hex.


- it's got no stream concept. Every object has to create and manage 
its own buffer, and nobody knows if anyone actually needs it.


It ought to be at least as simple as:

struct Foo(A, B, C){
A[10] a;
B b;
C c;
void toString(Sink sink){
   foreach(x; a) sink(x);
   sink(b);
   sink(c);
}
}
... but it's not, you have to create a silly buffer to put all your 
strings in, even if there are 200 million of them and your giant 
string is just going to be written to a file anyway.


I'd like to see version(debug) {} put around Object.toString(). 
It's a deathtrap feature that's got no business being used other 
than for debugging.

/rant


First of all, printing stuff struct.toString() style is for two 
things:


 o  Debugging
 o  Small throwaway code snippets

The latter mainly being for two purposes:

 o  Testing quick concepts, trying out library functions, etc.
 o  For the newbie, when he's learning D, but not output formatting.

No Real Program uses this, because there you typically do proper 
formatting of the output anyway, and almost never print entire 
structs or objects as such. Instead, rather the information that 
they represent.


How about something like BigInt? Why can't you just print it out?


?? Why couldn't you?

They're not stored as strings (not Janice's anyway), but I don't 
understand the question.


You can write:

int a, b;
a=10; b=20;
writefln(%d %x, a, b);

I'd like to be able to write:

BigInt a, b;
a=10; b=20;
writefln(%d %x, a, b);

and have it behave exactly the same.



Hmm. My idea was to only have writeln (and not writefln) be automated. 
(For the small/debugging purpose.)


Andrei seems to be at this, but right now I don't know enough details to 
say anything. It seems to be an even bigger thing than what I suggested, 
and knowing he does things in a universal way, one would assume that if 
a class wants to be printed in some way, then maybe there'll be some 
provisions for it.


But, things like BigInt, that really are classes or structs that have to 
be printed in a specific way, I have a hard time figuring out how to 
printe them using write_f_ln.


One way would be to have the format specification (as in %x) be 
somehow passed to the toString of the struct/class. Then the class could 
decide for itself how to be printed in this case.



But even this is stretching it a bit, since some more complicated 
class/struct might need a more elaborate hint than just one letter. And 
by that time the whole thing starts to crumble, in usability issues, at 
least.


One thing we sholuld be wary of is overdesign. BigInt is ok, but by the 
time we try to include a class called CompleteSimulationOfAnF1RaceCar, 
we're screwed. :-)  I see no way to incorporate them into writefln or 
even plain writeln. Or at least, no *use*.





Re: dmd 2.029 release

2009-04-23 Thread bearophile
Simen Kjaeraas:
 That actually sounds like a good idea. Like you say, is has no use
 outside of debugging, but while debugging, it's quite useful.

It's also important for small script-like programs.
I am using D to write a lot of them :-)

Bye,
bearophile


Re: dmd 2.029 release

2009-04-23 Thread Don

Georg Wrede wrote:

Don wrote:

Georg Wrede wrote:

Don wrote:

Georg Wrede wrote:

Don wrote:

bearophile wrote:

This post is mostly for Andrei.
I have played with D2 a bit; probably I'll need months to digest 
it and its new Phobos2. While I explore Phobos I'll probably post 
some comments/bugs around here.


After reading this:
http://blogs.msdn.com/vcblog/archive/2009/04/22/decltype-c-0x-features-in-vc10-part-3.aspx 

I have tried to write a toy implementation of it in D2 (not using 
Phobos2 yet):


import std.stdio: writeln;
import std.string: format;

struct Watts {

...


Two things to improve:
1) All structs must have a default built-in opString, a good 
representation can be:

StructName(field_value1, field_value2, field_value1, ...).
It's not a perfect textual representation, but it's WAY better 
than the current one (currently it shows just the struct name).
(Printing the module name before the struct name is bad, most 
times is just noise)


No!
rant
toString() is one of the most dreadful features in D. Trying to 
slightly improve it is a waste of time -- the whole concept needs 
to be redone.
It's horribly inflexible, tedious, and hugely inefficient. What 
more could there be to hate?


- the object being called has no context. It doesn't know what 
format is desired, for example.
- you can't emulate formatting of built-in types, NOT EVEN int! 
You can't do left-align, pad with zeros, include + sign, display 
in hex.


- it's got no stream concept. Every object has to create and 
manage its own buffer, and nobody knows if anyone actually needs it.


It ought to be at least as simple as:

struct Foo(A, B, C){
A[10] a;
B b;
C c;
void toString(Sink sink){
   foreach(x; a) sink(x);
   sink(b);
   sink(c);
}
}
... but it's not, you have to create a silly buffer to put all 
your strings in, even if there are 200 million of them and your 
giant string is just going to be written to a file anyway.


I'd like to see version(debug) {} put around Object.toString(). 
It's a deathtrap feature that's got no business being used other 
than for debugging.

/rant


First of all, printing stuff struct.toString() style is for two 
things:


 o  Debugging
 o  Small throwaway code snippets

The latter mainly being for two purposes:

 o  Testing quick concepts, trying out library functions, etc.
 o  For the newbie, when he's learning D, but not output formatting.

No Real Program uses this, because there you typically do proper 
formatting of the output anyway, and almost never print entire 
structs or objects as such. Instead, rather the information that 
they represent.


How about something like BigInt? Why can't you just print it out?


?? Why couldn't you?

They're not stored as strings (not Janice's anyway), but I don't 
understand the question.


You can write:

int a, b;
a=10; b=20;
writefln(%d %x, a, b);

I'd like to be able to write:

BigInt a, b;
a=10; b=20;
writefln(%d %x, a, b);

and have it behave exactly the same.



Hmm. My idea was to only have writeln (and not writefln) be automated. 
(For the small/debugging purpose.)


Andrei seems to be at this, but right now I don't know enough details to 
say anything. It seems to be an even bigger thing than what I suggested, 
and knowing he does things in a universal way, one would assume that if 
a class wants to be printed in some way, then maybe there'll be some 
provisions for it.


But, things like BigInt, that really are classes or structs that have to 
be printed in a specific way, I have a hard time figuring out how to 
printe them using write_f_ln.


One way would be to have the format specification (as in %x) be 
somehow passed to the toString of the struct/class. Then the class could 
decide for itself how to be printed in this case.



But even this is stretching it a bit, since some more complicated 
class/struct might need a more elaborate hint than just one letter. And 
by that time the whole thing starts to crumble, in usability issues, at 
least.


One thing we sholuld be wary of is overdesign. BigInt is ok, but by the 
time we try to include a class called CompleteSimulationOfAnF1RaceCar, 
we're screwed. :-)  I see no way to incorporate them into writefln or 
even plain writeln. Or at least, no *use*.


I think it'd be reasonable to limit things to the options available for 
built-in types. Outside of that, custom formatting functions make a lot 
of sense. The problem is that toString() _looks_ like it emulates 
built-in formatting, but it only does '%s'. So it's really beguiling.


BTW, when passing the output to a sink, it should be possible to (say) 
format your members with '%x' format, but you can't do that by 
permanently altering sink: it should revert to its previous value once 
you've sunk your last member. (I think this C++ iostreams got this wrong).


Re: dmd 2.029 release

2009-04-23 Thread bearophile
Don:
 toString() is one of the most dreadful features in D.

It's also one of the most useful, and it's quite easy to understand and use. 
You need very little brain to use it. Features that require little/no brain are 
very important to me (but surely it's a quality that is at the bottom of the 
list of qualities for C++ programmers).

Bye,
bearophile


Re: dmd 2.029 release

2009-04-23 Thread Steven Schveighoffer
On Thu, 23 Apr 2009 10:30:15 -0400, Andrei Alexandrescu  
seewebsiteforem...@erdani.org wrote:



Daniel Keep wrote:

 Andrei Alexandrescu wrote:

Steven Schveighoffer wrote:

On Thu, 23 Apr 2009 09:24:59 -0400, Andrei Alexandrescu
seewebsiteforem...@erdani.org wrote:


Steven Schveighoffer wrote:

This has to go into object.d and be part of the runtime, where
std.range doesn't exist.  There is nothing stopping you from  
calling:

 streamOut(outputrange.put);
 So I'd rather have a sink function.

It must be a sink _object_ so it can hold its own state. And it must
support put() so it integrates with statically-bound output ranges.

interface OutRange
{
 void put(... a number of overloads ...);
}

I see now, yes I agree (I think that was don's original request
anyways).  That interface has to go in the runtime, though.

We may not be able to do this using templates... it has to be a
virtual function in Object to be on-par with toString.  This means
struct interfaces are a requirement if you want to use ranges :(

We're in good shape actually. OutRange as a dynamic interface and an
implicit interface using .put against a struct will work just as well
with templates. (The template doesn't care whether obj.put(x) is a
virtual call or statically-bound call.)

Andrei
 We may not be able to do this using templates... it has to be a  
virtual

function in Object to be on-par with toString.
 Note that toString is a virtual method.  You are proposing replacing
toString with a template.  You cannot have virtual template methods.
Ergo, new toString would be inaccessible without the actual type, and
certainly not at runtime.


The toStream that I have in mind is virtual and takes an interface of  
type OutRange as outlined above.


OK, that's fine, I was working off your original proposal:

void streamOut(R)(R range)
{
 foreach(x; a) range.put(x);
 range.put(b);
 range.put(c);
}

Of course, this then eliminates structs from being OutRange's without  
having struct interfaces.  As most ranges are structs (and rightfully so,  
who wants to call 3 virtual functions every loop!), they would have to be  
wrapped under the current compiler. Or am I missing something else?


-Steve


Re: dmd 2.029 release

2009-04-23 Thread Georg Wrede

Don wrote:

Georg Wrede wrote:
One thing we sholuld be wary of is overdesign. BigInt is ok, but by 
the time we try to include a class called 
CompleteSimulationOfAnF1RaceCar, we're screwed. :-)  I see no way to 
incorporate them into writefln or even plain writeln. Or at least, no 
*use*.


I think it'd be reasonable to limit things to the options available for 
built-in types. Outside of that, custom formatting functions make a lot 
of sense. The problem is that toString() _looks_ like it emulates 
built-in formatting, but it only does '%s'. So it's really beguiling.


Heh, one thought is, suppose we could have arbitrary format 
specifications in writef. Say, if we wrote %lkjasdf; this string would 
be passed to toString. (It would of course be up to the class to 
error-check the string, writefln obviously cant (or shouldn't) do it.)


So, things are doable. But I'm really not looking forward to that kind 
of sports. Any elaborate printing or formatting should be handled 
outside writefln co.


BTW, when passing the output to a sink, it should be possible to (say) 
format your members with '%x' format, but you can't do that by 
permanently altering sink: it should revert to its previous value once 
you've sunk your last member. (I think this C++ iostreams got this wrong).


I guess they, too, thought of making it easier in the wrong place. 
Just because you can, doesn't mean you have to.


(OT: an excellent example of this It's Done Because We Noticed We Could 
stuff is in Firefox. When a picture is a link to another page, and you 
want to drag that to the tab area, the entire picture is dragged with 
the mouse. Now, how the hell am I supposed to hit the small tab area 
when the large picture covers half of my Firefox??


So now I have to learn to remember to grab bigger pictures near some 
edge. And I really can't see *any* valid benefit for having to drag the 
picture. I'd rather have it the old way, where the mouse pointer simply 
changes shape, so you know you're dragging. Damn, damn...)


Re: dmd 2.029 release

2009-04-23 Thread Charles Hixson

Georg Wrede wrote:

Don wrote:

Georg Wrede wrote:

Don wrote:

Georg Wrede wrote:

Walter Bright wrote:

Lutger wrote:

what the hell...this code can't be human.


I was replaced by Colossus years ago.


Michael A. Jackson wouldn't approve 1175 gotos in 113 files.


It'd be really funny to pass it through one of those code quality 
metrics, one of the ones with a ridiculously heavy penalty for using 
goto. I think it'd tell you that DMD source is almost the 
lowest-quality code on the planet. g


Yeah. But now I'm getting a bad conscience, this is beginning to look 
like Walter-bashing... :-)


I think those code quality metrics are ridiculous. The prejudice 
against 'goto' is really just brainwashing and totally without basis.


Well, at the time, they had no choice. Unstructured code was the norm, 
and people who tangled themselves in spaghetti never noticed it's 
because of goto usage. Instead they just preceived programming as hard.


The language on my first computer was old fashioned BASIC, with line 
numbers and no named subroutines or structural elements. I felt that the 
effort needed to program was exponential to the number of lines. In 
hindsight, that must have been entirely because I'd had no higher 
education in programming, no notion of structuring the code (in any 
particular way), etc. But the absolutely worst thing was that one 
couldn't pass parameters to subroutines. (gosub lineNumber) And all 
variables were global.


In those days most programming was done in COBOL, by (essentially) 
non-programmers. (The idea of COBOL was, after all, to be usable by 
business people, not MSc programmers.) Jackson had to change not only 
the methodology, but before that, the concept and the motivation for 
using structured programming. That was the hard part, and it needed some 
serious evangelising and brainwashing, to overcome the inertia.


Unfortunately, that meant murdering, dismembering, and pulverizing any 
least hint of even thinking about using goto. And as with any paradigm 
shift, the disciples took it to religious extremes.



Here's a recent link from Andrew Koenig, who really should know better.

http://dobbscodetalk.com/index.php?option=com_myblogshow=What-Dijkstra-said-was-harmful-about-goto-statements.htmlItemid=29 

Can you see his fundamental mistake? He talks about the program 
(just as Dijkstra said), but it's just not relevant for 
C/C++/D/Pascal/...
or any other structured programming language. Wherever he says 
program you should substitute function. And then the force of the 
argument totally disappears.


Yes.

The problem with goto in an unstructured language is that when you see 
a label, you don't know where it came from. It could be anywhere in 
the entire program (maybe a million lines of code!) And that's a 
complete disaster. But in a structured language, you know it's from 
somewhere in the function.
And this is no different from any other control structure. You ALWAYS 
have to look at the whole scope you're in.


void foo(){
 int n;
bool b = true;
  while (b) {
if (n==4) {   /* when do we get here? You have to read the whole 
function to find out. Where does n get modified? */ }

:
:
:
  }
}

Heck, even in inline ASM in D, you can't write the kind of spaghetti 
code Dijkstra was complaining about. You always have local scope.


OTOH, getting the algorithm may become tedious even in small snippets. 
For example, here's Algorithm M, from /Fundamental Algorithms/, Knuth 
1969, page 95:


M1: int j=n; int k=n; int m=X[n];
M2: if(k==0) goto M6;
M3: if(X[k] = m) goto M5;
M4: j=k; m=X[k];
M5: k--; goto M2;
M6: ;

That's three gotos for six lines. How long did it take to fully figure 
out what it's doing? Way longer than if it were written in structured D, 
anyway.


Yet, I personally have been so affected by anti-goto brainwashing that 
I've never used goto in C, C++, or D. But I gradually realised that it 
was just brainwashing. I've never experienced any problem with goto in 
ASM.


Same here. Last time I used it was in Pascal, and boy, did I have a bad 
conscience. It felt like I was doing something Mom has forbidden.


Actually, looking through the DMD source it becomes obvious that 
goto is really not a problem at all. The lack of comments is much 
more of a problem. (Especially with files with names like e2ir.c. 
What the heck is fltables.c, cdxxx.c, elxxx.c ?). Even so, 
it's mostly not that difficult to understand.


I guess Walter has to keep alternating between ASM, C and D. And a 
lot of ASM coding is nothing more than a bunch of MOV and JMP stuff. 
And file naming conventions here look like what one typically finds 
in development code (before some pre-publishing guy has tidyed it up 
with a lot of global searchreplaces). And, after all, the C files 
never were meant to be public anyway.


Actually, the one interesting question might be, would rewriting this 
code in a structured fashion (I mean, removing the gotos) make it 

Re: dmd 2.029 release

2009-04-23 Thread Joel C. Salomon
Georg Wrede wrote:
 Don wrote:
 Georg Wrede wrote:
 One thing we sholuld be wary of is overdesign. BigInt is ok, but by
 the time we try to include a class called
 CompleteSimulationOfAnF1RaceCar, we're screwed. :-)  I see no way to
 incorporate them into writefln or even plain writeln. Or at least, no
 *use*.

 I think it'd be reasonable to limit things to the options available
 for built-in types. Outside of that, custom formatting functions make
 a lot of sense. The problem is that toString() _looks_ like it
 emulates built-in formatting, but it only does '%s'. So it's really
 beguiling.
 
 Heh, one thought is, suppose we could have arbitrary format
 specifications in writef. Say, if we wrote %lkjasdf; this string would
 be passed to toString. (It would of course be up to the class to
 error-check the string, writefln obviously cant (or shouldn't) do it.)
 
 So, things are doable. But I'm really not looking forward to that kind
 of sports. Any elaborate printing or formatting should be handled
 outside writefln co.

Take a look at the formatting library for Plan 9.  It’s very much like
printf  co., except it exposes enough of its internals to allow for new
formats to be added in.  See the documentation (for the *nix-ported
version) at http://swtch.com/plan9port/man/man3/print.html and
http://swtch.com/plan9port/man/man3/fmtinstall.html. For example:

typedef
struct {
double  r, i;
} Complex;
#pragma  varargck  type X  Complex// compiler checks type-safety

int
Xfmt(Fmt *f)
{
Complex c;
c = va_arg(f−args, Complex);
return fmtprint(f, (%g,%g), c.r, c.i); // can use flags here
}

main(...)
{
Complex x = (Complex){ 1.5, −2.3 };
fmtinstall('X', Xfmt);
print(x = %X\n, x);
}

With D’s type-safe variadic functions, this model can be made really
powerful.

—Joel Salomon


Re: dmd 2.029 release

2009-04-23 Thread Denis Koroskin
On Thu, 23 Apr 2009 18:28:53 +0400, Andrei Alexandrescu 
seewebsiteforem...@erdani.org wrote:

 Denis Koroskin wrote:
 Sink is okay, but most my usages belong to one of the two scenarios: 1)  
 I need a string representation of an Object - how is Sink useful
 here? I just want to call obj.toString() and get the result 2) I need
 to print it to stdout, thus I call writeln/Stdout(obj); - Sink is of
 no use here again.

 I hear you, but there are quite a few more considerations that apply.

 For one, making string the common format of all objects is pretty  
 hamfisted. We need to integrate things like binary streams too. Second,  
 using string append and composing with it is bound to be inefficient,  
 and for multiple reasons. You can't just say that a reasonable way to  
 print a matrix is to call toString against it and print the resulting  
 string. With the temporary buffer passed-in or not, that's just a  
 terrible design.

 But you need not fear. Converting to string will remain easy and simple,  
   it will only be a particular case of streaming objects out.


 Andrei

I'm fine with that, especially if entire Phobos will be consistent with it 
(e.g. std.string.format accepts sink object etc). There a few problems with it, 
though.

I like the toStream name but I believe it is a bit misleading - if toString() 
returns a string, then toStream() should return stream, too, not accept it.

But what about custom formatting? Previously I stated that current scheme 
doesn't allow them, but it turned out to be possible.

For example, you introduced custom array formatting:

%(s; ) - array.toString(s; , ...);

Similar approach may be used for other user-defined formatting options:

%s - obj.toString(s);
%d - obj.toString(d);
...
%(any_set_of_characters) - obj.toString(any_set_of_characters); // including 
inner %() etc


Example: given an array of arrays of ints, print them as follows: [ [1, 2, 3, 
4, ]; [5, 6, 7, 8, ]; [9, a, b, c, ]; ]

int[][] arrayOfArraysOfInts;
writefln([ %([%(x, )]; )], arrayOfArraysOfInts);

Just to make it more clear:

[ %([%(x, )]; )] - [  ~ arrayOfArraysOfInts.toString([%(x, )]; ) ~ ]


Re: dmd 2.029 release

2009-04-23 Thread Denis Koroskin
On Thu, 23 Apr 2009 19:34:38 +0400, Don nos...@nospam.com wrote:

 Georg Wrede wrote:
 Don wrote:
 Georg Wrede wrote:
 Don wrote:
 Georg Wrede wrote:
 Don wrote:
 bearophile wrote:
 This post is mostly for Andrei.
 I have played with D2 a bit; probably I'll need months to digest  
 it and its new Phobos2. While I explore Phobos I'll probably post  
 some comments/bugs around here.

 After reading this:
 http://blogs.msdn.com/vcblog/archive/2009/04/22/decltype-c-0x-features-in-vc10-part-3.aspx
   
 I have tried to write a toy implementation of it in D2 (not using  
 Phobos2 yet):

 import std.stdio: writeln;
 import std.string: format;

 struct Watts {
 ...

 Two things to improve:
 1) All structs must have a default built-in opString, a good  
 representation can be:
 StructName(field_value1, field_value2, field_value1, ...).
 It's not a perfect textual representation, but it's WAY better  
 than the current one (currently it shows just the struct name).
 (Printing the module name before the struct name is bad, most  
 times is just noise)

 No!
 rant
 toString() is one of the most dreadful features in D. Trying to  
 slightly improve it is a waste of time -- the whole concept needs  
 to be redone.
 It's horribly inflexible, tedious, and hugely inefficient. What  
 more could there be to hate?

 - the object being called has no context. It doesn't know what  
 format is desired, for example.
 - you can't emulate formatting of built-in types, NOT EVEN int!  
 You can't do left-align, pad with zeros, include + sign, display  
 in hex.

 - it's got no stream concept. Every object has to create and  
 manage its own buffer, and nobody knows if anyone actually needs  
 it.

 It ought to be at least as simple as:

 struct Foo(A, B, C){
 A[10] a;
 B b;
 C c;
 void toString(Sink sink){
foreach(x; a) sink(x);
sink(b);
sink(c);
 }
 }
 ... but it's not, you have to create a silly buffer to put all  
 your strings in, even if there are 200 million of them and your  
 giant string is just going to be written to a file anyway.

 I'd like to see version(debug) {} put around Object.toString().  
 It's a deathtrap feature that's got no business being used other  
 than for debugging.
 /rant

 First of all, printing stuff struct.toString() style is for two  
 things:

  o  Debugging
  o  Small throwaway code snippets

 The latter mainly being for two purposes:

  o  Testing quick concepts, trying out library functions, etc.
  o  For the newbie, when he's learning D, but not output formatting.

 No Real Program uses this, because there you typically do proper  
 formatting of the output anyway, and almost never print entire  
 structs or objects as such. Instead, rather the information that  
 they represent.

 How about something like BigInt? Why can't you just print it out?

 ?? Why couldn't you?

 They're not stored as strings (not Janice's anyway), but I don't  
 understand the question.

 You can write:

 int a, b;
 a=10; b=20;
 writefln(%d %x, a, b);

 I'd like to be able to write:

 BigInt a, b;
 a=10; b=20;
 writefln(%d %x, a, b);

 and have it behave exactly the same.
   Hmm. My idea was to only have writeln (and not writefln) be  
 automated. (For the small/debugging purpose.)
  Andrei seems to be at this, but right now I don't know enough details  
 to say anything. It seems to be an even bigger thing than what I  
 suggested, and knowing he does things in a universal way, one would  
 assume that if a class wants to be printed in some way, then maybe  
 there'll be some provisions for it.
  But, things like BigInt, that really are classes or structs that have  
 to be printed in a specific way, I have a hard time figuring out how to  
 printe them using write_f_ln.
  One way would be to have the format specification (as in %x) be  
 somehow passed to the toString of the struct/class. Then the class  
 could decide for itself how to be printed in this case.
   But even this is stretching it a bit, since some more complicated  
 class/struct might need a more elaborate hint than just one letter. And  
 by that time the whole thing starts to crumble, in usability issues, at  
 least.
  One thing we sholuld be wary of is overdesign. BigInt is ok, but by  
 the time we try to include a class called  
 CompleteSimulationOfAnF1RaceCar, we're screwed. :-)  I see no way to  
 incorporate them into writefln or even plain writeln. Or at least, no  
 *use*.

 I think it'd be reasonable to limit things to the options available for  
 built-in types. Outside of that, custom formatting functions make a lot  
 of sense. The problem is that toString() _looks_ like it emulates  
 built-in formatting, but it only does '%s'. So it's really beguiling.

 BTW, when passing the output to a sink, it should be possible to (say)  
 format your members with '%x' format, but you can't do that by  
 permanently altering sink: it should revert to its previous value once  
 you've sunk your last member. (I think this C++ iostreams 

Re: dmd 2.029 release [OT]

2009-04-23 Thread Steven Schveighoffer

On Thu, 23 Apr 2009 12:09:20 -0400, Georg Wrede georg.wr...@iki.fi wrote:

(OT: an excellent example of this It's Done Because We Noticed We Could  
stuff is in Firefox. When a picture is a link to another page, and you  
want to drag that to the tab area, the entire picture is dragged with  
the mouse. Now, how the hell am I supposed to hit the small tab area  
when the large picture covers half of my Firefox??


So now I have to learn to remember to grab bigger pictures near some  
edge. And I really can't see *any* valid benefit for having to drag the  
picture. I'd rather have it the old way, where the mouse pointer simply  
changes shape, so you know you're dragging. Damn, damn...)


On my system, dragging the image drags a translucent copy of the image, so  
I can still see where my mouse pointer is aimed.  Maybe you don't have  
enough colors enabled on your screen?


-Steve


Re: dmd 2.029 release

2009-04-23 Thread Andrei Alexandrescu

Steven Schveighoffer wrote:

  As most ranges are structs (and rightfully
so, who wants to call 3 virtual functions every loop!), they would have 
to be wrapped under the current compiler. Or am I missing something else?


Yes, some wrapping would have to be done. Hopefully it will simple 
enough to keep things appealingly easy:


obj.toString(dynaRange(range));


Andrei


Re: dmd 2.029 release [OT]

2009-04-23 Thread Jarrett Billingsley
On Thu, Apr 23, 2009 at 2:32 PM, Georg Wrede georg.wr...@iki.fi wrote:

 (OT: an excellent example of this It's Done Because We Noticed We Could
 stuff is in Firefox. When a picture is a link to another page, and you want
 to drag that to the tab area, the entire picture is dragged with the mouse.
 Now, how the hell am I supposed to hit the small tab area when the large
 picture covers half of my Firefox??

 Sure it looks good, and the computer owner can brag to the guy in the next
 cubicle, etc. But there should be some obvious or useful *purpose* for
 dragging entire pictures where a mouse pointer would be clearer, cleaner,
 easier for the user, and use less computer cycles.

 I mean, who's such a nutcase that he forgets halfway in the dragging, what
 it is he's dragging?

Middle-click.


Re: dmd 2.029 release [OT]

2009-04-23 Thread Steven Schveighoffer

On Thu, 23 Apr 2009 14:32:13 -0400, Georg Wrede georg.wr...@iki.fi wrote:


Steven Schveighoffer wrote:
On Thu, 23 Apr 2009 12:09:20 -0400, Georg Wrede georg.wr...@iki.fi  
wrote:


(OT: an excellent example of this It's Done Because We Noticed We  
Could stuff is in Firefox. When a picture is a link to another page,  
and you want to drag that to the tab area, the entire picture is  
dragged with the mouse. Now, how the hell am I supposed to hit the  
small tab area when the large picture covers half of my Firefox??


So now I have to learn to remember to grab bigger pictures near some  
edge. And I really can't see *any* valid benefit for having to drag  
the picture. I'd rather have it the old way, where the mouse pointer  
simply changes shape, so you know you're dragging. Damn, damn...)
 On my system, dragging the image drags a translucent copy of the  
image, so I can still see where my mouse pointer is aimed.  Maybe you  
don't have enough colors enabled on your screen?


Sure it looks good, and the computer owner can brag to the guy in the  
next cubicle, etc. But there should be some obvious or useful *purpose*  
for dragging entire pictures where a mouse pointer would be clearer,  
cleaner, easier for the user, and use less computer cycles.


I mean, who's such a nutcase that he forgets halfway in the dragging,  
what it is he's dragging?


One thing that does annoy me is if you are doing this over a slow RDP  
link, the eye candy isn't worth it.


I was never a huge fan of application themes.  I don't mind a theme for  
the whole system (as long as it's simple), but I don't want iTunes to look  
different just because it can.  I think it has been discussed before that  
most video editors have the slickest GUI, with real-looking knobs and  
led's, but the video editing part of it is buggy as hell.


-Steve



Re: dmd 2.029 release

2009-04-23 Thread Christopher Wright

Andrei Alexandrescu wrote:
Yes. The way it should be is not with sink, but with the standard output 
iterator method put().


void streamOut(T, R)(T object, R range)
{
foreach(x; a) range.put(x);
range.put(b);
range.put(c);
}


// object.d
class Object
{
void streamOut(R)(R range);
}

No?


Re: dmd 2.029 release

2009-04-23 Thread Jarrett Billingsley
On Thu, Apr 23, 2009 at 6:01 PM, Christopher Wright dhase...@gmail.com wrote:
 Andrei Alexandrescu wrote:

 Yes. The way it should be is not with sink, but with the standard output
 iterator method put().

 void streamOut(T, R)(T object, R range)
 {
    foreach(x; a) range.put(x);
    range.put(b);
    range.put(c);
 }

 // object.d
 class Object
 {
        void streamOut(R)(R range);
 }

 No?

No.  Templated methods are not virtual.


Re: dmd 2.029 release [OT]

2009-04-23 Thread Nick Sabalausky
Steven Schveighoffer schvei...@yahoo.com wrote in message 
news:op.usux6bskeav...@steves.networkengines.com...

 I was never a huge fan of application themes.  I don't mind a theme for 
 the whole system (as long as it's simple), but I don't want iTunes to look 
 different just because it can.


That's one of my biggest pet peeves about modern software. I can't really do 
the subject justice without delving into a giant pile of expletives. But 
worse still is when they decide to go and piss all over not just standard 
looks, but also standard behaviors. Like how the Win build of iTunes will 
still ignore/eat any click that brings it to the foreground. If I wanted 
that behavior I'd be running a Mac.

The absolute worst of all though is when an app (*cough* skype *cough*) 
decides that close and the 'close' button should mean don't close 
anything at all, but minimize to tray instead. That should be a firing 
squad offense ;) Joking aside though, any of these are guaranteed ways to 
make me lose any and all respect for a piece of software and its developers, 
especially if they're arrogant enough to provide no way to turn such things 
off.




Re: dmd 2.029 release [OT]

2009-04-23 Thread Jesse Phillips
On Thu, 23 Apr 2009 21:40:36 -0400, Christopher Wright wrote:

 Nick Sabalausky wrote:
 Steven Schveighoffer schvei...@yahoo.com wrote in message
 news:op.usux6bskeav...@steves.networkengines.com...
 I was never a huge fan of application themes.  I don't mind a theme
 for the whole system (as long as it's simple), but I don't want iTunes
 to look different just because it can.


 That's one of my biggest pet peeves about modern software. I can't
 really do the subject justice without delving into a giant pile of
 expletives. But worse still is when they decide to go and piss all over
 not just standard looks, but also standard behaviors. Like how the Win
 build of iTunes will still ignore/eat any click that brings it to the
 foreground. If I wanted that behavior I'd be running a Mac.
 
 The absolute worst of all though is when an app (*cough* skype *cough*)
 decides that close and the 'close' button should mean don't close
 anything at all, but minimize to tray instead. That should be a firing
 squad offense ;)
 
 I'd be killing my IM client constantly if not for that feature. I pretty
 much expect it of any application that's meant to be running for a long
 time and only rarely needing user interaction (such as a bittorrent
 client).

I think he was referring to not having an exit. That is File-Exit is 
also minimize to tray which is not the case in most such apps.


Re: dmd 2.029 release [OT]

2009-04-23 Thread BCS

Hello Christopher,


Nick Sabalausky wrote:
 

The absolute worst of all though is when an app (*cough* skype
*cough*) decides that close and the 'close' button should mean
don't close anything at all, but minimize to tray instead. That
should be a firing squad offense ;)


I'd be killing my IM client constantly if not for that feature. I
pretty much expect it of any application that's meant to be running
for a long time and only rarely needing user interaction (such as a
bittorrent client).



yah, for some programs you rarely want to close the program but often want 
to close the UI.





Re: dmd 2.029 release [OT]

2009-04-23 Thread Daniel Keep


BCS wrote:
 Hello Christopher,
 
 Nick Sabalausky wrote:
  
 The absolute worst of all though is when an app (*cough* skype
 *cough*) decides that close and the 'close' button should mean
 don't close anything at all, but minimize to tray instead. That
 should be a firing squad offense ;)

 I'd be killing my IM client constantly if not for that feature. I
 pretty much expect it of any application that's meant to be running
 for a long time and only rarely needing user interaction (such as a
 bittorrent client).

 
 yah, for some programs you rarely want to close the program but often
 want to close the UI.

This is one place where I think Mac OS X gets it right.  It's a massive
pain to close the last document open in OpenOffice.org before opening a
new one, only to realise that now you have to sit through the loading
screen again.

  -- Daniel


Re: dmd 2.029 release

2009-04-22 Thread Lutger
Russell Lewis wrote:

...
 Case in point: I have been bitten by this perhaps half a dozen times 
 *already* porting older code.  This code used to work fine:
 
   writefln(The value is: %d, myVar, .  Do something!);
 
...

I bet a lot of to-be-ported D code will have this bug, I know my code will.  
When you want to print a format string this way - last argument(s) simply 
appended, it saves you two characters typing. When something saves any 
characters typing and produces the same result, programmers will do that. 




Re: dmd 2.029 release

2009-04-22 Thread Don

Georg Wrede wrote:

Walter Bright wrote:

Lutger wrote:

what the hell...this code can't be human.


I was replaced by Colossus years ago.


Michael A. Jackson wouldn't approve 1175 gotos in 113 files.


It'd be really funny to pass it through one of those code quality 
metrics, one of the ones with a ridiculously heavy penalty for using 
goto. I think it'd tell you that DMD source is almost the lowest-quality 
code on the planet. g


Actually, looking through the DMD source it becomes obvious that goto is 
really not a problem at all. The lack of comments is much more of a 
problem. (Especially with files with names like e2ir.c. What the heck 
is fltables.c, cdxxx.c, elxxx.c ?). Even so, it's mostly not that 
difficult to understand.


Re: dmd 2.029 release

2009-04-22 Thread Steven Schveighoffer

On Wed, 22 Apr 2009 03:12:04 -0400, Don nos...@nospam.com wrote:


Daniel Keep wrote:

 Michel Fortin wrote:

On 2009-04-21 11:18:39 -0400, Don nos...@nospam.com said:

Yes. Actually, marking a nested function as pure doesn't make much  
sense.

It's entirely equivalent to moving it outside the function; a nested
pure function shouldn't be able to access any members of the enclosing
function, otherwise it's not pure. But DMD doesn't enforce that, and
so it creates inefficient and possibly buggy code.

What about immutable local variables? A pure function can access
immutable globals, so it should be able to access immutable locals too.


 If you treat the nested function's context pointer as a pointer to a
struct matching the stack layout, then you can have pure nested
functions -- they have exactly the same semantics as a pure struct
member function.
   -- Daniel


True, but that would mean that it'd be pretty useless. It's almost  
exactly the same as not marking it pure.

pure foo(int x)
{
   int y;
   pure int bar(int z) { return z*z; }

   int a= bar(2);
   y++;
   int b = bar(2); // has to recalculate bar(2), because y has changed.
}

---
The basic issue is that the situations where marking a nested function  
as 'pure' is a good idea, is extremely limited.
Compared to making it an external pure private function, with any  
desired immutable members passed as parameters, it has these advantages  
and disadvantages.

+ inaccessable to other functions in the same module.
+ can access immutable members in the outer function, without passing  
them as parameters.

- slower, since it needs a context pointer as well as a frame pointer.

I think those benefits are pathetic.


What about treating nested functions of pure functions like a logical  
grouping of statements within the function?  That is, when you call a  
nested function inside a pure function, the call can't be optimized, but  
any calls the nested function makes (to a global pure function) can be  
optimized, and the nested function still provides the same guarantees  
(cannot access any globals, must only call other pure functions), however  
it can access and modify locals within the outer function.


I use nested functions a lot not as mini functions within a function but  
as simple ways to avoid duplicating code everywhere in my function.


You probably couldn't allow taking a delegate of such a function either.

-Steve


Re: dmd 2.029 release

2009-04-22 Thread Don

Steven Schveighoffer wrote:

On Wed, 22 Apr 2009 03:12:04 -0400, Don nos...@nospam.com wrote:


Daniel Keep wrote:

 Michel Fortin wrote:

On 2009-04-21 11:18:39 -0400, Don nos...@nospam.com said:

Yes. Actually, marking a nested function as pure doesn't make much 
sense.

It's entirely equivalent to moving it outside the function; a nested
pure function shouldn't be able to access any members of the enclosing
function, otherwise it's not pure. But DMD doesn't enforce that, and
so it creates inefficient and possibly buggy code.

What about immutable local variables? A pure function can access
immutable globals, so it should be able to access immutable locals too.


 If you treat the nested function's context pointer as a pointer to a
struct matching the stack layout, then you can have pure nested
functions -- they have exactly the same semantics as a pure struct
member function.
   -- Daniel


True, but that would mean that it'd be pretty useless. It's almost 
exactly the same as not marking it pure.

pure foo(int x)
{
   int y;
   pure int bar(int z) { return z*z; }

   int a= bar(2);
   y++;
   int b = bar(2); // has to recalculate bar(2), because y has changed.
}

---
The basic issue is that the situations where marking a nested function 
as 'pure' is a good idea, is extremely limited.
Compared to making it an external pure private function, with any 
desired immutable members passed as parameters, it has these 
advantages and disadvantages.

+ inaccessable to other functions in the same module.
+ can access immutable members in the outer function, without passing 
them as parameters.

- slower, since it needs a context pointer as well as a frame pointer.

I think those benefits are pathetic.


What about treating nested functions of pure functions like a logical 
grouping of statements within the function?  That is, when you call a 
nested function inside a pure function, the call can't be optimized, but 
any calls the nested function makes (to a global pure function) can be 
optimized, and the nested function still provides the same guarantees 
(cannot access any globals, must only call other pure functions), 
however it can access and modify locals within the outer function.


That's exactly what my recent change (2804) did.

I use nested functions a lot not as mini functions within a function but 
as simple ways to avoid duplicating code everywhere in my function.


You probably couldn't allow taking a delegate of such a function either.


I've just submitted a patch (2695) which makes usage of function 
pointers and delegates safe within pure functions. Basically, you can 
take the delegate of a nested function, but you can't call it.
You could return it, but I believe that's OK, because it should become a 
closure.


I'm on a quest to make 'pure' usable in D g.


Re: dmd 2.029 release

2009-04-22 Thread Leandro Lucarella
Don, el 22 de abril a las 09:24 me escribiste:
 Georg Wrede wrote:
 Walter Bright wrote:
 Lutger wrote:
 what the hell...this code can't be human.
 
 I was replaced by Colossus years ago.
 Michael A. Jackson wouldn't approve 1175 gotos in 113 files.
 
 It'd be really funny to pass it through one of those code quality
 metrics, one of the ones with a ridiculously heavy penalty for using
 goto. I think it'd tell you that DMD source is almost the lowest-quality
 code on the planet. g

Try the Linux kernel.

The difference is:
a) Well, Linux is a kernel =)
b) Gotos are not used gratuitously in the kernel code, they are used to
   handle error, which is almost the only right way to do it in C. For
   what I saw for the DMD code that's not true.

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/

GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)

1950 we were 3 billion people on the earth,
today we are 6 billion people


Re: dmd 2.029 release

2009-04-22 Thread Andrei Alexandrescu

Steven Schveighoffer wrote:
On Wed, 22 Apr 2009 13:49:18 -0400, Andrei Alexandrescu 
seewebsiteforem...@erdani.org wrote:



tama wrote:

On Mon, 20 Apr 2009 16:09:09 +0900, Walter Bright
newshou...@digitalmars.com wrote:



This is a major revision to Phobos, including Andrei's revolutionary
new range support.

http://www.digitalmars.com/d/2.0/changelog.html
http://ftp.digitalmars.com/dmd.2.029.zip


Range is so cool!

Though...
I tried following code:

void main()
{
writeln(Case1);
{
Mt19937 gen = Mt19937(0);
writeln(gen.front);
gen.popFront;
writeln(gen.front);
}
writeln(---);
{
Mt19937 gen = Mt19937(0);
advance(gen, 1);  // skip 1 element
writeln(gen.front);
gen.popFront;
writeln(gen.front);
}
writeln(\nCase2);
{
Mt19937 gen;
writeln(gen.front);
gen.popFront;
writeln(gen.front);
}
writeln(---);
{
Mt19937 gen;
advance(gen, 1);  // skip 1 element
writeln(gen.front);
gen.popFront;
writeln(gen.front);
}
}

Result:

Case1
2357136044 (1)
2546248239 (2)
---
2546248239 (2)
3071714933 (3)

Case2
581869302  (1)
3890346734 (2)
---
581869302  (1)?
3890346734 (2)?

I think 'Case1' is correct, but 'Case2' is wrong.
Mt19937's bug?



If you initialize the Mersenne twister with no seed it will start with
seed 5489u.


I think his point is in the second part of Case2, he skipped one 
element, but it appears that it didn't skip anything.


Oh ok, thanks tama and Steve. I know where the problem is (on the 
Mersenne twister, if you call popFront without ever calling head there's 
a bug). Could you submit a bug? I'm on battery and on short time, and 
Walter is bugging me :o).



Andrei


Re: dmd 2.029 release

2009-04-22 Thread bearophile
Don:
 Actually it's not so difficult. I've created a patch for bug 2807 -- 
 it's only 5 lines long! It gives an error message if a nested pure 
 function accesses a mutable variable from an outer scope.

Thank you very much Don, your work helps a lot.

Every time I try a tiny program I find something I don't understand:

import std.stdio: writeln;
import std.math: sqrt;
import std.conv: to;

void main(string[] args) {
double x = args.length == 2 ? to!(double)(args[1]) : 4.0;
writeln(sqrt(x) + sqrt(x));
}

I have also tried with std.math.sin with similar results:

L0: enter   8,0
mov EAX,8[EBP]
cmp EAX,2
jne L30
cmp EAX,1
ja  L1B
mov EAX,6
callnear ptr _D6test7__arrayZ
L1B:mov EDX,0Ch[EBP]
mov EAX,8[EBP]
mov EAX,8[EDX]
mov EDX,0Ch[EDX]
pushEDX
pushEAX
callnear ptr _D3std4conv13__T2toTdTAyaZ2toFAyaZd
jmp short   L36
L30:fld qword ptr FLAT:_DATA[00h]
L36:fstpqword ptr -8[EBP]
fld qword ptr -8[EBP]
fsin
fld qword ptr -8[EBP]
fsin
faddp   ST(1),ST
sub ESP,0Ch
fstptbyte ptr [ESP]
callnear ptr _D3std5stdio14__T7writelnTeZ7writelnFeZv
xor EAX,EAX
leave
ret

Isn't sin(x)+sin(x) pure? Even if the compiler doesn't want to replace x+x with 
x*2 because x is a floating point, it can do:

y = sin(x)
y+y

And that gives the same result even with FPs.

Note: with SSE2 it's even possible to perform two sqrt(double) at the same 
time, so a compiler can implement sin(x)+sin(y) with a single instruction 
(SQRTSD) (plus eventually some register loading/unloading).

Bye,
bearophile


Re: dmd 2.029 release

2009-04-22 Thread Masahiro Nakagawa

Changed sender name from screen name to real name.

On Thu, 23 Apr 2009 02:55:37 +0900, Steven Schveighoffer  
schvei...@yahoo.com wrote:


On Wed, 22 Apr 2009 13:49:18 -0400, Andrei Alexandrescu  
seewebsiteforem...@erdani.org wrote:



tama wrote:

On Mon, 20 Apr 2009 16:09:09 +0900, Walter Bright
newshou...@digitalmars.com wrote:



This is a major revision to Phobos, including Andrei's revolutionary
new range support.

http://www.digitalmars.com/d/2.0/changelog.html
http://ftp.digitalmars.com/dmd.2.029.zip


Range is so cool!

Though...
I tried following code:

void main()
{
writeln(Case1);
{
Mt19937 gen = Mt19937(0);
writeln(gen.front);
gen.popFront;
writeln(gen.front);
}
writeln(---);
{
Mt19937 gen = Mt19937(0);
advance(gen, 1);  // skip 1 element
writeln(gen.front);
gen.popFront;
writeln(gen.front);
}
writeln(\nCase2);
{
Mt19937 gen;
writeln(gen.front);
gen.popFront;
writeln(gen.front);
}
writeln(---);
{
Mt19937 gen;
advance(gen, 1);  // skip 1 element
writeln(gen.front);
gen.popFront;
writeln(gen.front);
}
}

Result:

Case1
2357136044 (1)
2546248239 (2)
---
2546248239 (2)
3071714933 (3)

Case2
581869302  (1)
3890346734 (2)
---
581869302  (1)?
3890346734 (2)?

I think 'Case1' is correct, but 'Case2' is wrong.
Mt19937's bug?



If you initialize the Mersenne twister with no seed it will start with
seed 5489u.


I think his point is in the second part of Case2, he skipped one  
element, but it appears that it didn't skip anything.

Thanks for your comment.
Lack of talk about this problem:|

--
tama repeate...@gmail.com
http://profile.livedoor.com/repeatedly/


Re: dmd 2.029 release

2009-04-21 Thread Max Samukha
On Mon, 20 Apr 2009 00:09:09 -0700, Walter Bright
newshou...@digitalmars.com wrote:


This is a major revision to Phobos, including Andrei's revolutionary new 
range support.

http://www.digitalmars.com/d/2.0/changelog.html
http://ftp.digitalmars.com/dmd.2.029.zip

Wicked awesome!

file:///C:/dmd/html/d/phobos/std_range.html#cons
Looks like bug 2676 was fixed in 2.027


Re: dmd 2.029 release

2009-04-21 Thread Max Samukha
On Mon, 20 Apr 2009 09:57:55 +0200, Max Samukha
samu...@voliacable.com.removethis wrote:

On Mon, 20 Apr 2009 00:09:09 -0700, Walter Bright
newshou...@digitalmars.com wrote:


This is a major revision to Phobos, including Andrei's revolutionary new 
range support.

http://www.digitalmars.com/d/2.0/changelog.html
http://ftp.digitalmars.com/dmd.2.029.zip

Wicked awesome!

file:///C:/dmd/html/d/phobos/std_range.html#cons
http://www.digitalmars.com/d/2.0/phobos/std_range.html#cons

Looks like bug 2676 was fixed in 2.027


Re: dmd 2.029 release

2009-04-21 Thread Lars T. Kyllingstad

Walter Bright wrote:


This is a major revision to Phobos, including Andrei's revolutionary new 
range support.


http://www.digitalmars.com/d/2.0/changelog.html
http://ftp.digitalmars.com/dmd.2.029.zip


This is looking very nice! I want to switch from D1 to D2, but...

I don't want to sound greedy or anything, and I know others have asked 
for this before, but is making a 64-bit Linux version of DMD a lot of work?


I admit I don't know much about these things, and what I'm going to say 
next may not make sense at all, but here goes:


x86-64 is just a superset of x86, right? Wouldn't it be possible, as a 
first step in the direction of a full-fledged x86-64 compiler, to simply 
make one that uses the same instruction set as the current DMD, but, I 
dunno, marks the executable as 64-bit (or something like that)? 
Specialisation and optimisation for the 64-bit architecture could then 
come at a later point in time.


I know it is possible to run the 32-bit compiler (and the executables it 
produces) on a 64-bit operating system, but it isn't possible to link 
against 64-bit libraries. This means that one has to install and 
maintain 32-bit versions of all the libraries one wants to use, and 
those are, in general, not available through the repositories of most 
64-bit distros.


-Lars


Re: dmd 2.029 release

2009-04-21 Thread Frits van Bommel

Lars T. Kyllingstad wrote:

Walter Bright wrote:


This is a major revision to Phobos, including Andrei's revolutionary 
new range support.


http://www.digitalmars.com/d/2.0/changelog.html
http://ftp.digitalmars.com/dmd.2.029.zip


This is looking very nice! I want to switch from D1 to D2, but...

I don't want to sound greedy or anything, and I know others have asked 
for this before, but is making a 64-bit Linux version of DMD a lot of work?


I admit I don't know much about these things, and what I'm going to say 
next may not make sense at all, but here goes:


x86-64 is just a superset of x86, right? Wouldn't it be possible, as a 
first step in the direction of a full-fledged x86-64 compiler, to simply 
make one that uses the same instruction set as the current DMD, but, I 
dunno, marks the executable as 64-bit (or something like that)? 
Specialisation and optimisation for the 64-bit architecture could then 
come at a later point in time.


It's not quite that simple. It's not a full superset; some x86 instructions are 
not valid x86-64 instructions.
For example, I think 'inc' was removed to make place for prefixes that set some 
flags for the next instruction and allow it to use the extra registers r8-r15.


Re: dmd 2.029 release

2009-04-21 Thread Frits van Bommel

Daniel Keep wrote:


Lars T. Kyllingstad wrote:

Walter Bright wrote:

This is a major revision to Phobos, including Andrei's revolutionary
new range support.

http://www.digitalmars.com/d/2.0/changelog.html
http://ftp.digitalmars.com/dmd.2.029.zip

This is looking very nice! I want to switch from D1 to D2, but...


[snip]


The best bet for 64-bit D executables at this point is probably LDC;
dunno what the current state is, though.


The state for D2 is currently very broken, AFAIK.


Re: dmd 2.029 release

2009-04-21 Thread Lutger
Daniel Keep wrote:

...
 -Lars
 
 The best bet for 64-bit D executables at this point is probably LDC;
 dunno what the current state is, though.
 
   -- Daniel

if you grep the dmd backend sources for x86_64, you'll get some results. 
Don't know what that means though, the source looks like magic to me!




Re: dmd 2.029 release

2009-04-21 Thread Andrei Alexandrescu

Lars T. Kyllingstad wrote:

Walter Bright wrote:


This is a major revision to Phobos, including Andrei's revolutionary 
new range support.


http://www.digitalmars.com/d/2.0/changelog.html
http://ftp.digitalmars.com/dmd.2.029.zip


This is looking very nice! I want to switch from D1 to D2, but...

I don't want to sound greedy or anything, and I know others have asked 
for this before, but is making a 64-bit Linux version of DMD a lot of work?


I would kill for a 64-bit Linux DMD. I think it could take a lot of ways 
of coding to a whole new level. Sean and I have also been discussing how 
to integrate memory-mapped files with the garbage collector. In a 64-bit 
environment this makes for an awesome programming model.



Andrei


Re: dmd 2.029 release

2009-04-21 Thread Andrei Alexandrescu

Max Samukha wrote:

On Mon, 20 Apr 2009 09:57:55 +0200, Max Samukha
samu...@voliacable.com.removethis wrote:


On Mon, 20 Apr 2009 00:09:09 -0700, Walter Bright
newshou...@digitalmars.com wrote:

This is a major revision to Phobos, including Andrei's revolutionary new 
range support.


http://www.digitalmars.com/d/2.0/changelog.html
http://ftp.digitalmars.com/dmd.2.029.zip

Wicked awesome!

file:///C:/dmd/html/d/phobos/std_range.html#cons

http://www.digitalmars.com/d/2.0/phobos/std_range.html#cons


Looks like bug 2676 was fixed in 2.027


Thanks. I uncommented the unittest, updated the doc, and checked in.

Andrei


Re: dmd 2.029 release

2009-04-21 Thread Lars T. Kyllingstad

Andrei Alexandrescu wrote:

Lars T. Kyllingstad wrote:

Walter Bright wrote:


This is a major revision to Phobos, including Andrei's revolutionary 
new range support.


http://www.digitalmars.com/d/2.0/changelog.html
http://ftp.digitalmars.com/dmd.2.029.zip


This is looking very nice! I want to switch from D1 to D2, but...

I don't want to sound greedy or anything, and I know others have asked 
for this before, but is making a 64-bit Linux version of DMD a lot of 
work?


I would kill for a 64-bit Linux DMD. [...]


Who does one have to kill to get a 64-bit compiler around here? :)

But seriously, now that the language itself is stabilising, I would 
consider this a major priority for further development of DMD. 64 bits 
is the (immediate) future.


-Lars


Re: dmd 2.029 release

2009-04-21 Thread Leandro Lucarella
Georg Wrede, el 21 de abril a las 09:25 me escribiste:
 What's sad, http://en.wikipedia.org/wiki/Standard_Template_Library
 really sucks at introducing the STL on a conceptual level. Even worse, that 
 is 
 actually the only thing it *should* do. Everyting else is optional.

You should improve it then =)

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/

GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)



Re: dmd 2.029 release

2009-04-21 Thread bearophile
Don:
  From 2.208:
 2804 Impure nested functions should be legal inside pure functions

Very good. Now that little example works:

import std.c.stdio: printf;
import std.conv: to;

pure int double_sqr(int x) {
int y, z;
void do_sqr() { y *= y; }
y = x;
do_sqr();
z += y;
y = x;
do_sqr();
z += y;
return z;
}

void main(string[] args) {
int x = args.length == 2 ? to!(int)(args[1]) : 10;
int y = double_sqr(x) + double_sqr(x);
printf(4 * x * x = %d\n, y);
}

The outout is correct:
4 * x * x = 400


Cleaned up ASM produced by DMD V.2.029, -O -release -inline:

double_sqr:
pushEAX
mov ECX,EAX
mov [ESP],0
mov [ESP],ECX
imulEAX,[ESP]
mov EDX,EAX
mov [ESP],EAX
mov EAX,ECX
mov [ESP],ECX
imulEAX,[ESP]
add EDX,EAX
mov [ESP],EAX
mov EAX,EDX
pop ECX
ret

double_sqr.do_sqr:
mov ECX,[EAX]
imulECX,[EAX]
mov [EAX],ECX
ret

main:
L0: sub ESP,014h
cmp dword ptr 018h[ESP],2
jne L21
mov EDX,01Ch[ESP]
mov EAX,018h[ESP]
mov EAX,8[EDX]
mov EDX,0Ch[EDX]
pushEDX
pushEAX
callnear ptr parseString
jmp short   L26
L21:mov EAX,0Ah
L26:callnear ptr double_sqr
add EAX,EAX
mov ECX,offset FLAT:_DATA
pushEAX
pushECX
callnear ptr printf

As you can see there's only one call to double_sqr in the main program, so the 
pure semantics is working here.

You can also see do_sqr is inlined into double_sqr. But the asm code inside 
double_sqr looks very hairy and long, and double_sqr itself isn't inlined in 
the main.

Bye,
bearophile


Re: dmd 2.029 release

2009-04-21 Thread Leandro Lucarella
Andrei Alexandrescu, el 21 de abril a las 07:38 me escribiste:
 Lars T. Kyllingstad wrote:
 Walter Bright wrote:
 
 This is a major revision to Phobos, including Andrei's revolutionary new 
 range 
 support.
 
 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.029.zip
 This is looking very nice! I want to switch from D1 to D2, but...
 I don't want to sound greedy or anything, and I know others have asked for 
 this 
 before, but is making a 64-bit Linux version of DMD a lot of work?
 
 I would kill for a 64-bit Linux DMD. I think it could take a lot of ways of 
 coding to a whole new level. Sean and I have also been discussing how to 
 integrate memory-mapped files with the garbage collector. In a 64-bit 
 environment this makes for an awesome programming model.

Can you elaborate on that?

Thanks.

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/

GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)



Re: dmd 2.029 release

2009-04-21 Thread bearophile
I have also tested the semantics of nested function purity:

import std.c.stdio: printf;
import std.conv: to;

pure int double_sqr(int x) {
pure int sqr(int y) { return y * y; }
return sqr(x) + sqr(x);
}

void main(string[] args) {
int x = args.length == 2 ? to!(int)(args[1]) : 10;
int y = double_sqr(x) + double_sqr(x);
printf(4 * x * x = %d\n, y);
}

Compiled without inlining:
-O -release

double_sqr.sqr:
mov EAX,4[ESP]
imulEAX,EAX
ret 4

double_sqr:
L0: pushEAX
pushEAX
xor EAX,EAX
callnear ptr double_sqr.sqr
pushEAX
sub ESP,4
xor EAX,EAX
pushdword ptr 8[ESP]
callnear ptr double_sqr.sqr
add ESP,4
mov ECX,EAX
pop EAX
add EAX,ECX
pop ECX
ret

main:
L0: pushEAX
cmp dword ptr 8[ESP],2
jne L1D
mov EDX,0Ch[ESP]
mov EAX,8[ESP]
pushdword ptr 0Ch[EDX]
pushdword ptr 8[EDX]
callnear ptr to!(int)()
jmp short   L22
L1D:mov EAX,0Ah
L22:callnear ptr double_sqr
add EAX,EAX
mov ECX,offset FLAT:_DATA
pushEAX
pushECX
callnear ptr printf

There's one call to double_sqr but unfortunately two to double_sqr.sqr.

Bye,
bearophile


Re: dmd 2.029 release

2009-04-21 Thread Don

bearophile wrote:

I have tried the following code:

import std.c.stdio: printf;
import std.conv: to;

nothrow pure int double_sqr(int x) { // line 4
int y, z;
nothrow void do_sqr() { y *= y; }
y = x;
do_sqr();
z += y;
y = x;
do_sqr();
z += y;
return z;
}

void main(string[] args) {
int x = args.length == 2 ? to!(int)(args[1]) : 10;
int y = double_sqr(x) + double_sqr(x);
printf(4 * x * x = %d\n, y);
}

The compiler spits the following error:

pure_impure_test.d(4): Error: function pure_impure_test.double_sqr 'double_sqr' 
is nothrow yet may throw

but I don't understand why. What are the things inside it that can throw an 
exception?

Bye,
bearophile


Obviously my 2808 patch only solved one part of the problem.
It compiles if you change do_sqr to
void do_sqr() nothrow { y *= y; }
Please add a bug report to Bugzilla.


Re: dmd 2.029 release

2009-04-21 Thread bearophile
Don:
 Yes. Actually, marking a nested function as pure doesn't make much sense.
 It's entirely equivalent to moving it outside the function; [...]
 I'm not sure that nested pure member functions should be legal.

It's not fully equivalent to moving it out of the function because once you 
pull it out you add a name to the outer namespace: nested functions are useful 
to keep namespaces tidy too.
So I'd like to have nested pure functions too.

pure int foo(int y) { return y + y; } // outer foo
pure void bar(int x) {
  pure int foo(int y) { return y * y; }
  return foo(x) * .foo(x);
}

Thank you,
bye,
bearophile


Re: dmd 2.029 release

2009-04-21 Thread Walter Bright

Lutger wrote:

what the hell...this code can't be human.


I was replaced by Colossus years ago.


Re: dmd 2.029 release

2009-04-21 Thread Don

bearophile wrote:

Don:

Yes. Actually, marking a nested function as pure doesn't make much sense.
It's entirely equivalent to moving it outside the function; [...]
I'm not sure that nested pure member functions should be legal.


It's not fully equivalent to moving it out of the function because once you 
pull it out you add a name to the outer namespace: nested functions are useful 
to keep namespaces tidy too.
So I'd like to have nested pure functions too.

pure int foo(int y) { return y + y; } // outer foo
pure void bar(int x) {
  pure int foo(int y) { return y * y; }
  return foo(x) * .foo(x);
}

Thank you,
bye,
bearophile


That's true, but it seems quite difficult to get right. A pure nested 
function can in theory access immutable members in the outer function -- 
but must not access the parameters of the outer function.
If there are no immutable members in the outer function, the compiler 
would ideally convert it into an external pure function, so that it
doesn't need a frame pointer to the outer function. But it would need 
error messages for any use of mutable outer function members. Etc.

It seems quite a lot of work for something of very limited use.
Making it into a external, private pure function is almost the same.




Re: dmd 2.029 release

2009-04-21 Thread Stewart Gordon

Walter Bright wrote:

Stewart Gordon wrote:
Walter, how often do you update your working copy from the SVN? 
Obviously less than once every 2 releases.


As far as I know, it is current. Everything got checked in.


So how has the fix for
http://d.puremagic.com/issues/show_bug.cgi?id=2580
(and probably others) not been included?

Stewart.


Re: dmd 2.029 release

2009-04-21 Thread Georg Wrede

Walter Bright wrote:

Lutger wrote:

what the hell...this code can't be human.


I was replaced by Colossus years ago.


Michael A. Jackson wouldn't approve 1175 gotos in 113 files.



Re: dmd 2.029 release

2009-04-21 Thread Michel Fortin

On 2009-04-21 11:18:39 -0400, Don nos...@nospam.com said:


Yes. Actually, marking a nested function as pure doesn't make much sense.
It's entirely equivalent to moving it outside the function; a nested 
pure function shouldn't be able to access any members of the enclosing 
function, otherwise it's not pure. But DMD doesn't enforce that, and so 
it creates inefficient and possibly buggy code.


What about immutable local variables? A pure function can access 
immutable globals, so it should be able to access immutable locals too.


--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/



  1   2   >