That was one of the most illuminating things I have ever read. Thank you for taking the time to write that.
On Tue, Jan 28, 2020, 16:12 Trey Ethan Harris <treyhar...@gmail.com> wrote: > Oops, rereading what I sent I see I missed looping back to one detail: > > On Tue, Jan 28, 2020 at 08:54 Trey Harris <t...@lopsa.org> wrote: > >> In Perl5, undefinedness meant something that it still _can_ mean, and in >> the course of ordinary “business logic” programming perhaps still most >> often means: a yet-to-be-filled container, an unassigned value. In Perl5 it >> was also very obviously a sort of falseness and frequently used in that >> manner. >> > > Let me elaborate: in Perl5, we lacked a proper boolean type. 0 was > frequently used as a stand-in for False following the C-family > tradition—except in cases where 0 was a perfectly good numeric value that > needed to be true. Then we came up with dodges like `undef` and `"0 but > true"` being used for truthiness. > > In Raku, we have a proper Bool, and things that define truth or are > answering yes-or-no questions respond with a proper boolean, True or False. > Given that, we have no need anymore for undefinedness to be a sort of > falseness. > > ...and yet: it turns out to be very nice for DWIMminess if undefined > values coerce to False, not True, so they do in Raku. For iterating through > sparse structures or unbounded structures, for short-circuited > existence-checking, for a bunch of other reasons, undefined values are > False. > > This all means, recalling that undefinedness equals notionality and > notionality equals type and type objects equal undef, that _every_ type > value is False, from Mu on down, and no type object, no matter how vacuous > or concrete, is True. > > So, in Raku, it’s best not to use undefinedness as a False value except in > the specific cases where you know what you’re doing. You also need to know > for gotcha-avoidance and debugging purposes that a Bool container, such as > “my Bool $x”, notionally can ”be” any of _three_ “values”: `True`, `False`, > and `Bool`, which is a type, so is undefined, and so also coerces to False. > > But, the takeaway: in general, it’s not good practice in your programs to > mix your use of “undefinedness as type value” and “undefinedness as lack of > concrete assignment”. > > >> >> In Raku, “an undefined Int” means not only the above but also what it >> means in English: the notional value of Int-ness. If you try to use rvalue >> “undef” in Raku as you would in Perl5, you’ll get a very nice error message >> to explain: >> >> ```console >> > undef >> ===SORRY!=== Error while compiling: >> >> Unsupported use of undef as a value; in Perl 6 please use something more >> specific: >> an undefined type object such as Any or Int, >> :!defined as a matcher, >> >> Any:U as a type constraint, >> Nil as the absence of an expected value >> or fail() as a failure return >> >> ------> undef<EOL> >> ``` >> >> So, to distill and recap: >> >> 1. In signatures, `:D` and `:U` mean “defined value” vs. “undefined value” >> >> 2. At least as often as `T:U` (where `T` is some type) literally means “a >> container of type T that has not yet been assigned a value”, it means “the >> notion of T” or simply “the literal type value, `T`”. Since types are among >> the things that define namespaces, a unary routine `routine-name` with a >> `T:U` parameter often means, “something you can usefully call as >> `T.routine-name” >> >> 3. In Perl5 it’s quite rare that a routine (or rather, for Perl5, func >> and/or sub) works on a variable before it’s assigned to but fails after. In >> Raku it’s quite common, as `.Range` shows. This may be a source of >> confusion, but if you remember that definedness doesn’t just mean >> “assignedness” but “notionality vs. concreteness”, it makes more sense. >> >> 4. All that said, in the case of multis it’s not unknown to use `:U` for >> the “unassigned” rather than “undefined” connotation, as one might use a >> top-level sub guard, to fail with a useful diagnostic directing one to the >> proper usage of a routine. >> >> 5. `Int` is a type value. Type values are always undefined. `my Int $x;` >> creates a $x which is a container to hold an Int, but until it does, it >> _is_ still an `Int`, an undefined `Int`, which makes it exactly equal to >> the literal `Int`—i.e., a type object. It’s not great programming practice >> to use a single container as both a type value and a concrete value, but in >> diagnostics such as the one for Range that surprised you, you need to be >> aware that it _can_ work that way. >> >> Trey >> >