HaloO,

John M. Dlugosz wrote:
  sub (::Type $x)     # declares generic type parameter as actual type
                      # of $x argument
sub (::Type $) # ditto, but don't care what the value is. Value # passed though.

OK.

  sub (::Type)   # the parameter is a type object.

No. That can be evaluated at compile time to ::Type ::= Void.
Never mix type level and value level!


  sub ($x, $y --> ::+RetType)  # Not a generic, but the current value of
                               # the context variable

This is generic. Please let's really not mix terms:

     value variables contain values
     type  variables contain types
     kind  variables contain kinds
     ...

instead of contains one also says the 'variable ranges over'.


  sub (::?CLASS $self, $x, $y)  # Not a generic, but special ? variable

No. I would call that compile time generic because of the twigil.


  sub ($x, ::Foo::Bar $y)  # Not a generic, but current meaning of
                           # ::Foo::Bar

Hmm. Obviously Foo has to be predeclared. And I don't know why
one would like to capture the type of $y into another namespace.
So to invoke the type Foo::Bar you need to drop the :: sigil.


  sub ($x, ::Bar $y)  # Generic, defines new Bar and ignores any
>                       # current meaning

Yes, in the lexical scope of sub. Just like $x and $y.


That would fix the problems with cases where you must use the sigil. But I still think the idea smells bad: that the sigil normally means a symbol of a particular type, can be omitted when that kind of symbol is expected, but leaving it on is "normal" and explicit but omitting it is a shortcut; except now the sigil means something different if you don't omit it but only in some places.

Sigils are not in the least bit optional. The two sigils & and :: change
the meaning of the bare word they are attached to---always. Some of the
possible meanings are conflated for convenience: &foo() means the same
as foo(). But bar(&foo) means something different than bar(foo). And
bar(::foo) should be a syntax error because it is not in a declarative
context. If you want to call bar with the HOW of foo and foo does the
Code role you have to say bar(&foo.HOW). Otherwise bar(foo) already
means that and bar(foo.HOW) would be the meta of the meta class
singleton. Note that this is a value that you can of course not use in
type position.


I still want to find a positive syntax for declaring generic types that harmonizes better. Many ways suggest themselves, but the hard part is coming up with something succinct. Larry, you never said what you thought of my idea of simply using more colons. That seems to have precedent in the language as it stands. ::::Type is probably the most precedent-harmonizing, but :::Type seems sufficient.

I would argue that ::Type is sufficient.


But suffixes, there is lots of room available. We already know that it has a :: sigil and a single identifier. Perhaps ::Type! connotes "declare me here", and goes well with the ? suffix of optional parameters.

No, you need these in

   role Foo [::T!, T *::S] {...}

to mean one required type parameter and optional compatible ones.
That is Foo[Num,Int,Int] is a valid instanciation. S[0] and S[1]
are then Int within the instanciation of {...}.


And I close with this example of generics and signature extraction, because Perl 6 generics needs to be at least as powerful as C++ templates:

   sub (Positional ::Container[of => ::ValType] $x)

makes both Container and ValType available in the scope of the function's block, and ensures that whatever is passed also supports Positional.

Well done.

The only thing is, I had to make the parameter $x not @x. How can I name the container type as a generic, rather than the value type?

You mean capturing the sigil? I guess using $ is as generic as one could
get. @, @@ and % essentially are type constraints. So

    sub (::Container[of => ::ValType] @x)

already constrains ::Container to Positional.


Regards, TSa.
--

"The unavoidable price of reliability is simplicity"
  -- C.A.R. Hoare

Reply via email to