I've been thinking quite a bit about Sub::Signatures and what it would take to get them "production ready" (for the 3 people on the planet who would dare to use them) and I think I've stumbled on it: ignore types. Since I've made it extremely clear that this was alpha code, I don't feel bad about changing how it works.
What finally made me lean that way was Ruby's duck typing. Duck typing says "if it looks like a duck and quacks like a duck, you can treat it like a duck, even if it's just some guy with a weird fetish." Basically, if your object has a shoot() method, who cares what type it is? In reality, I think many of us care. Not too many people brag about bringing a camera to a gun fight. However, the gun fight is a perfect analogy. If you have to go to the gun fight, what do you do if you don't have a gun? What if one guy brings a bow and arrow and the other brings a feather boa? Townspeople will speak for years about the bloody mess of feathers blowing in the wind and how lucky the other idiot was.
That's why I think duck typing probably works. You understand the domain of the problem and you introduce things that are suitable to that domain. Arguments to functions tend not to be passed at random. The function reasonably dies when you have gunfight($feather_boa) because when you tell your feather boa to shoot, it doesn't get the message. gunfight($bow_and_arrow) somehow succeeds because you do have a shoot method, not because of strong typing. If one passes the wrong arguments to a function, it probably can't do what you want. If it can do what you want, it has a better chance of working because you probably didn't pass a camera when you needed something that solves the "let's kill the other guy" business need. You passed something reasonable. Passing the wrong thing is far less likely to arbitrarily succeed because it's not reasonable.
Yes, there are those obscure cases where someone really does bring the camera and pulls down a posthumous Pulitzer, so how do we deal with that? I think that is handled the same way any dynamic typing issue is handled: you have so much freedom of movement without the straightjacket that when you accidentally poke yourself in the eye, you don't mind the jumble of metaphors.
Which is why I think I might remove all type checking from Sub::Signatures. It will have two modes: normal and dispatch. With normal mode, it's just syntactic sugar for handling arguments. With dispatch mode, it handles MMD based upon the number of arguments, not their types. With this, we can also allow a trailing array or hash, but any variadic functions that are ambiguous are fatal at compile-time.
sub foo (@array) { ... } sub foo (%hash) { ... } sub foo ($scalar) { ... }
No two of those can be use together because the code has no way of disambiguating them (my kingdom for non-list flattening context!)
We could, however, do this (something the code currently does not handle):
sub foo { ... } sub foo ($bar) { ... } sub foo ($bar, $baz) { ... } sub foo ($bar, $baz, @array) { ... }
But if $baz can be either an arrayref or a hashref, it still has to be handled by the actual code. Still, that defeats one of the major benefits spelled out in the docs.
Would I use this code? Possibly. The major benefit I see is experimentation. Some people are leery of seeing us experiment with things they think are "not Perl," but I can't say I like the solutions I've seen. Of course, with a Perl 6 beta likely only a year or so away, I'll probably drop all of this immediately for my next half-finished project. Hmm ... maybe a Perl 6 tutorial on my site?