November 12, 2018
On Monday, 12 November 2018 at 21:29:20 UTC, Walter Bright wrote:

> I once worked with software that defined true as 0 and false as 1

OK, I got to know what language you were using at the time, because I am curious at what other oddities does it have.

-Alex
November 12, 2018
On 11/12/2018 11:28 AM, Adam D. Ruppe wrote:
> D used to have a `bit` type, waaaay back in the day. It was renamed to `bool` way back in D 0.148, released Feb 25, 2006.

D's old bit type was not a bool. It literally was a single bit, and an array of bits was packed into an int by the compiler.

It was abandoned because it caused more or less ugly problems with the type system, i.e. a <pointer to bit> required a phat pointer to represent it. A bit type is far better done as a library type.
November 12, 2018
On 11/12/2018 12:34 PM, Neia Neutuladh wrote:
> Tell me more about this "consistency".

int f(short s) { return 1; }
int f(int i) { return 2; }

enum : int { a = 0 }
enum A : int { a = 0 }

pragma (msg, f(a));   // calls f(int)
pragma (msg, f(A.a)); // calls f(short)

I.e. it's consistent.

Here's how it works:

f(a): `a` is a manifest constant of type `int`, and `int` is an exact match for f(int), and f(short) requires an implicit conversion. The exact match of f(int) is better.

f(A.a): `a` is an enum of type `A`. `A` gets implicitly converted to `int`. The `int` then gets exact match to f(int), and an implicit match to f(short). The sequence of conversions is folded into one according to:

    <implicit conversion> <exact>               => <implicit conversion>
    <implicit conversion> <implicit conversion> => <implicit conversion>

Both f(int) and f(short) match, because implicit conversions rank the same. To disambiguate, f(short) is pitted against f(int) using partial ordering rules,
which are:

    Can a short be used to call f(int)? Yes.
    Can an int be used to call f(short)? No.

So f(short) is selected, because the "Most Specialized" function is selected when there is an ambiguous match.

Note: the "most specialized" partial ordering rules are independent of the arguments being passed.

---

One could have <implicit conversion><exact> be treated as "better than" <implicit conversion><implicit conversion>, and it sounds like a good idea, but even C++, not known for simplicity, tried that and had to abandon it as nobody could figure it out once the code examples got beyond trivial examples.

November 12, 2018
On 11/12/2018 1:39 PM, 12345swordy wrote:
> OK, I got to know what language you were using at the time, because I am curious at what other oddities does it have.

I wish I could remember what it was. It was like 40 years ago :-)

November 13, 2018
On Monday, 12 November 2018 at 21:29:20 UTC, Walter Bright wrote:
> *snip*
>
> In my college daze I was learning programming alongside designing and building digital circuits, and later software for FPGAs and PLDs (ABEL). The notions of True, T, 1, !0 (from C and Asm), and +5V are all completely interchangeable in my mind.
>
> *snip*

Well if we're talking about code smell: I would regard any code that expects true to be the same as 1 a code smell (I've interacted with C++ code that uses integers instead of bools and it's annoying and hard to read).

There's a reason I use
const foo = boolValue ? otherValue : 0;
and not
const foo = otherValue * boolValue;
because it shows _intent_.

I think the rest of us would like to hear an actual justification for bool being an "integer" type.
November 13, 2018
On Monday, 12 November 2018 at 22:07:39 UTC, Walter Bright wrote:
> *snip*
> Both f(int) and f(short) match, because implicit conversions rank the same.
> To disambiguate, f(short) is pitted against f(int) using partial ordering rules,
> which are:
>
>    Can a short be used to call f(int)? Yes.
>    Can an int be used to call f(short)? No.
>
> So f(short) is selected, because the "Most Specialized" function is selected
> when there is an ambiguous match.
> Note: the "most specialized" partial ordering rules are independent of the arguments being passed.

Well frankly that's bad design. If I declare Foo as an int enum I (and any _reasonable_ programmer) would expect Foo to prefer the int overload.

Think of it this way, each enum can be thought of like this:

immutable struct EnumName(T) {
    T value;
    alias value this;
}

So, if a programmer declares an enum of type int (EnumName!int), the alias-this will convert the enum to an int. Thus, the programmer expects the value to implicitly
convert to an int; which is a _direct_ implicit conversion (IE: is weighed heavier than just an implicit conversion).

Regardless of what you believe, it is an inconsistent behavior to the programmer (IE: The person you should be considering as a language designer).

If this horrid design choice stays, this _will_ go down as a mistaken "feature" of the language that everyone has to account for otherwise it bites them (Example: C++ implicitly converting by default instead of requiring an implicit attribute).


If you really want this plaque in the language, at least make it not affect those that gave their enum a type. If you at least do that, someone can add it to DScanner to tell anyone that doesn't type their enum to expect illogical behavior.
November 13, 2018
On Mon, 12 Nov 2018 14:07:39 -0800, Walter Bright wrote:
>      <implicit conversion> <exact>               => <implicit
>      conversion>
>      <implicit conversion> <implicit conversion> => <implicit
>      conversion>

One confusion is from value range propagation / constant folding reaching past the static type information to yield a different result from what static typing alone would suggest. My intuition was that the compiler should prefer the declared type of the symbol when it's got a symbol with a declared type.

Like, A implicitly converts to int, and int doesn't implicitly convert to short, so an expression of type A shouldn't implicitly convert to short. And this is *generally* true, but when the compiler can use constant folding to get a literal value out of the expression, it does things I don't expect.

And this doesn't happen with structs with alias this, but I can't tell if that's an oversight or not, and there's no doubt some nuanced explanation of how things work, and it probably solves some edge cases to have it work differently...
November 13, 2018
On Tue, 13 Nov 2018 00:08:04 +0000, Isaac S. wrote:
> If you really want this plaque in the language, at least make it not affect those that gave their enum a type. If you at least do that, someone can add it to DScanner to tell anyone that doesn't type their enum to expect illogical behavior.

Unfortunately, dscanner only parses code. It can't tell you that your overload resolution depends on value range propagation on an enum value; that depends on semantic analysis. So it would have to aggressively warn you against using `enum Foo : some_int_type`.
November 13, 2018
On Tuesday, 13 November 2018 at 00:21:25 UTC, Neia Neutuladh wrote:
> On Tue, 13 Nov 2018 00:08:04 +0000, Isaac S. wrote:
>> If you really want this plaque in the language, at least make it not affect those that gave their enum a type. If you at least do that, someone can add it to DScanner to tell anyone that doesn't type their enum to expect illogical behavior.
>
> Unfortunately, dscanner only parses code. It can't tell you that your overload resolution depends on value range propagation on an enum value; that depends on semantic analysis. So it would have to aggressively warn you against using `enum Foo : some_int_type`.

Sorry if it wasn't clear, I meant that if `enum Foo : some_int_type` makes it so some_int_type is preferred (because it's a more direct conversion) DScanner could warn anyone that just does `enum Foo`.
November 13, 2018
On Tue, 13 Nov 2018 00:28:46 +0000, Isaac S. wrote:
> Sorry if it wasn't clear, I meant that if `enum Foo : some_int_type` makes it so some_int_type is preferred (because it's a more direct conversion) DScanner could warn anyone that just does `enum Foo`.

Sorry, I read too hastily and thought you meant relative to the status quo.