April 22, 2009
On Wed, 22 Apr 2009 00:32:27 -0700, Brad Roberts <braddr@puremagic.com> wrote:

>Max Samukha wrote:
>> On Tue, 21 Apr 2009 07:42:46 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>> 
>>> Max Samukha wrote:
>>>> On Mon, 20 Apr 2009 09:57:55 +0200, Max Samukha <samukha@voliacable.com.removethis> wrote:
>>>>
>>>>> On Mon, 20 Apr 2009 00:09:09 -0700, Walter Bright <newshound1@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
>> 
>> A couple more minor doc issues: http://www.digitalmars.com/d/2.0/phobos/std_range.html: instances of "the popFront" need to be corrected to "the next".
>> 
>> On the std.algorithm page, the examples for "map" and "filter" don't compile due to the fixed size array in equal().
>> 
>> The example for "bringToFront" is outdated.
>> 
>> The comments for "remove": "If $(s =" -> "If $(D s ="
>
>Please file a bug report.  Posts here are are good way for issues to fall through the cracks.
>
>Thanks,
>Brad

done http://d.puremagic.com/issues/show_bug.cgi?id=2874
April 22, 2009
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... :-)

> 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 search&replaces). 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 suggesting Walter should do it. Just an academic question.)
April 22, 2009
On Wed, 22 Apr 2009 03:12:04 -0400, Don <nospam@nospam.com> wrote:

> Daniel Keep wrote:
>>  Michel Fortin wrote:
>>> On 2009-04-21 11:18:39 -0400, Don <nospam@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
April 22, 2009
Steven Schveighoffer wrote:
> On Wed, 22 Apr 2009 03:12:04 -0400, Don <nospam@nospam.com> wrote:
> 
>> Daniel Keep wrote:
>>>  Michel Fortin wrote:
>>>> On 2009-04-21 11:18:39 -0400, Don <nospam@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>.
April 22, 2009
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.

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

http://dobbscodetalk.com/index.php?option=com_myblog&show=What-Dijkstra-said-was-harmful-about-goto-statements.html&Itemid=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.

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.

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.

>> 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 search&replaces). 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 suggesting Walter should do it. Just an academic question.)

I doubt it'd affect the speed at all. It'd probably make it longer. There are cases in DMD where it seems to make the control flow simpler.
April 22, 2009
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
April 22, 2009
Georg Wrede wrote:
> 
> 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 suggesting Walter should do it. Just an academic question.)

Yes.  For better or worse, goto is sometimes the best way to write efficient code without any duplication.
April 22, 2009
tama wrote:
> On Mon, 20 Apr 2009 16:09:09 +0900, Walter Bright <newshound1@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.

Andrei
April 22, 2009
On Wed, 22 Apr 2009 13:49:18 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> tama wrote:
>> On Mon, 20 Apr 2009 16:09:09 +0900, Walter Bright
>> <newshound1@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.

-Steve
April 22, 2009
Steven Schveighoffer wrote:
> On Wed, 22 Apr 2009 13:49:18 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> 
>> tama wrote:
>>> On Mon, 20 Apr 2009 16:09:09 +0900, Walter Bright
>>> <newshound1@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