January 16, 2019
On Tuesday, 15 January 2019 at 21:39:08 UTC, Meta wrote:
> On Tuesday, 15 January 2019 at 10:08:28 UTC, ixid wrote:
>> Sorry to bikeshed but any name other than 'bottom' would be preferable, D may be the butt of the joke so to speak if code is full of this. There are plenty of synonyms.
>
> "never" is used in Rust, i.e., the never type. Scala and a few other languages use Nothing, and Haskell uses Void (not the same as `void` in C-family languages).

+1 for not using "bottom". It's really confusing to anyone who is not a language theory expert. "Never" makes a lot more sense.

Never is also used in Swift. Motivation from their proposal for a bottom type [0]:

"The best name for the standard library uninhabited type was a point of contention. Many of the names suggested by type theory literature or experience in functional programming circles are wanting:

* Void might have been mathematically appropriate, but alas has already been heavily confused with "unit" in C-derived circles.
* Names like Nothing, Nil, etc. have the potential to be confused with the nil value of Optional, or with returning Void.
* Type theory jargon like Bottom wouldn't be immediately understood by many users.

The first revision of this proposal suggested NoReturn, but in discussion, the alternative name Never was suggested, which was strongly preferred by most participants. Never properly implies the temporal aspect--this function returns never --and also generalizes well to other potential applications for an uninhabited type. For instance, if we gained the ability to support typed throws, then () throws<Never> -> Void would also clearly communicate a function that never throws."

[0] https://github.com/apple/swift-evolution/blob/master/proposals/0102-noreturn-bottom-type.md


January 16, 2019
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;
    }
}

D currently special cases assert(0) for that. But practically you can have function other than a special cased assert that never return. Without the bottom type I'd have to write "return make-up-a-number" and then if there's a bug in "exit" i could be returning make-up-a-number and using it and I'd never be the wiser.

January 16, 2019
On Wednesday, 16 January 2019 at 01:14:58 UTC, Nicholas Wilson wrote:
> Those can all be done by an attribute. So it comes down to a cost benefit analysis: the benefits they provide are the same, except the implementation of bottom is going to be much more costly.

Is it "much" more costly?

What about the benefit of not being able to write code like:

@noreturn int f() { ... } // wat?
January 16, 2019
On Wednesday, 16 January 2019 at 04:24:34 UTC, aliak wrote:
> On Wednesday, 16 January 2019 at 01:14:58 UTC, Nicholas Wilson wrote:
>> Those can all be done by an attribute. So it comes down to a cost benefit analysis: the benefits they provide are the same, except the implementation of bottom is going to be much more costly.
>
> Is it "much" more costly?
>
> What about the benefit of not being able to write code like:
>
> @noreturn int f() { ... } // wat?

Ooh and eventually getting a "top type"... ? Can't have a toptype attribute can you?
January 16, 2019
On Wednesday, 16 January 2019 at 04:24:34 UTC, aliak wrote:
> On Wednesday, 16 January 2019 at 01:14:58 UTC, Nicholas Wilson wrote:
>> Those can all be done by an attribute. So it comes down to a cost benefit analysis: the benefits they provide are the same, except the implementation of bottom is going to be much more costly.
>
> Is it "much" more costly?

Bottom, must be implemented in the compiler. Attributes exist _now_.

version (LDC)
    enum noreturn = ldc.attributes.llvmAttr("noreturn"));
else version (GDC)
    enum noreturn = gcc.attribute.attribute("noreturn"); // ?
else version (DigitalMars)
    enum noreturn;

This exhibits the documentation benefits on all compilers, and performance gains on the compilers that matter.

> What about the benefit of not being able to write code like:
>
> @noreturn int f() { ... } // wat?

Yes that is possible. Does it make sense to write? Of course not. We shouldn't be taking into considerations of people writing code like that when designing the language. `@noreturn void` is what people use in C/C++ I don't see why that wouldn't follow in D.

January 16, 2019
On Wednesday, 16 January 2019 at 04:33:08 UTC, Nicholas Wilson wrote:
> On Wednesday, 16 January 2019 at 04:24:34 UTC, aliak wrote:
>> On Wednesday, 16 January 2019 at 01:14:58 UTC, Nicholas Wilson wrote:
>>> Those can all be done by an attribute. So it comes down to a cost benefit analysis: the benefits they provide are the same, except the implementation of bottom is going to be much more costly.
>>
>> Is it "much" more costly?
>
> Bottom, must be implemented in the compiler. Attributes exist _now_.
>
> version (LDC)
>     enum noreturn = ldc.attributes.llvmAttr("noreturn"));
> else version (GDC)
>     enum noreturn = gcc.attribute.attribute("noreturn"); // ?
> else version (DigitalMars)
>     enum noreturn;
>
> This exhibits the documentation benefits on all compilers, and performance gains on the compilers that matter.
>
>> What about the benefit of not being able to write code like:
>>
>> @noreturn int f() { ... } // wat?
>
> Yes that is possible. Does it make sense to write? Of course not. We shouldn't be taking into considerations of people writing code like that when designing the language. `@noreturn void` is what people use in C/C++ I don't see why that wouldn't follow in D.

You'd have to take that in to consideration because you'd have to implement the logic to handle it though no? What would that logic be? Compiler error maybe ... 🤔 but then that's special casing in the compiler? (yuk). And I guess I just disagree with not taking how people would write code in to consideration.

A proper type gives you everything the attribute does, and has the advantage of not allowing for weird code, and makes the type system more solid, and provides future top-type possibilities. It sounds like the only argument for an attribute is "it's a bit quicker to implement" ... in which case I'd not vote for it.
January 16, 2019
On Wednesday, 16 January 2019 at 04:52:15 UTC, aliak wrote:
> On Wednesday, 16 January 2019 at 04:33:08 UTC, Nicholas Wilson
>> Yes that is possible. Does it make sense to write? Of course not. We shouldn't be taking into considerations of people writing code like that when designing the language. `@noreturn void` is what people use in C/C++ I don't see why that wouldn't follow in D.
>
> You'd have to take that in to consideration because you'd have to implement the logic to handle it though no?

No, the logic to handle it is already there `typeof(f()) == int`, just if you call it, it is undefined behaviour for it to return.

> And I guess I just disagree with not taking how people would write code in to consideration.

I agree with the sentiment, but people are not going to write code like that. People can write a spaghetti of gotos, do they? Of course not. Should we designing around the fact that they can?

> A proper type gives you everything the attribute does, and has the advantage of not allowing for weird code, and makes the type system more solid, and provides future top-type possibilities. It sounds like the only argument for an attribute is "it's a bit quicker to implement" ... in which case I'd not vote for it.

Solidification of the type comes at the cost of complexity, time, learning curve and bunch of other things. If the only advantage of type over an attribute is that it disallows code that people are not going to write in the first place, then the benefits its provides are not _practical benefits_ and we should treat them as such in the cost benefit analysis.

The fact that it is already implemented is icing on the cake (or nail in the coffin, depending in which way you look at it).
January 15, 2019
As a historical note, subroutines used to be grouped into two categories:

* functions return a value
* procedures do not return a value

See Pascal and Ada for example, they have "function" and "procedure" keywords.

C decided to merge the two into functions, which has its advantages (a pointer to a function need not be a separate type than a pointer to a procedure). They are distinguished by having the function return 'void'.
January 16, 2019
Johan Engelen <j@j.nl> wrote:
> Rust is indeed interesting here because, as far as I understand, Rust used to have a bottom type but they removed it because it was causing too much trouble. So we'd need to learn from them why `!` is not a bottom type proper in Rust, and what justification they have for `!` being a not-quite-bottom type and how that applies to D.

AFAIK the reason is, that Rust has no subtyping in the language. In type theory, the bottom type is the subtype of all other types, which is difficult to achieve without proper subtyping.

Tobi
January 15, 2019
On 1/15/2019 8:16 PM, aliak wrote:
> +1 for not using "bottom". It's really confusing to anyone who is not a language theory expert.

Fortunately, "bottom type" is very google-able, and this comes up:

https://en.wikipedia.org/wiki/Bottom_type

> "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.

---

It reminds me of when we were coming up with a term for what became "immutable" types. People would say:

Q: what does 'readonly' actually mean?
A: readonly means immutable
Q: ok, I get it

Q: what does 'invariant' actually mean?
A: invariant means immutable
Q: ok, I get it

Finally we realized we were being clubbed with a Clue-By-4. Just call it "immutable" and voila, haven't had comprehensibility problems with it since.