HaloO Larry,

you wrote:
Well, there's something to be said for that, but my gut feeling says
that we should reserve the explicit generic notation for compile time
processing via roles, and then think of run-time lazy type aliasing

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?

as something a little different.  So if you really want to write
that sort of thing, I'd rather generalize roles to work as modules
containing generic subs:

    role FooStuff[T] {
        sub foo (T $x, T $y) { }

Otherwise people are tempted to scatter generics all over the
place, and it's probably better to encourage them to group similarly
parameterized generics in the same spot for sanity.  It also encourages
people to instantiate their generics in one spot even if they're
calling them from all over.
I think people should say "does FooStuff[Int]" and automatically alias
all the routines to the Int form so we don't have to scatter :[Int]
all over.  Or if they just say "does FooStuff", they get lazily-bound
type parameters.

I get that right, FooStuff can be instanciated without a class or object?
Something like unary operator does? Into which scope do these role instanciations go? Does "does *FooStuff[Int]" mean global?

: >    ::T $x := $obj;
: >    my T $y = $x;
: : The prime use of that feature is to ensure type homogenity for
: temporary and loop vars in a certain scope. But the scope in the
: above syntax is not apparent enough---to me at least.

Actually, I was holding those up as bad examples of scope visibility,
so I'm agreeing with you there.  (Which is why I suggested that we
require a "my" context, even if only implied by the formal paramter list.)

: Thus I opt for an explicit
: : subtype T of $obj.type; # or just $obj perhaps?
:    T $x := $obj;
:    my T $y = $x;

Yuck.  I think that completely obscures the lazy type binding.
Plus you've managed to omit the "my", so you've created a global
subtype T.  (Unless, as I'm leaning towards, we make such bare "inner"
types illegal, and require "my", "our", or "*".)

The only thing I did was to replace the :: sigil with a subtype
declaration. 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? I mean even non-declared
auto-vivified vars go into the immediately surrounding scope,
or am I horribly mistaken?

sub foo()
   if (1) { $x = 'from above' }
   if (2) { say $x }  # prints 'from above' even if no outer $x exists?

   say $x; # prints undef or 'from above' if outer $x

Up til now I assumed that ::T and plain T mean exactly the same if T
is pre-declared/defined. The type sigil is only needed to defer the
definition/binding. In a certain sense this is a hanging type reference
similar to &foo beeing a reference to Code. Which brings me to the
question how to bind a type reference. I mean we have

my &fooref := &foo

which allows fooref() calls, right? How are type references derefed
if not by dropping the sigil? ::TypeRef() perhaps?

my ::TypeRef; # type variable?

sub make ( ::Type, Type $value ) returns Type
   if (::TypeRef != ::Type)
      ::TypeRef = ::Type;
   my Type $x;
   $x = $value;
   return $x;

my $i = make(Int, 17);
my @a = make(Array, [1,2,3]); # single element array?
                              # or three element array?

my $e = make(Int 'string'); # type error in &make?

With the automatic binding of a ::Type variable to the type
of it's argument the definition of &make could be shortend to

sub make ( ::Type $value ) returns Type
{ ... }

and called like this

my $i = make(17);

which at least prevents type errors ;)

TSa (Thomas Sandlaß)

Reply via email to