HaloO Larry,
you wrote:
: Could you explain what exactly 'run-time lazy type aliasing' is?
: I mean what does it achieve and how does it compare to type
: instanciation and parametric contraint checking?
It achieves guaranteed *late* binding of types, whereas generics/roles
are biased towards early binding (class composition time, usually at
"compile time").
To me "binding" implies prior existance. That is the type instanciation
takes place elsewhere and flows into a scope as a temporarily bound
variable. How do you intent to achieve demand driven on-the-fly type
instanciations? This seems to me a necessity for Perl6 where not all
type information is available at compile time.
: Something like unary operator does?
Don't follow that.
Well, I regard operator does as binary. It's LHS is the receiver of the
role given as the RHS. This composing into comes in two modes for
compile time and runtime. E.g.
class LHS does RHS {...} # binary does at compile time
$x does RHS; # runtime role attachment
does RHS; # unary form?
: The only thing I did was to replace the :: sigil with a subtype
: declaration.
It's the lack of a "my" that bothers me.
: Does subtype always go into global scope? I thought
: that it requires a *name to go into global and our to go to the
: innermost module---or was that package?
For unqualified packages/modules/classes the default up till now has
been to put them into *. But I think I'm going to change that. See below.
That is very wise. But I would make a distinction in defaulting to
my or our: the keyword declared things like class, sub, etc default
to our, while the sigiled variables default to my. The latter would
prevent data leakage and auto-vivification surprises:
sub a { $x = 'a' }
sub b { $x = 'b' }
sub x
{
rand() < 0.5 ?? a :: b;
say $x; # should print undef unless $x defined before &a
}
: I mean even non-declared
: auto-vivified vars go into the immediately surrounding scope,
: or am I horribly mistaken?
They are "our" by default, not "my". Just as subs are "our" by
default. And indeed, that is probably what package/module/class
names are going to default to as well.
I think that forcing our on variables that shall go to the outer
scope where sharing is intended is a good idea. There could even be
a compiler mode that doesn't actually produce bytecode but re-writes
the source with nested our declaration moved to there "proper" place.
The purpose of my and our declarations is to give the compiler
and the runtime environment about the declared variable. Our stores
that information at the innermost level of collaboration while my
stores it at the innermost scope. For auto-vivified vars no storing
is needed because they bear no specific meaning.
I was confused because I
thought of file-scoped "class Foo;" declarations as defaulting directly
to *. That's inaccurate. It's just that the "current package" at the
start of a file happens to be *, and so it doesn't matter if you
say "class Foo" or "our class Foo", because they mean the same thing
at that point. If you say "class Bar" within the scope of any other
package/module/class, though, it should default to "our class Bar".
So it might as well default to "our" everywhere. The upshot is that
if you want to declare a module that declares a bunch of global classes
inside it, you have to use *. That seems like good documentation anyway.
Only the first class or module declaration in a file defaults to *.
I think it defaults to the scope it is embedded into. Conceptually
a module is instanciated into the surrounding scope by a use statement.
The implementation might of course be optimised in loading the generic
code of the module ones and create a proxy and/or specific instanciations
of generics into the importing scope.
Hmm. Does that mean that the top-level program starts running in *
instead of in Main. Or maybe the * rule only works on .pm files?
I would keep files out of the picture. The canonical form of a
Perl6 program is the "concatination" of all sources with the
"package Foo; ... eof" replaced with "package Foo {...}".
In this line of thinking * is the outer shell of the Perl6 bubble
you are in. Immediately outside that bubble one typically finds
Parrot or Pugs, but it could be other forms of programatical
embedding.
: my ::TypeRef; # type variable?
No, that's what I've been trying to say. I haven't wanted ::T to be a type
variable by itself. It's a type literal that simply doesn't have to
have been declared yet, but we know that if it had been declared, we
could also call it bare "T". I want some other syntax for declaring
type variables that involves explicitly "mying" or "ouring" the type.
[Or at least I did want it. I change my mind below.]
So currently the above would be a syntax error. We don't want
::TypeRef to behave differently in
my ::T;
my ::T $foo;
They should either both declare ::T, or both refer to an existing
type literally named "T". That's where the ::-as-a-variable-sigil
idea breaks down.
[..]
Okay, you've used ::Type as a type variable--now how do you declare
that you simply want Type treated as a forward declaration of "Type".
I'm not quibbling with the desire to bind types to type variables.
It's just we've got a conflict in the definition of what :: means
that we'll have to resolve one way or another.
I don't want value-like type variables because that would generate
a big mess if one wanted to store type refs in value vars:
my $typeref = $object.type;
my ::$typeref $same_type_object; # do we want this?
my $typeref $weird; # or even this??
The only use of type variables is in parametric types. And since
you want to restrict that to roles the need for implicit type binding
shifts onto the does operator and role instanciation. But how automatic
will your example
role FooStuff[T] {
sub foo (T $x, T $y) { }
...
}
be instanciable? I guess the explicit forms are:
FooStuff[Int]::foo(1,2);
&strfoo ::= (FooStuff[Str].new)::new; # from Autrijus Hackathon notes
Will re-instanciation be prevented when the latter is spelled
&strfoo := (FooStuff[Str].new)::foo; # or with =
Actually this syntax might be wrong usage of ::.
But do I get you right that the lazy forms are
does FooStuff; # lazy role instanciation into current scope
foo(1,2); # &FooStuff[Int]::foo:(Int,Int)
foo(1,'blahh'); # type error?
Regards,
--
TSa (Thomas Sandlaß)