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