January 16, 2019
On Wednesday, 16 January 2019 at 06:43:59 UTC, Walter Bright wrote:
> > "Never" makes a lot more sense.
>
> Inventing new jargon for established terms is worse. Established jargon gives the reader a certain level of confidence when established terms are used correctly in that the reader understands the text and that the writer understands the text.
>
> The "Bottom" type appears in books on type theory, like "Types and Programming Languages" by Pierce. "Never" does not, leaving the reader wondering what relation it might have to a bottom type.

Since Rust already uses `never`, it won't be inventing new jargon. We can choose either of these two based on our taste.

But also, your DIP needn't make that choice. Since the type is defined with `typeof` instead of it's own keyword, anyone can alias the type however he wants. The terminology can be left to evolve naturally, without needing to dictate a term for the type.


January 16, 2019
On 1/16/2019 2:18 AM, Dukc wrote:
> But also, your DIP needn't make that choice. Since the type is defined with `typeof` instead of it's own keyword, anyone can alias the type however he wants. The terminology can be left to evolve naturally, without needing to dictate a term for the type.

Exactly why it was done that way. It was a way to avoid needing a keyword, much like `string` is an alias, not a keyword.

The name was never the point of the DIP.
January 16, 2019
On Wednesday, 16 January 2019 at 04:20:42 UTC, aliak wrote:
> On Tuesday, 15 January 2019 at 22:44:56 UTC, Johan Engelen wrote:
>> The link does not really have answers that explain the use of a bottom type in a practical imperative language, beyond that it signifies `noreturn`.
>> The question we have is whether there is a compelling use for "bottom". I'd like to see a real code use case, besides signifying `noreturn` (trivial).
>
> A very practical use case is with error code paths where you end up asserting/exiting the program, something like:
>
> int f(int i) {
>     if (i) {
>         exit(0);
>     } else {
>         return 0;
>     }
> }

This is just another example of using the bottom type to signify `noreturn`, which is trivially done with an attribute and doesn't need a new type. I'd like to see _other_ practical uses of the bottom type.

-Johan

January 16, 2019
On Wed, 16 Jan 2019 08:09:39 +0000, Johannes Loher wrote:
> This is not completely accurate. Nothing actually is the bottom type in Kotlin in the sense that it DOES implicitly convert to any type. E.g.

Thank you for the correction.

> I actually also think it is correct to do the same for `void`, but `void` should even a single value and thus it should be default constructible and have an `init` property. As I mentioned earlier in this thread, this would make `void` a proper unit type, drawing a clear line between `Tbottom` and `void`. It is however very complicated to get this to work with C-interoperability.

I very much agree with void being a proper type. It's an annoying special case for generic code as is.
January 16, 2019
On Wednesday, 16 January 2019 at 10:25:21 UTC, Walter Bright wrote:
> The name was never the point of the DIP.

Agreed, the type name is bikeshedding.

What is your answer to the rebuttal, common in both this thread and the previous thread, that a bottom type has no practical use justifying the complexity (and probable corner cases) it would add to the type system?

In particular, I think this question from Jonathan Marler really needs to be answered before the DIP moves forward:

> What else does the new bottom type give us?  And be sure to distinguish between things that only require "no-return" functions and things that require a bottom type.  If they only require "no-return" functions, then they are not rationale for adding a bottom type.

I mean, this is clearly the biggest point of contention. If the DIP is forwarded and implemented without addressing it (like it has been so far), then it's basically saying that the DIP process is a formality and the gathered feedback doesn't matter.
January 16, 2019
On Wednesday, 16 January 2019 at 11:40:36 UTC, Olivier FAURE wrote:
> On Wednesday, 16 January 2019 at 10:25:21 UTC, Walter Bright wrote:

>
> I mean, this is clearly the biggest point of contention. If the DIP is forwarded and implemented without addressing it (like it has been so far), then it's basically saying that the DIP process is a formality and the gathered feedback doesn't matter.

I guess I need to edit the procedure document to clarify this. The DIP process is not just a formality and is working as intended.

The purpose of the review process is to help get the DIP in shape for the formal assessment by Walter and Andrei, to help ensure it is as thorough as possible. It is no way intended to be a referendum on whether a DIP should be implemented. In the formal assessment, Walter and Andrei will take any unaddressed feedback and objections into account, but the final decision rests with them.

Of course, in this case, it's a bit different since Walter is the DIP author. Your feedback is going directly to him. If you happen to persuade him to come around to your point of view, congratulations. But again, please don't view this referendum.
January 16, 2019
On Wednesday, 16 January 2019 at 12:11:36 UTC, Mike Parker wrote:

> congratulations. But again, please don't view this referendum.

"as a referendum"

And I should add, if anyone disagrees and wants to reply to me, please open another thread. I don't want to pollute the review thread with a debate on the merits of the DIP process. Thanks!
January 16, 2019
On Wednesday, 16 January 2019 at 09:43:24 UTC, Dukc wrote:
> On Wednesday, 16 January 2019 at 08:47:48 UTC, Johannes Loher wrote:
>> On Tuesday, 15 January 2019 at 18:51:13 UTC, Johannes Loher ```
>> alias void = Tbottom*;
>> ```
>
> I believe you meant `enum null = typeof(Tbottom*).init;`

No, I actually meant it exactly as I wrote it. The reasoning is the following: If we were to make `void` a proper unit type, it needs to be a type with exactly one value. We could choose any type we want for this, as long as it only has one value. E.g. `struct A {}` could be a candidate for such a type as any two instances of it are equal. However, `Tbottom*` is also a type with only one value: `null`. To me it seemed like the canonical choice for defining `void`.

There might actually be reasons not to do this. As I mentioned, Kotlin is going another route. `Unit` and `Nothing?` are different types in Kotlin, although they both can hold exactly one value: `Nothing?` can only hold `null` and `Unit` only has the value `Unit`. I don't think their decision to separate those types is arbitrary. In particular, `Nothing?` is a subtype of all optional types in Kotlin. Maybe there are some bad implications of making the unit type a subtype of all optional types, I don't know. The analogue in D (if `void` is defined to be `Tbottom*` would be that `void` is a subtype of all pointer types, which might seem weird.

What you are describing is actually completely orthogonal to what I suggested. Even if `void` is defined in some other way and even if we keep it like it is (instead of making it a proper unit type), we can still define `null` to be the only value of `Tbottom*`. Now that you suggested it, it also really makes sense to do this in my opinion. (It would allow us to get rid of `null` as a builtin symbol)

January 16, 2019
On 1/16/2019 3:40 AM, Olivier FAURE wrote:
> What is your answer to the rebuttal, common in both this thread and the previous thread, that a bottom type has no practical use justifying the complexity (and probable corner cases) it would add to the type system?

That indeed is the correct question.

The thing is, I know little about formal type theory. As far as I can tell, nobody in this community does either, aside from Timon Gehr.

There are notions in mathematics and programming that seem like nonsense, but exist as important boundary conditions:

* zero
* infinity
* black hole objects
* white hole objects
* identity functions
* top type (represents every value, like D's "Object" root type)
* bottom type (represents no value)

Civilization had arithmetic long before zero was discovered. Today, we can't imagine doing math without 0. Infinity came along later, and its usefulness can be seen as an indispensable foundation of calculus.

C++ muddled along for decades with an identity function being impossible to write. Although an identity function seems pointless, it went unrecognized for a long time that this was causing all sorts of problems with templates.

Back to the bottom type. C's ability to manipulate types is so primitive nobody misses type calculus. But D can do type calculus, and I worry that the lack of a bottom type, far from creating corner cases, causes corner cases and awkward problems analogous to what the lack of an identity function causes.

The trouble is, I don't know enough about type theory to know if this is the case or not. I only know analogies to problems other systems have when the boundary cases are not expressible.

An example of an awkward corner case caused by lack of a bottom type:

   @noreturn int betty();

How can it return an int yet not return? It makes no sense. And if one was doing type calculus on the return value of betty(), it would show up as 'int' and botch everything up. It'd be like substituting '5' in calculations that need a '0', but have no notion of '0'.

The trouble with 'void' as a bottom type is it is only half done. For example, 'void' functions are procedures, and certainly do return. A void* is certainly a pointer to something, not nothing. 'void' is the one with awkward corner cases, it's just we're so used to them we don't see them, like few C++ people recognized the identity function problem.

My trouble explaining the immediate value of a bottom type stems from my poor knowledge of type theory. Other languages aren't necessarily good role models here, as few language designers seem to know much about type calculus, either. I was hoping that someone who does understand it would help out!

(I.e. it's not just about functions that don't return. That's just an obvious benefit.)
January 16, 2019
On Wednesday, 16 January 2019 at 22:32:33 UTC, Walter Bright wrote:
> The trouble with 'void' as a bottom type is it is only half done. For example, 'void' functions are procedures, and certainly do return. A void* is certainly a pointer to something, not nothing. 'void' is the one with awkward corner cases, it's just we're so used to them we don't see them, like few C++ people recognized the identity function problem.

Isn't `void` in fact analogous to the TOP type? With a bit additional features, it could be used as one, as I understand it.