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
>

Reply via email to