March 14, 2014
On Fri, 14 Mar 2014 10:11:25 -0400, Ethan <gooberman@gmail.com> wrote:

> On Friday, 14 March 2014 at 14:02:06 UTC, Steven Schveighoffer
> wrote:
>>
>> And for that point, your demonstration has failed :)
>
> It's an extraordinarily simple use case, but it is still quite a
> common pattern in C++ defines, ie:
>
> #ifdef _DEBUG
> #define FEATUREA
> #define FEATUREB
> #define FEATUREC
> #else
> #define FEATUREB
> #define FEATUREC
> #endif
>
> #ifdef FEATUREB
> ...
> #endif

No, not really, there was no else in the version. It's when you have two different versions that may trigger the same definition.

#if defined(MODEA) || defined(MODEB)
#define FEATUREA
#define FEATUREB
#endif

In D, this is:

version(MODEA) version = USEFEATUREAANDB;
version(MODEB) version = USEFEATUREAANDB;

...

version(USEFEATUREAANDB) // imagine reading this first, and wondering what causes it to compile.
{
   version = FEATUREA;
   version = FEATUREB;
}

It's the equivalent of this in C:

#ifdef MODEA
#define USEFEATUREAANDB
#endif
#ifdef MODEB
#define USEFEATUREAANDB
#endif

...

#ifdef USEFEATUREAANDB
#define FEATUREA
#define FEATUREB
#endif

Yes, there are real world examples where the lack of logical or makes things difficult to read. It's not all about versioning based on OS or boolean flags.

-Steve
March 14, 2014
On Fri, 14 Mar 2014 05:58:28 -0400, Regan Heath <regan@netmail.co.nz> wrote:

> On Fri, 14 Mar 2014 08:51:05 -0000, 1100110 <0b1100110@gmail.com> wrote:
>>
>>      version (X86 || X86_64 || PPC || PPC64 || ARM || AArch64)
>>      {
>>          enum RTLD_LAZY = 0x00001;
>>          enum RTLD_NOW = 0x00002;
>>          enum RTLD_GLOBAL = 0x00100;
>>          enum RTLD_LOCAL = 0x00000;
>>      }
>>      else version (MIPS32)
>>      {
>>          enum RTLD_LAZY = 0x0001;
>>          enum RTLD_NOW = 0x0002;
>>          enum RTLD_GLOBAL = 0x0004;
>>          enum RTLD_LOCAL = 0;
>>      }
>
> Walter's point, I believe, is that you should define a meaningful version identifier for each specific case, and that this is "better" because then you're less concerned about where it's supported and more concerned with what it is which is/isn't supported.
>
> Maintenance is very slightly better too, IMO, because you add/remove/alter a complete line rather than editing a set of || && etc which can in some cases be a little confusing.  Basically, the chance of an error is very slightly lower.
>
> For example, either this:
>
> version(X86) version = MeaningfulVersion
> version(X86_64) version = MeaningfulVersion
> version(PPC) version = MeaningfulVersion
> version(PPC64) version = MeaningfulVersion
> version(ARM) version = MeaningfulVersion
> version(AArch64) version = MeaningfulVersion
>
> version(MeaningfulVersion)
> {
> }
> else version (MIPS32)
> {
> }
>
> or this:
>
> version (X86) version = MeaningfulVersion
> version (X86_64) version = MeaningfulVersion
> version (PPC) version = MeaningfulVersion
> version (PPC64) version = MeaningfulVersion
> version (ARM) version = MeaningfulVersion
> version (AArch64) version = MeaningfulVersion
>
> version (MIPS32) version = OtherMeaningfulVersion
>
> version (MeaningfulVersion)
> {
> }
> else version (OtherMeaningfulVersion)
> {
> }
>
> Regan

I think the point we are trying to make is, what if MeaningfulVersion does not exist? That is, how do you attribute a name to those flags?

Then it becomes a "where's waldo" to see if your particular platform defines the arbitrary name you had to choose.

There's not always an easy to define symbol for everything.

BTW, && does not present the same problem, because there isn't much difference between:

version(x && y)
version(x) version(y)

But there is a huge difference between

version(x || y)

version(x) version = somearbitrarysymbol;
version(y) version = somearbitrarysymbol;
version(somearbitrarysymbol)

-Steve
March 14, 2014
On 3/14/2014 10:21 PM, Regan Heath wrote:
> On Fri, 14 Mar 2014 10:22:40 -0000, 1100110 <0b1100110@gmail.com> wrote:
>
>> On 3/14/14, 4:58, Regan Heath wrote:
>>>
>>> Maintenance is very slightly better too, IMO, because you
>>> add/remove/alter a complete line rather than editing a set of || && etc
>>> which can in some cases be a little confusing.  Basically, the chance of
>>> an error is very slightly lower.
>>>
>>> For example, either this:
>>>
>>> version(X86) version = MeaningfulVersion
>>> version(X86_64) version = MeaningfulVersion
>>> version(PPC) version = MeaningfulVersion
>>> version(PPC64) version = MeaningfulVersion
>>> version(ARM) version = MeaningfulVersion
>>> version(AArch64) version = MeaningfulVersion
>>>
>>> version(MeaningfulVersion)
>>> {
>>> }
>>> else version (MIPS32)
>>> {
>>> }
>>>
>>> or this:
>>>
>>> version (X86) version = MeaningfulVersion
>>> version (X86_64) version = MeaningfulVersion
>>> version (PPC) version = MeaningfulVersion
>>> version (PPC64) version = MeaningfulVersion
>>> version (ARM) version = MeaningfulVersion
>>> version (AArch64) version = MeaningfulVersion
>>>
>>> version (MIPS32) version = OtherMeaningfulVersion
>>>
>>> version (MeaningfulVersion)
>>> {
>>> }
>>> else version (OtherMeaningfulVersion)
>>> {
>>> }
>>>
>>> Regan
>>>
>>
>>
>> ...I can't even begin to describe how much more readable the OR'd
>> version is.
>
> It's shorter, but shorter does not mean more "readable".. if by readable
> you mean include the ability to communicate intent etc.  Add to that,
> that readable is just one metric.
>
> Walter's point is that the above pattern is better at communicating
> intent, clarifying your logic, and making the resulting version
> statements easier to understand (aka "more readable")
>
> R
>

For me, the issue is that this has to go in *every* module that needs MeaningfulVersion and OtherMeaningfulVersion to be defined. That's a lot more points to track than a single line of ORed versions in each module.

When I do need something like this, I just define some manifest constants in a config module, import that everywhere, and use static if. But that feels very much like the workaround it is. I would much prefer to have boolean versions. The bottom line is that I'm doing exactly what Walter apparently doesn't want me to do anyway, just with the added annoyance of importing an extra module to get it done.
March 14, 2014
On Fri, 14 Mar 2014 10:00:23 -0400, bearophile <bearophileHUGS@lycos.com> wrote:

> Steven Schveighoffer:
>
>> I think it may be best to introduce a new array property:
>>
>> dest.slength = src.length; // same as dest.length = src.length, but follows D1 rules (slength = stomp length)
>>
>> If you use slicing (I'm assuming you do), then appending would have to become a function/member instead of ~=.
>>
>> I can help write those if you want.
>
> Eventually the D1 legacy will go away, so probably it's better to introduce something that later can be removed safely. So instead of "slength" it's better a name like "__slength", to allow its usage only if you compile with the "-d" compile switch (that activates deprecated features) and instead of a built-in array property as "length" it could be better (if possible) to make it a function in the object module as assumeSafeAppend.

I hope you understand that I was not recommending adding this to druntime or phobos. This is not a typical requirement.

Anyone starting with D2 code would use something other than straight array-slices to do this kind of work.

-Steve
March 14, 2014
On 3/14/14, 8:21, Regan Heath wrote:
> On Fri, 14 Mar 2014 10:22:40 -0000, 1100110 <0b1100110@gmail.com> wrote:
>
>> On 3/14/14, 4:58, Regan Heath wrote:
>>>
>>> Maintenance is very slightly better too, IMO, because you
>>> add/remove/alter a complete line rather than editing a set of || && etc
>>> which can in some cases be a little confusing.  Basically, the chance of
>>> an error is very slightly lower.
>>>
>>> For example, either this:
>>>
>>> version(X86) version = MeaningfulVersion
>>> version(X86_64) version = MeaningfulVersion
>>> version(PPC) version = MeaningfulVersion
>>> version(PPC64) version = MeaningfulVersion
>>> version(ARM) version = MeaningfulVersion
>>> version(AArch64) version = MeaningfulVersion
>>>
>>> version(MeaningfulVersion)
>>> {
>>> }
>>> else version (MIPS32)
>>> {
>>> }
>>>
>>> or this:
>>>
>>> version (X86) version = MeaningfulVersion
>>> version (X86_64) version = MeaningfulVersion
>>> version (PPC) version = MeaningfulVersion
>>> version (PPC64) version = MeaningfulVersion
>>> version (ARM) version = MeanigfulVersion
>>> version (AArch64) version = MeaningfulVersion
>>>
>>> version (MIPS32) version = OtherMeaningfulVersion
>>>
>>> version (MeaningfulVersion)
>>> {
>>> }
>>> else version (OtherMeaningfulVersion)
>>> {
>>> }
>>>
>>> Regan
>>>
>>
>>
>> ...I can't even begin to describe how much more readable the OR'd
>> version is.
>
> It's shorter, but shorter does not mean more "readable".. if by readable
> you mean include the ability to communicate intent etc.  Add to that,
> that readable is just one metric.
>
> Walter's point is that the above pattern is better at communicating
> intent, clarifying your logic, and making the resulting version
> statements easier to understand (aka "more readable")
>
> R
>


That's an awful lot of typo opportunities....   Quick!  which one did I change!?
March 14, 2014
On Friday, 14 March 2014 at 14:26:20 UTC, Steven Schveighoffer
wrote:
>
> No, not really, there was no else in the version.
>

I'm aware of that, and you missed the point. There's no need to
get so hung up on Walter's specific example when the pattern he
suggests you follow is widely used in analagous situations.
March 14, 2014
On 3/14/14, 4:37 AM, Daniel Murphy wrote:
> "Walter Bright"  wrote in message news:lfu74a$8cr$1@digitalmars.com...
>
>> > No, it doesn't, because it is not usable if C introduces any virtual
>> > methods.
>>
>> That's what the !final storage class is for.
>
> My mistake, I forgot you'd said you were in favor of this.  Being able
> to 'escape' final certainly gets us most of the way there.
>
> !final is really rather hideous though.

A few possibilities discussed around here:

!final
~final
final(false)
@disable final

I've had an epiphany literally a few seconds ago that "final(false)" has the advantage of being generalizable to "final(bool)" taking any CTFE-able Boolean.

On occasion I needed a computed qualifier (I think there's code in Phobos like that) and the only way I could do it was through ugly code duplication or odd mixin-generated code. Allowing computed qualifiers/attributes would be a very elegant and general approach, and plays beautifully into the strength of D and our current investment in Boolean compile-time predicates.


Andrei

March 14, 2014
On Friday, 14 March 2014 at 15:17:08 UTC, Andrei Alexandrescu wrote:
> I've had an epiphany literally a few seconds ago that "final(false)" has the advantage of being generalizable to "final(bool)" taking any CTFE-able Boolean.
>
> On occasion I needed a computed qualifier (I think there's code in Phobos like that) and the only way I could do it was through ugly code duplication or odd mixin-generated code. Allowing computed qualifiers/attributes would be a very elegant and general approach, and plays beautifully into the strength of D and our current investment in Boolean compile-time predicates.
>
>
> Andrei

+1 for this approach. It's also another step towards perfect forwarding without using string mixin declarations.
March 14, 2014
On Friday, 14 March 2014 at 15:17:08 UTC, Andrei Alexandrescu wrote:
> On 3/14/14, 4:37 AM, Daniel Murphy wrote:
>> "Walter Bright"  wrote in message news:lfu74a$8cr$1@digitalmars.com...
>>
>>> > No, it doesn't, because it is not usable if C introduces any virtual
>>> > methods.
>>>
>>> That's what the !final storage class is for.
>>
>> My mistake, I forgot you'd said you were in favor of this.  Being able
>> to 'escape' final certainly gets us most of the way there.
>>
>> !final is really rather hideous though.
>
> A few possibilities discussed around here:
>
> !final
> ~final
> final(false)
> @disable final
>
> I've had an epiphany literally a few seconds ago that "final(false)" has the advantage of being generalizable to "final(bool)" taking any CTFE-able Boolean.
>
> On occasion I needed a computed qualifier (I think there's code in Phobos like that) and the only way I could do it was through ugly code duplication or odd mixin-generated code. Allowing computed qualifiers/attributes would be a very elegant and general approach, and plays beautifully into the strength of D and our current investment in Boolean compile-time predicates.
>
>
> Andrei

Great idea.
March 14, 2014
On Fri, 14 Mar 2014 11:15:39 -0400, Ethan <gooberman@gmail.com> wrote:

> On Friday, 14 March 2014 at 14:26:20 UTC, Steven Schveighoffer
> wrote:
>>
>> No, not really, there was no else in the version.
>>
>
> I'm aware of that, and you missed the point. There's no need to
> get so hung up on Walter's specific example when the pattern he
> suggests you follow is widely used in analagous situations.

I'm not hung up on his example, in fact, I said in many cases, factoring into a common version identifier is a good thing.

But it's not always the answer, and removing boolean OR does not make things better in all cases.

I have no problems with a version/else statement, I don't know why you brought it up, that works fine for me.

-Steve