Re: DIP 1015--Deprecation of Implicit Conversion of Int. & Char. Literals to bool--Formal Assement

2018-11-14 Thread Neia Neutuladh via Digitalmars-d-announce
On Wed, 14 Nov 2018 13:40:46 -0500, Steven Schveighoffer wrote:
> You don't think this is confusing?
> 
> enum A : int {
>  val
> }
> 
> A a;
> foo(a); // error: be more specific
> int x = a;
> foo(x); // Sure

I find this confusing:

void foo(int i) {}
void foo(ubyte b) {}
enum A : int { val = 0 }
foo(A.val);  // calls foo(ubyte)
A a = A.val;
foo(a);  // calls foo(int)

If it instead produced an error, the error would look like:

Error: foo called with argument types (E) matches both:
example.d(1): foo(int i)
and:
example.d(2): foo(ubyte i)

Or else:

Error: none of the overloads of foo are callable using
argument types (A), candidates are:
example.d(1): foo(int i)
example.d(2): foo(ubyte i)

These aren't the intuitively obvious thing to me, but they're not going to 
surprise me by calling the wrong function, and there are obvious ways to 
make the code work as I want. Of the two, I'd prefer the former.

The intuitively obvious thing for me is:

* Don't use VRP to select an overload. Only use it if there's only one 
candidate with the right number of arguments.
* Don't use VRP if the argument is a ctor, cast expression, or symbol 
expression referring to a non-builtin. Maybe disallow with builtins.
* Don't use VRP if the argument is a literal with explicitly indicated type 
(0UL shouldn't match to byte, for instance).

I think this would make things more as most people expect:

foo(A.val);  // A -> int, but no A -> byte; calls foo(int)
foo(0);  // errors (currently calls foo(int))
foo(0L); // errors (currently calls foo(ubyte))
foo(cast(ulong)0);  // errors (currently calls foo(ubyte))

And when there's only one overload:

void bar(byte b) {}
bar(A.val);  // errors; can't convert A -> byte
bar(0);  // type any-number and fits within byte, so should work
bar(0UL);// errors; explicit incorrect type
bar(0UL & 0x1F);// bitwise and expression can do VRP
bar("foo".length);  // length is a builtin; maybe do VRP?
bar(byte.sizeof);   // sizeof is a builtin; maybe do VRP?


Re: DIP 1015--Deprecation of Implicit Conversion of Int. & Char. Literals to bool--Formal Assement

2018-11-14 Thread Rubn via Digitalmars-d-announce
On Wednesday, 14 November 2018 at 02:45:38 UTC, Walter Bright 
wrote:

On 11/13/2018 3:29 PM, Rubn wrote:
> enum A : int { a = 127 }

`a` is a manifest constant of type `A` with a value of `127`.

Remember that `A` is not an `int`. It is implicitly convertible 
to an integer type that its value will fit in (Value Range 
Propagation). Other languages do not have VRP, so expectations 
from how those languages behave do not apply to D. VRP is a 
nice feature, it is why:


enum s = 100; // typed as int
enum t = 300; // also typed as int
ubyte u = s + 50; // works, no cast required,
  // although the type is implicitly 
converted

ubyte v = t + 50; // fails

In your articles, it is crucial to understand the difference 
between a manifest constant of type `int` and one of type `A`.


At least can you understand where the problem lies? If you have 
code like this:


foo(Enum.value);

Then it gets changed:

// ops might be calling a different function now
foo(runtimeCond ? Enum.value : Enum.otherValue);

Or how about if we just add another enum to our list:

enum Enum : int {
// ...
// add new enum here, shifting the values down
value,  // 126 -> 127
otherValue, // 127 -> 128 - Ops now we are calling a 
different function ~somewhere~

// ...
}

From your implementation perspective I can see why it is a good 
thing. But from my user's perspective this just screams 
unreliable chaotic mess, even in the most trivial examples.


What D does is only suitable for the absolute most trivial 
example:


enum int s = 100;
ubyte v = s; // ok no cast required

But even just a slightly more trivial example like we have now, 
and it falls apart:


enum int s = 100;

void foo(int);
void foo(byte);

foo(s); // Not suitable for determining overloads
// though is good for variable initialization

Not one's really asking to add another layer to anything. Merely 
to not treat named enum types as if they are just constants like 
anonymous enums.


ubyte a = Enum.value; // this is ok
foo(Enum.value);  // this needs to be x1000 more reliable



Re: DIP 1015--Deprecation of Implicit Conversion of Int. & Char. Literals to bool--Formal Assement

2018-11-14 Thread H. S. Teoh via Digitalmars-d-announce
On Wed, Nov 14, 2018 at 06:59:30PM +, Carl Sturtivant via 
Digitalmars-d-announce wrote:
> On Monday, 12 November 2018 at 10:05:09 UTC, Jonathan M Davis wrote:
> > *sigh* Well, I guess that's the core issue right there. A lot of us
> > would strongly disagree with the idea that bool is an integral type
> > and consider code that treats it as such as inviting bugs. We _want_
> > bool to be considered as being completely distinct from integer
> > types. The fact that you can ever pass 0 or 1 to a function that
> > accepts bool without a cast is a problem in and of itself.

+1.

Honestly, I think 'bool' as understood by Walter & Andrei ought to be
renamed to 'bit', i.e., a numerical, rather than logical, value.

Of course, that still doesn't address the conceptually awkward behaviour
of && and || returning a numerical value rather than a logical
true/false state.

The crux of the issue is whether we look at it from an implementation
POV, or from a conceptual POV.  Since there's a trivial 1-to-1 mapping
from a logical true/false state to a binary digit, it's tempting to
conflate the two, but they are actually two different things. It just so
happens that in D, a true/false state is *implemented* as a binary value
of 0 or 1.  Hence, if you think of it from an implementation POV, it
sort of makes sense to treat it as a numerical entity, since after all,
at the implementation level it's just a binary digit, a numerical
entity. However, if you look at it from a conceptual POV, the mapping
true=>1, false=>0 is an arbitrary one, and nothing about the truth
values true/false entail an ability to operate on them as numerical
values, much less promotion to multi-bit binary numbers like int.

I argue that viewing it from an implementation POV is a leaky
abstraction, whereas enforcing the distinction of bool from integral
types is more encapsulated -- because it hides away the implementation
detail that a truth value is implemented as a binary digit.

It's a similar situation with char vs. ubyte: if we look at it from an
implementation point of view, there is no need for the existence of char
at all, since at the implementation level it's not any different from a
ubyte.  But clearly, it is useful to distinguish between them, since
otherwise why would Walter & Andrei have introduced distinct types for
them in the first place?  The usefulness is that we can define char to
be a UTF-8 code unit, with a different .init value, and this distinction
lets the compiler catch potentially incorrect usages of the types in
user code.  (Unfortunately, even here there's a fly in the ointment that
char also implicitly converts to int -- again you see the symptoms of
viewing things from an implementation POV, and the trouble that results,
such as the wrong overload being invoked when you pass a char literal
that no-thanks to VRP magically becomes an integral value.)


> > But it doesn't really surprise me that Walter doesn't agree on that
> > point, since he's never agreed on that point, though I was hoping
> > that this DIP was convincing enough, and its failure is certainly
> > disappointing.

I am also disappointed.  One of the reasons I like D so much is its
powerful abstraction mechanisms, and the ability of user types to behave
(almost) like built-in types.  This conflation of bool with its
implementation as a binary digit seems to be antithetical to abstraction
and encapsulation, and frankly does not leave a good taste in the mouth.
(Though I will concede that it's a minor enough point that it wouldn't
be grounds for deserting D. But still, it does leave a bad taste in the
mouth.)


> I'm at a loss to see any significant advantage to having bool as a
> part of the language itself if it isn't deliberately isolated from
> `integral types`.

Same thing with implicit conversion to/from char types and integral
types.  I understand the historical / legacy reasons behind both cases,
but I have to say it's rather disappointing from a modern programming
language design point of view.


T

-- 
Written on the window of a clothing store: No shirt, no shoes, no service.


Re: DIP 1015--Deprecation of Implicit Conversion of Int. & Char. Literals to bool--Formal Assement

2018-11-14 Thread 12345swordy via Digitalmars-d-announce
On Wednesday, 14 November 2018 at 18:11:59 UTC, Neia Neutuladh 
wrote:

On Tue, 13 Nov 2018 20:27:05 -0800, Walter Bright wrote:
There have been various attempts over the years to "fix" 
various things in the D matching system by adding "just one 
more" match level.


I kind of feel like, if something would be confusing like this, 
maybe the compiler shouldn't be making an automatic decision. 
Not "just one more" match level, but just...don't match. If 
there are multiple matching overloads, just error out. Don't 
try to be clever and surprise people, just tell the user to be 
more explicit.


That type of behavior is best left to the programmer defining the 
public interface.


-Alex


Re: DIP 1015--Deprecation of Implicit Conversion of Int. & Char. Literals to bool--Formal Assement

2018-11-14 Thread Carl Sturtivant via Digitalmars-d-announce
On Monday, 12 November 2018 at 10:05:09 UTC, Jonathan M Davis 
wrote:
*sigh* Well, I guess that's the core issue right there. A lot 
of us would strongly disagree with the idea that bool is an 
integral type and consider code that treats it as such as 
inviting bugs. We _want_ bool to be considered as being 
completely distinct from integer types. The fact that you can 
ever pass 0 or 1 to a function that accepts bool without a cast 
is a problem in and of itself. But it doesn't really surprise 
me that Walter doesn't agree on that point, since he's never 
agreed on that point, though I was hoping that this DIP was 
convincing enough, and its failure is certainly disappointing.


I'm at a loss to see any significant advantage to having bool as 
a part of the language itself if it isn't deliberately isolated 
from `integral types`.


Re: DIP 1015--Deprecation of Implicit Conversion of Int. & Char. Literals to bool--Formal Assement

2018-11-14 Thread Steven Schveighoffer via Digitalmars-d-announce

On 11/14/18 1:11 PM, Neia Neutuladh wrote:

On Tue, 13 Nov 2018 20:27:05 -0800, Walter Bright wrote:

There have been various attempts over the years to "fix" various things
in the D matching system by adding "just one more" match level.


I kind of feel like, if something would be confusing like this, maybe the
compiler shouldn't be making an automatic decision. Not "just one more"
match level, but just...don't match. If there are multiple matching
overloads, just error out. Don't try to be clever and surprise people,
just tell the user to be more explicit.



You don't think this is confusing?

enum A : int
{
val
}

A a;
foo(a); // error: be more specific
int x = a;
foo(x); // Sure

-Steve


Re: DIP 1015--Deprecation of Implicit Conversion of Int. & Char. Literals to bool--Formal Assement

2018-11-14 Thread Neia Neutuladh via Digitalmars-d-announce
On Tue, 13 Nov 2018 20:27:05 -0800, Walter Bright wrote:
> There have been various attempts over the years to "fix" various things
> in the D matching system by adding "just one more" match level.

I kind of feel like, if something would be confusing like this, maybe the 
compiler shouldn't be making an automatic decision. Not "just one more" 
match level, but just...don't match. If there are multiple matching 
overloads, just error out. Don't try to be clever and surprise people, 
just tell the user to be more explicit.


Re: DIP 1015--Deprecation of Implicit Conversion of Int. & Char. Literals to bool--Formal Assement

2018-11-14 Thread Neia Neutuladh via Digitalmars-d-announce
On Wed, 14 Nov 2018 12:09:33 +0100, Jacob Carlborg wrote:
> What is ": int" doing, only specifying the size?

It specifies the type to match for overloading when the compiler isn't 
required by the language to constant-fold the value.


Re: DIP 1015--Deprecation of Implicit Conversion of Int. & Char. Literals to bool--Formal Assement

2018-11-14 Thread Jacob Carlborg via Digitalmars-d-announce

On 2018-11-14 03:45, Walter Bright wrote:

On 11/13/2018 3:29 PM, Rubn wrote:

enum : int { a = 127 }


To reiterate, this does not create an anonymous enum type. 'a' is typed
as 'int'. Technically,

`a` is a manifest constant of type `int` with a value of `127`.

 > enum A : int { a = 127 }

`a` is a manifest constant of type `A` with a value of `127`.

Remember that `A` is not an `int`.


What is ": int" doing, only specifying the size?

--
/Jacob Carlborg


Re: Profiling DMD's Compilation Time with dmdprof

2018-11-14 Thread Vladimir Panteleev via Digitalmars-d-announce

On Thursday, 8 November 2018 at 07:54:56 UTC, Manu wrote:
And all builds are release builds... what good is a debug 
build? DMD
is unbelievably slow in debug. If it wasn't already slow 
enough... if
I try and build with a debug build, it takes closer to 5 
minutes.


I just got to try a side-by-side comparison of a release and 
debug (as in `make -f posix.mak BUILD=debug`) build of DMD.


With a 25KLOC project, the debug build is only 36% slower.

Maybe the experience on Windows / Visual Studio is very different.