HaloO, John M. Dlugosz wrote:
First, consider the stated examples for Generic type parameters, from the passage which defines the terminology in S02:
I fear we need a rigorous definition of generic first.
sub max (Num ::X @array)
> { > push @array, X.new(); > } Here you have a nice example of the variance problem. Assuming Num <: Any the question is if push is callable with Array[Num]. If Array[::T] is invariant on ::T push has to have exactly this type. This is easily achievable if push is itself parametric and the above instanciates push[Array of X, X [EMAIL PROTECTED] on the fly.
Question 1 - can the Any be left off? That is, ::X as an undeclared type name used as the only type, syntactically correct?
Any can be dropped. But note that ::X captures the *actual* type of @array. That is my Num @a = (1,2,3); # actually Array of Int my Num @b = (1.2, 2.2); # actually Array of Num compare( @a, @b ); # type error
Question 2 - is $x constrained to ::T or does that just note what it was originally? (in cases where $x is not read only. In this example that is moot.)
It captures the actual type. To put a contraint on $x you need to evaluate the type, that is use it without the :: sigil. For rw parameters we can't allow variance if we want type safety anyway. BTW, I wonder if the trait 'is ref' means write-only parameter?
So, we might want to capture that concrete type to, and write Document Storable Positional ::DocType $doc;
Fine.
Now the fact that this is a generic type notwithstanding, it is just another type in the list. It just happens to be the same type that is the actual type $doc was initialized with. But, it implies that yes, $doc is constrained to that type from then on. The generic type just customizes the list at run-time, but it is still a list of juxaposed types, so they are ANDed together.
No.
Now we have a list of juxaposed type names, that are ANDed together. The generic type is the one that wasn't defined (as a type) before. It needs the :: so it doesn't flag as an undefined symbol, but the others could have the sigil if you wanted to be explicit: ::Document ::Storable ::Positional ::DocType $doc;
Hopefully not. This just captures the type $doc into four variables.
::T $x;
No, this is just like &foo is different from foo. It does not constrain $x to T but captures Any in this case. And if T is already declared in this scope it's a redeclaration error. S02 seems to say that this just rebinds ::T but that means to loose it as a unique type parameter for the scope! So we should change that. BTW, C# raises an error for the following case sub foo ($a) { my $x = 3; if $a > 0 { say $x; # error usage before declaration my $x = 17; # in effect from start of scope say $x; } } and I see some merit in it. How is Perl 6 supposed to handle this?
That answers the two questions, based only on other things in the Synopses.
Ups, my reading is different.
Now for a proposal, and the observation of an issue. The only thing that makes a generic type parameter generic is that it was previous undefined as a type. So, what if you have code that's working just fine, and then some other change puts a symbol T into the lexical scope, perhaps as a global import? Boom! The code changes meaning drastically.
Which is no problem if ::T defines it in the lexical scope. Any outer definition is hidden. I guess re-using ::T in the same scope again for capturing a new type is an error. Just like redeclaring a value variable. BTW is sub foo ($x) { my $x; # redeclaration error? } just funnily hiding the parameter $x or an error?
Contrast that to the normal meaning of declaring a variable, in which case it hides anything with the same name in the outer scopes. Introducing a global one does not change the code that uses lexical variables. Except for generics. That is inconsistant and wrong for the same reason that it would be wrong for all other kinds of symbols.
Which is why it isn't so, or is it? Please correct me if I'm wrong!
To address this, I propose using a positive way to declare generic parameters rather than having them implicit based on not previously existing. I propose the triple colon, :::, for this purpose: :::T $x;
Which is ugly. Regards, TSa. -- "The unavoidable price of reliability is simplicity" -- C.A.R. Hoare