To me the foo looks like a template sub and I wonder how it is
instanciated with different types. Since type parameters are
provided with [] it should be foo[Int], foo[Str] and the like.
I wonder further if that could also be written foo of Str like
with Array of Int etc.

  my foo of Int &intfoo;

  my Int $x := intfoo(3,2); # type correct

Also I wonder if Perl 6 can support all foo[::T] with a single
generic body where other languages have to generate different
code for each ::T. The type inferencer could also find out a
lot of constraints for ::T from the body. E.g.

   sub foo (::T $a, T $b --> T)
   {
       if $a != 0 && $b != 0   # ::T does Compare[Num]
       {
          return $a * $b;      # ::T does Arithmetic
       }
       ...
   }


Regards, TSa.

Having a generic type in sub foo will serve the same effect as templates in C++. I think it literally means having one body, without strong typing, that has static type checking added to it.

The implementation could indeed decided to instantiate different bodies depending on the type, rather than doing it the slow way on each use of the object.

But, &sub is a single Routine object, unlike a multi which are different subs that can be referred to individually. If the implementation chooses to specialize the body, it would be "inside" the single &foo entry point. Code that calls foo still needs to call the single entry point rather than optimizing to the real body, in case &foo gets wrapped at run-time.

Note that an implementation can =always= generate specific code and then run it, rather than looking up untyped access as it goes. If you have

  sub bar ($a)

and call a lot of methods on $a, perhaps in a loop with millions of iterations, the implementation might specialize the block once when it knows the actual type of the object in $a. Lets hear it for read-only variables--they can be as useful as declared types, for optimizing! If you run the optimizer at run-time, that is.

I don't think the inferencer can tell that ::T does Compare. It could find any implementation of the operator that can be called with that type, without it being part of a known interface. It has to build up an interface on the fly based on what is done in the function, and then populate it upon entry. For things that are not called as method-call syntax, it will have trouble even doing that unless it knows the types of the other arguments too.

--John

Reply via email to