March 16, 2012
On 3/16/2012 4:04 PM, Andrei Alexandrescu wrote:
> Never say never. There are I/O routines that are specialized for several OSs and
> fall back to a generic (slower) implementation.

I'm going to suggest that is wrong as well. It's fine for a new port to use a generic slow implementation, but that ought to be a deliberate choice, *not* a default that went unnoticed during the porting process.

March 16, 2012
On 3/16/2012 4:18 PM, Walter Bright wrote:
> On 3/16/2012 4:04 PM, Andrei Alexandrescu wrote:
>> Never say never. There are I/O routines that are specialized for several OSs and
>> fall back to a generic (slower) implementation.
>
> I'm going to suggest that is wrong as well. It's fine for a new port to use a
> generic slow implementation, but that ought to be a deliberate choice, *not* a
> default that went unnoticed during the porting process.
>

I should explain this better. Having a default is wrong because:

1. as mentioned, it can be overlooked in the porting process

2. if the default doesn't work right for some system, the temptation will be to 'fix' the default in ways that are untested (and therefore broken) on other systems. Working on one system's code should not affect other systems!

3. it leaves unknown to the reader what systems that may apply to

I know the powerful temptation to avoid copypasta. But I have decades of trying it that way, and it just leads to lots of time wasted tracking down bugs. This includes historical bugs from doing it that way with druntime & phobos.
March 17, 2012
On 3/16/12 6:30 PM, Walter Bright wrote:
> On 3/16/2012 4:18 PM, Walter Bright wrote:
>> On 3/16/2012 4:04 PM, Andrei Alexandrescu wrote:
>>> Never say never. There are I/O routines that are specialized for
>>> several OSs and
>>> fall back to a generic (slower) implementation.
>>
>> I'm going to suggest that is wrong as well. It's fine for a new port
>> to use a
>> generic slow implementation, but that ought to be a deliberate choice,
>> *not* a
>> default that went unnoticed during the porting process.
>>
>
> I should explain this better. Having a default is wrong because:
>
> 1. as mentioned, it can be overlooked in the porting process
>
> 2. if the default doesn't work right for some system, the temptation
> will be to 'fix' the default in ways that are untested (and therefore
> broken) on other systems. Working on one system's code should not affect
> other systems!
>
> 3. it leaves unknown to the reader what systems that may apply to
>
> I know the powerful temptation to avoid copypasta. But I have decades of
> trying it that way, and it just leads to lots of time wasted tracking
> down bugs. This includes historical bugs from doing it that way with
> druntime & phobos.

Not convinced. They call it specialization, and it's a powerful concept. We use it in std.algorithm all over the place.

Andrei
March 17, 2012
"Andrei Alexandrescu" <SeeWebsiteForEmail@erdani.org> wrote in message news:jk0l57$20hs$1@digitalmars.com...
>
> Not convinced. They call it specialization, and it's a powerful concept. We use it in std.algorithm all over the place.
>
> Andrei

You can do that just as well without using an 'else' block.

version(ThisOS)
{
   doItThisWay();
}
else version(ThatOS)
{
   doItThatWay();
}
else version(SomeOS)
{
   doItSlowWay();
}
else version(OtherOS)
{
   doItSlowWay();
}
else
   static assert(0, "OS not implemented");

This means you're forced to choose which way when implementing that new version, instead of hoping that it will work.

This is not really the same thing as (eg) specializing searching for narrow strings.


March 17, 2012
On 3/16/12 7:45 PM, Daniel Murphy wrote:
> You can do that just as well without using an 'else' block.
>
> version(ThisOS)
> {
>     doItThisWay();
> }
> else version(ThatOS)
> {
>     doItThatWay();
> }
> else version(SomeOS)
> {
>     doItSlowWay();
> }
> else version(OtherOS)
> {
>     doItSlowWay();
> }
> else
>     static assert(0, "OS not implemented");

But why duplicate doItSlowWay(); which may be an arbitrarily long sequence?

This seems to accomplish little more than "well I didn't use else".

Again: what exactly is wrong with specialization?


Andrei
March 17, 2012
"Andrei Alexandrescu" <SeeWebsiteForEmail@erdani.org> wrote in message news:jk0naq$257e$1@digitalmars.com...
>
> But why duplicate doItSlowWay(); which may be an arbitrarily long sequence?

If duplicating that block is a problem, there are other ways to do it.

version(ThisOS)
{
   version = FastWayA;
}
else version(ThatOS)
{
   version = FastWayB;
}
else version(SomeOS)
{
   version = SlowWay;
}
else version(OtherOS)
{
   version = SlowWay;
}
else
   static assert(0, "OS not implemented");

version(FastWayA)
{
...
}
else version (FastWayB)
{
...
}
else version (SlowWay)
{
...
}


>
> This seems to accomplish little more than "well I didn't use else".
>
> Again: what exactly is wrong with specialization?
>

The advantage is, that when you write the code, you have _no idea_ what platform/os it might need to run on in the future.  You _cannot_ know which version is most appropriate for _all_ new platforms, or even if any of them will work at all.  The only time to make this decision is when implementing support for a specific platform, and this pattern forces you to consider each place where platform specific behaviour is required.  When doing things like this, 100 false positives are much faster to fix than a single false negative causing wrong code/corruption.


March 17, 2012
On 3/16/12 8:16 PM, Daniel Murphy wrote:
> "Andrei Alexandrescu"<SeeWebsiteForEmail@erdani.org>  wrote in message
> news:jk0naq$257e$1@digitalmars.com...
>>
>> But why duplicate doItSlowWay(); which may be an arbitrarily long
>> sequence?
>
> If duplicating that block is a problem, there are other ways to do it.
[snip]

This is in the same vein: "let's avoid else".

>> This seems to accomplish little more than "well I didn't use else".
>>
>> Again: what exactly is wrong with specialization?
>>
>
> The advantage is, that when you write the code, you have _no idea_ what
> platform/os it might need to run on in the future.  You _cannot_ know which
> version is most appropriate for _all_ new platforms, or even if any of them
> will work at all.

Oh yes I do. Often I know every platform has e.g. getchar() so I can use it. That will definitely work for everyone. Then, if I get to optimize things for particular platforms, great. This is the case for many artifacts.

> The only time to make this decision is when implementing
> support for a specific platform, and this pattern forces you to consider
> each place where platform specific behaviour is required.  When doing things
> like this, 100 false positives are much faster to fix than a single false
> negative causing wrong code/corruption.

I just find it difficult to get convinced about this. Walter has often talked my ear off about this dogma and never produced a convincing argument.


Andrei
March 17, 2012
On 17-03-2012 02:16, Daniel Murphy wrote:
> "Andrei Alexandrescu"<SeeWebsiteForEmail@erdani.org>  wrote in message
> news:jk0naq$257e$1@digitalmars.com...
>>
>> But why duplicate doItSlowWay(); which may be an arbitrarily long
>> sequence?
>
> If duplicating that block is a problem, there are other ways to do it.
>
> version(ThisOS)
> {
>     version = FastWayA;
> }
> else version(ThatOS)
> {
>     version = FastWayB;
> }
> else version(SomeOS)
> {
>     version = SlowWay;
> }
> else version(OtherOS)
> {
>     version = SlowWay;
> }
> else
>     static assert(0, "OS not implemented");
>
> version(FastWayA)
> {
> ....
> }
> else version (FastWayB)
> {
> ....
> }
> else version (SlowWay)
> {
> ....
> }
>
>
>>
>> This seems to accomplish little more than "well I didn't use else".
>>
>> Again: what exactly is wrong with specialization?
>>
>
> The advantage is, that when you write the code, you have _no idea_ what
> platform/os it might need to run on in the future.  You _cannot_ know which
> version is most appropriate for _all_ new platforms, or even if any of them
> will work at all.  The only time to make this decision is when implementing
> support for a specific platform, and this pattern forces you to consider
> each place where platform specific behaviour is required.  When doing things
> like this, 100 false positives are much faster to fix than a single false
> negative causing wrong code/corruption.
>
>

I think this post is basically proof that we need logical and/or in version statements. I'm just putting that out there....

-- 
- Alex
March 17, 2012
"Andrei Alexandrescu" <SeeWebsiteForEmail@erdani.org> wrote in message news:jk0ptd$29g2$1@digitalmars.com...
>>>
>>> But why duplicate doItSlowWay(); which may be an arbitrarily long
>>> sequence?
>>
>> If duplicating that block is a problem, there are other ways to do it.
> [snip]
>
> This is in the same vein: "let's avoid else".
>

Yes.

>>> This seems to accomplish little more than "well I didn't use else".
>>>
>>> Again: what exactly is wrong with specialization?
>>>
>>
>> The advantage is, that when you write the code, you have _no idea_ what
>> platform/os it might need to run on in the future.  You _cannot_ know
>> which
>> version is most appropriate for _all_ new platforms, or even if any of
>> them
>> will work at all.
>
> Oh yes I do. Often I know every platform has e.g. getchar() so I can use it. That will definitely work for everyone. Then, if I get to optimize things for particular platforms, great. This is the case for many artifacts.
>

Are there really no platforms out there where getchar doesn't exist?  What if you need to work around a buggy c standard lib on some platforms?

Relying on getchar (and most of the c standard lib) working correctly is probably ok, so long as we never target more exotic architectures.  But this is not true generally, and do you really trust everybody who works on the code to make the right choice each time?

>> The only time to make this decision is when implementing
>> support for a specific platform, and this pattern forces you to consider
>> each place where platform specific behaviour is required.  When doing
>> things
>> like this, 100 false positives are much faster to fix than a single false
>> negative causing wrong code/corruption.
>
> I just find it difficult to get convinced about this. Walter has often talked my ear off about this dogma and never produced a convincing argument.
>
>
> Andrei

Well, he managed to convince me some time ago.  Maybe you should try porting code between microcontrollers and see if it makes more sense then.  The best part is that if you use this pattern when it isn't needed, the cost is very small.


March 17, 2012
"Alex Rønne Petersen" <xtzgzorex@gmail.com> wrote in message news:jk0rr8$2c3n$1@digitalmars.com...
>
> I think this post is basically proof that we need logical and/or in version statements. I'm just putting that out there....
>
> -- 
> - Alex

Yeah.  While I agree with Walter's arguments against this, forcing that approch on everyone that uses D is not the language's job.