On Wed, Jul 06, 2005 at 03:29:36PM +0200, "TSa (Thomas Sandlaß)" wrote:
: 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?

It achieves guaranteed *late* binding of types, whereas generics/roles
are biased towards early binding (class composition time, usually at
"compile time").

: >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?

Would be a late type binding in that case.

: Something like unary operator does?

Don't follow that.

: Into which scope do these role instanciations go?

Unary role instantiations always go into the "currently composing class"
(and maybe module, if we admit "sub" roles).

: Does "does *FooStuff[Int]" mean global?

It means to look for FooStuff in the global namespace and nowhere else.

: >: >    ::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.

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.

: 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 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 *.

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?

: 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.

Yes, it's currently just a promise that T will be declared by the
time we need it.  Otherwise T would be taken as an illegal bareword.

: 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?

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.

: 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 ;)

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.

=begin WAFFLE

I suppose we could reserve ::Type as the variable form, and then require
an actual forward declaration for the other form:

    my class T {...}
    my T $x;
    ...
    my class T { has $.x; }

Note that in this case, the second "class T" probably should default
to "my" instead of "our", or otherwise produce some kind of warning
if there's a "my" vs "our" conflict.  Similarly

    class T {...}
    my T $x;
    ...
    class T { has $.x; }

requires both references to be to "our" T.

That seems okay, and maybe even consistent, but we'll have to
think about the relationship of ::T and ::($x) a bit more, and how
it differs from ::{$x} (or ::$x for that matter).  And if we're
changing the meaning of :: from "this is a known name" to "this is
an unknown type", whether consistency requires that $($x) be the
explicit symbolic deref form.  I think I'd prefer that symbolic refs
were huffmanly longer than that.

Even if we settle on ::T for type variables, I still think we have
to say that they are legal only in a declarative context.  These would
be fine

    my ::T;     # unbound type variable
    my ::T $x;  # type variable bound when $x is bound

but in rvalue context I don't think ::T should imply declaration, but
rather refer to an earlier declared ::T, or fail.  An explicit declaration
can still be done

    $x = (my ::T) $y

to get ::T bound to the type of $y "en passant".  Probably.

=end WAFFLE

Larry

Reply via email to