September 07, 2011
On 09/07/2011 10:49 PM, Jonathan M Davis wrote:
> On Wednesday, September 07, 2011 14:16:55 Timon Gehr wrote:
>> On 09/07/2011 01:42 PM, Jonathan M Davis wrote:
>>> On 09/07/2011 01:27 PM, Timon Gehr wrote:
>>>> Oh, btw:
>>>>
>>>> final switch(Mode.read|Mode.write){
>>>>
>>>>        case Mode.read: writeln(1); break;
>>>>        case Mode.write: writeln(2); break;
>>>>
>>>> }
>>>>
>>>> =>   2
>>>>
>>>> hm...
>>
>> Actually, it will print nothing, not even an Assertion failure, my enum
>> definition was wrong
>
> Did you compile with -w? I don't remember if that affects final switch or not,
> but there's definitely a problem if you can get final switch to take a value
> that it doesn't handle without using a cast.

final switch works the same with or without warnings. Basically final switch is wrong in assuming that enumerations can only contain the declared values, because the bitwise operators work on enums.

>
>>> Personally, I don't think that&ing or |ing enums should result in an
>>> enum, and this case illustrates one reason why. But ultimately, the
>>> main issue IMHO is that&ing or |ring enums doesn't generally result in
>>> a valid enum value, so it just doesn't make sense.
>>
>> Yes exactly. That is why I always use
>>
>> alias int MODE;
>> enum:MODE{
>>       MODEread=1,
>>       MODEwrite=2,
>> }
>
> And how is that any different from
>
> alias int MODE;
> enum MODEread = 1;
> enum MODEwrite = 2;

It is not. But there is currently no nice way to express a set of orthogonal flags. enumerations are mis-used for it sometimes, but as you said that does not make sense. I sometimes have small bugs because the alias is weakly typed though.

>
> They're manifest constants, not enum values. So, you're basically suggesting
> that flags be done with manifest constants as opposed to enums? That doesn't
> encapsulate as well IMHO, and I'd still object to a function having a MODE
> parameter, since that implies that a MODE is a single flag, whereas it's a
> group of flags -

I'd argue that (MODEread | MODEwrite) is a single mode resulting from the composition of the MODEread and MODEwrite modes.

> that and as far as Phobos goes, we don't generally use aliases
> like that (of course, we don't name types in all caps or start variable or
> enum value names with uppercase characaters either, so what Phobos does
> obviously isn't necssarily what you stick to).
>

That is why imho Phobos should not use enums for file modes. They are just not a good match, because the language is so confused about what is valid on enums and what is not.




September 07, 2011
> It is not. But there is currently no nice way to express a set of orthogonal flags.
Well, you could use an array of flags ? Oh, wait, that is precisely what
"r", "w", "rw" would be.
Another option is to use the power of typesafe variadic functions:

enum Mode :char { read, write }
File fOpen(string filename, Mode[]...);

auto file = fOpen("test.txt", Mode.read, Mode.write);

Isn't it much clearer than using (Mode.read | Mode.write)? Even using explicitely [Mode.read, Mode.write] sounds safer anyway. It is uses more memory that using bits operators, but who cares about few bytes when opening a whole file ?

-- 
Christophe
September 07, 2011
On 09/07/2011 11:59 PM, Christophe wrote:
>> It is not. But there is currently no nice way to express a set of
>> orthogonal flags.
> Well, you could use an array of flags ? Oh, wait, that is precisely what
> "r", "w", "rw" would be.

At least it is short.

> Another option is to use the power of typesafe variadic functions:
>
> enum Mode :char { read, write }
> File fOpen(string filename, Mode[]...);
>
> auto file = fOpen("test.txt", Mode.read, Mode.write);
>
> Isn't it much clearer than using (Mode.read | Mode.write)? Even using
> explicitely [Mode.read, Mode.write] sounds safer anyway. It is uses more
> memory that using bits operators, but who cares about few bytes when
> opening a whole file ?
>

do you seriously prefer

auto f=fOpen("bah.txt",[Mode.read, Mode.write]);

over

auto f=fOpen("bah.txt","rw");


if that is the case, you could do

auto f=fOpen("bah.txt",encodeMode!([Mode.read, Mode.write]));


that even saves the few bytes.





September 07, 2011
On 9/7/2011 5:21 AM, Michel Fortin wrote:
> On 2011-09-06 18:00:36 +0000, Walter Bright <newshound2@digitalmars.com> said:
>
>> The winner with binary compatibility is, far and away, Microsoft.
>
> Indeed, I think you're right that they are better than Apple. But you have to
> keep in mind that DMD doesn't depend on Microsoft's linker, and doesn't depend
> on Microsoft's C runtime. I bet you'd see more breakages otherwise.


I used to know people who worked in Microsoft's "app compat" department. The lengths they would go to to maintain support for older apps was amazing. It wasn't about just supporting documented behavior, it was supporting undocumented behavior and gross misuse of the APIs.
September 07, 2011
On 9/7/2011 6:22 PM, Walter Bright wrote:
> On 9/7/2011 5:21 AM, Michel Fortin wrote:
>> On 2011-09-06 18:00:36 +0000, Walter Bright
>> <newshound2@digitalmars.com> said:
>>
>>> The winner with binary compatibility is, far and away, Microsoft.
>>
>> Indeed, I think you're right that they are better than Apple. But you
>> have to
>> keep in mind that DMD doesn't depend on Microsoft's linker, and
>> doesn't depend
>> on Microsoft's C runtime. I bet you'd see more breakages otherwise.
>
>
> I used to know people who worked in Microsoft's "app compat" department.
> The lengths they would go to to maintain support for older apps was
> amazing. It wasn't about just supporting documented behavior, it was
> supporting undocumented behavior and gross misuse of the APIs.

Yeh, the story of Raymond Chen working on a team that disassembled SimCity and inserted extra code to make it work even though it used previously freed memory comes to mind.
September 07, 2011
On 9/7/2011 4:06 PM, dsimcha wrote:
> On 9/7/2011 6:22 PM, Walter Bright wrote:
>> On 9/7/2011 5:21 AM, Michel Fortin wrote:
>>> On 2011-09-06 18:00:36 +0000, Walter Bright
>>> <newshound2@digitalmars.com> said:
>>>
>>>> The winner with binary compatibility is, far and away, Microsoft.
>>>
>>> Indeed, I think you're right that they are better than Apple. But you
>>> have to
>>> keep in mind that DMD doesn't depend on Microsoft's linker, and
>>> doesn't depend
>>> on Microsoft's C runtime. I bet you'd see more breakages otherwise.
>>
>>
>> I used to know people who worked in Microsoft's "app compat" department.
>> The lengths they would go to to maintain support for older apps was
>> amazing. It wasn't about just supporting documented behavior, it was
>> supporting undocumented behavior and gross misuse of the APIs.
>
> Yeh, the story of Raymond Chen working on a team that disassembled SimCity and
> inserted extra code to make it work even though it used previously freed memory
> comes to mind.


I believe this was a large factor in the success of Microsoft Windows.
September 08, 2011
On 2011-09-07 22:22:25 +0000, Walter Bright <newshound2@digitalmars.com> said:

> On 9/7/2011 5:21 AM, Michel Fortin wrote:
>> On 2011-09-06 18:00:36 +0000, Walter Bright <newshound2@digitalmars.com> said:
>> 
>>> The winner with binary compatibility is, far and away, Microsoft.
>> 
>> Indeed, I think you're right that they are better than Apple. But you have to
>> keep in mind that DMD doesn't depend on Microsoft's linker, and doesn't depend
>> on Microsoft's C runtime. I bet you'd see more breakages otherwise.
> 
> I used to know people who worked in Microsoft's "app compat" department. The lengths they would go to to maintain support for older apps was amazing. It wasn't about just supporting documented behavior, it was supporting undocumented behavior and gross misuse of the APIs.

Well, sometime Apple does support undocumented behaviour of previous version of their OS too. Take this prototype from time.h for instance:

	clock_t clock(void) __DARWIN_ALIAS(clock);

What this __DARWIN_ALIAS macro does is it forces the code to use "_clock$UNIX2003" as the symbol name for the clock() function instead of the standard "_clock" symbol name. That's because the older version of the function had some bug in it (it was not conformant to some UNIX standard) but they still wanted old binaries to continue using the old version (so they don't break). Code compiled with the newer header will link with the fixed "_clock$UNIX2003" function instead of the old buggy one.

But more generally, there's sometime a long term cost in supporting undocumented behaviour. If you let developers use undocumented things without consequence, you send the message that they can depend on them and they'll just depend on them more, and the more software that depends on undocumented behaviours the harder it becomes to tweak the API without breaking everything.

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

September 08, 2011
On 9/7/2011 2:19 AM, Jacob Carlborg wrote:
> On 2011-09-06 19:05, Daniel Murphy wrote:
>> "Andrei Alexandrescu"<SeeWebsiteForEmail@erdani.org> wrote in message
>> news:j45isu$2t3h$1@digitalmars.com...
>>>
>>> Yah, I also think the documentation makes it easy to clarify which
>>> module
>>> is the preferred one.
>>>
>>> I think there's a lot of merit to simply appending a '2' to the module
>>> name. There only place where the '2' occurs is in the name of the
>>> module,
>>> and there aren't many modules we need to replace like that.
>>
>> I still can never remember if I'm supposed to be using std.regex or
>> std.regexp.
>> When the new one is finished are we going to have 3?
>>
>> It's definately benificial to avoid breaking code, but I really disagree
>> that phobos has reached that point yet. The breaking changes need to
>> stop,
>> but stopping prematurely will leave phobos permanently disfigured.
>
> I agree.
>


In the COM based land for D3D, there is just a number tacked onto the class name.  We are up to version 11 (e.x. ID3D11Device).  It works well and is definitely nicer once you are used to it, than calling everything New or FunctionEx, and left wondering what to do when you rev the interface again.  Once you solve making 3 versions of an interface work cleanly, nice it should be a good system.

Making all the modules versioned in some way would probably be ideal. The way linux shared libraries are linked could be used as a model, just make the 'friendly unversioned' module name an alias of some sort to the latest version of the library.  Any code needing the older version can specify it explicitly.  An approach like this would need to be done within D, as symbol links are a problem for some platforms (though at least its possible on windows these days).

September 08, 2011
Christophe wrote:

>> It is not. But there is currently no nice way to express a set of orthogonal flags.
> Well, you could use an array of flags ? Oh, wait, that is precisely
what
> "r", "w", "rw" would be.
> Another option is to use the power of typesafe variadic functions:
> 
> enum Mode :char { read, write }
> File fOpen(string filename, Mode[]...);
> 
> auto file = fOpen("test.txt", Mode.read, Mode.write);

I like the variadic version most. Another alternative
would be to use a extra struct for flags, that
supports OR'ing them in a better way than plain
enum do. Maybe we can get some inspiration from
http://doc.qt.nokia.com/4.7/qflags.html

I'd like to add, that if we once get a good IDE for D,
it won't be able to show me possible values of the mode
parameter, if its type is just string.

And files may be not the only part of phobos that will
need flags. In the end, there should be a solution that
works even though the API and possible values are not
known from C.

September 08, 2011
On Wed, 07 Sep 2011 03:27:43 -0400, Jacob Carlborg <doob@me.com> wrote:

> On 2011-09-06 19:39, Steven Schveighoffer wrote:
>>
>> I like enums in terms of writing code that processes them, but in terms
>> of calling functions with them, I mean look at a sample fstream
>> constructor in C++:
>>
>> fstream ifs("filename.txt", ios_base::in | ios_base::out);
>>
>> vs.
>>
>> File("filename.txt", "r+"); // or "rw"
>>
>> There's just no way you can think "rw" is less descriptive or
>> understandable than ios_base::in | ios_base::out.
>>
>> -Steve
>
> But "r+" is. And that's what I assume will be used when I see a file opening function taking a string "mode" parameter. But if you say that "rw" can/will be used instead than that's better.
>

Yes, I'll try to add "rw" and maybe some other letter combinations that make sense in my next version.

But I think we still have to support "r+", even though it's esoteric, because too much existing code already does this, and to not support it would leave silently compiling bugs.

-Steve