Austin Hastings wrote:

But what's the vision for p6?

My expectation is that the type-checking stuff will be heavily used
for:

1- Large scale projects.

2- CPAN modules.

I expect that the folks who want to do one-liners will still want to be
able to say C<perl6 -MCPAN whatever>

So the "strict" bits have to be forgiving of the "non-strict" callers.

To me that's a contradiction in terms. Strictness can't be "forgiving". At the risk of stating the obvious, that's the whole point of strictness: to be strict.

What we're suggesting is that if you want to be non-strict, don't use types.
After all, they're optional.

"But," (I hear you say), "I may not have a choice! If the Cruel Module Author chose to use types, then I'm forced to do so too. That's not Lazy."

And you're right. The module author gets to determine the interface of their module. And if they determine that that interface will provide type-safety, then you have to respect that. Just as if they decided that it would have an OO interface, or would set PRE and POST conditions on calls, or would only take named arguments.

Because the author of the module is *relying* on that interface to ensure the correctness of their code; to prevent inappropriate data being passed to their subroutines. Typing is yet another way in which they can relax, knowing that the wrong type of data will be headed off at the (compiler) pass.


To me, the way around this is NOT to force interface contracts down to
some lowest common denominator, but rather to document what is
expected, and then allow the developer to accept responsibility for
stepping on his crank.

Yep. And the way for the client of some module to accept that responsibility is to put in an explicit conversion.



If you say, "Give me an Array of Hash of (String => Array of BigNum)"
and I say, "Here's an Array of Scalars. They're OK, I promise" and
things "gang agley", it's my fault. I can deal with that.

But large projects -- where typing will be most important -- *can't* deal with that. That's the point of typing: to specify and enforce interface contracts. At compile-time if at all possible.



But at the bottom, the C++ problem is a problem of its own making --
people want coercion. Just like me. I want coercion. I want the ability
to take advantage of the really nifty, carefully written code available
from dedicated, rigorous hackers like this Conway fellow. But I want to
do it as a slap-dash hack with no thought given to type stuff.  How?

By distinguishing a parameter that *requires* a particular type, from a parameter that *ensures* a particular type (by coercion if necessary). I've suggested that using C<is copy> semantics should indicate "make whatever I'm actually given into one of these, if you can", whereas reference semantics say "this must already be one of these" (by their very nature, since an aliased parameter *is* the argument).


Alternatively, one might imagine a separate and explicit trait that specifies that a parameter is allowed to coerce its corresponding argument to it's own type.

But what we can't allow is a reference parameter to coerce its argument. For example:

        sub loggedincr (Int $i is rw) {
                print $log: "Incremented $i.id()\n";
                $i++ unless $i.constant;
        }

# and later...

        int $x = 7;
        loggedincr($x);

The $i parameter *can't* be bound to $x, because $x doesn't have the necessary features to be an Int (e.g. it doesn't have the capacity to respond to method or property lookups). Even wrapping $x in a temporary Int wouldn't help, since it would render the logging of an .id meaningless. The whole point of having types is to catch this kind of problem at compile-time.


My own problem with this wrapping notion is that I consider it
incompatible with the reference semantics of normal Perl 6 parameters. Specifically, I *don't* want the aliasing mechanism to be capable of implicit type coercions.
Maybe you could expand on that a little?

See above.



On the other hand, I have *no* problem with this:

        sub foo(@a is Array of Int is copy) {...}
                                   ^^^^^^^
doing the kind of coercive wrapping you're suggesting.


What's the difference? (Aside from the obvious, that is...)

Suppose I call:


foo(@x);

The difference is that @a above is a lexically scoped variable into
which the contents of the corresponding argument (@x) are copied (i.e. assigned). Now it's perfectly possible that the contents of @x can be assigned into @a, even if the argument and the parameter are of wildly different types.


But if I say:

        sub foo(@a is Array of Int) {...}
        ...
        foo(@x);

then I'm saying: "within &foo, @a is just another name for @x". So they are (temporarily) the same thing. That can only (be allowed to) happen if the actual type of @x satisfies all the requirements of the declared type of @a.


Damian




Reply via email to