Open bartfeenstra opened 7 years ago
The same applies to currying and partial application, as the closures they produce do not specify return values.
func_get_args()
is also tricky, not because we cannot validate the number of parameters (because less than provided is always fine), but because there's no way to check the types of arguments the function obviously accepts.
I guess we have to accept any solution we come up with can tell most, but not all invalid callables are invalid, but it can never certainly say any callable is 100% valid, at the very least due to func_get_args()
.
One of the problems is that many callables developers may want to use do not conform to the interfaces we'll be defining here:
We can optionally whitelist callables per callable type, like registering
\is_string()
and siblings as valid predicates, even though their signatures may not indicate so. Manual registration should be allowed, but for built-in functions we may be able to useget_defined_functions()
. It also enforces developers to use type declarations while a large portion of them prefers duck typing. Catering to that audience is not a priority (type declarations improve debugging and validation experiences and that's exactly what we're trying to do here), but it would be nice if duck typing could be supported. Maybe a global assertion validation level? Maybe consider callables valid if they may not be as strictly defined as the prototype prescribes, but cannot be confirmed as otherwise incompatible? An example of this would be to allowis_string()
based on the fact it takes the correct number of arguments, and does not specify any types that would violate the prototype's contract. This deviates from interface implementation compatibility (which is what we were trying to emulate here), but would prevent MANY false negatives.