Hello,
I followed the instructions to mail to this address to measure the reaction
of an idea before going through the process of creating an RFC,
but I am sorry if this is off topic for this board.
Problem:
I have been looking for a solution to reduce the verbosity of my code and
invoke
data type validation exception automatically at the correct point within
the body of methods.
My research lead me to find that type hinting for scalar values is not
easy, mainly due to the impact it has on the language principles
as well as the effect it would have on backwards compatibility. Examples
found at:
http://nikic.github.io/2012/03/06/Scalar-type-hinting-is-harder-than-you-think.html
Including the RFC:
https://wiki.php.net/rfc/scalar_type_hinting_with_cast
Other solutions I have attempted to find involved mimicking autoboxing:
https://wiki.php.net/rfc/autoboxing
My solution:
In order to reach the best of all worlds, (principles, backwards
compatibility and portability across different user implementations)
I tried to design* a feature where all of these aspects are left in the
hands of the users.
What I came up with was a new construct which shares the same space as
classes, interfaces and traits, with
the sole purpose of being used as a type hint.
You would use it as a type hint, however rather than require the argument
to be an instance of the definition, it processes
the value with a user implemented handler, in order to assert the value or
change it.
My concept can be found here:
https://gist.github.com/orolyn/9ff0756b3cb3cdfe454b
Advantages:
- Methods expecting strict values would no longer need to use inline type
checking for scalar types. - Users could define reusable type checking for almost any type of value.
- Since the definitions would be user defined, there would be no chance of
conflicts with existing classes.
Disadvantages:
- Assertions would have to be static and stateless if you are using a good
dependency injection pattern. - Users of libraries incorporating custom type hints may become confused as
to what an argument should be if not properly documented. - Complications with IDE intellisense (primarily with type detection).
I left out performance issues in the disadvantages because I truthfully
don't know what they would be.
The example I provided is simply a concept. If the theory is desirable,
then the design is completely reworkable.
Thanks,
Dominic
My concept can be found here:
https://gist.github.com/orolyn/9ff0756b3cb3cdfe454bAdvantages:
- Methods expecting strict values would no longer need to use inline type
checking for scalar types.- Users could define reusable type checking for almost any type of value.
- Since the definitions would be user defined, there would be no chance of
conflicts with existing classes.Disadvantages:
- Assertions would have to be static and stateless if you are using a good
dependency injection pattern.- Users of libraries incorporating custom type hints may become confused as
to what an argument should be if not properly documented.- Complications with IDE intellisense (primarily with type detection).
I left out performance issues in the disadvantages because I truthfully
don't know what they would be.The example I provided is simply a concept. If the theory is desirable,
then the design is completely reworkable.
This is missing basic information like relation to namespaces. By the
dynamic nature of PHP this also most likely means that each use of this
leads to anb additional function call for each parameter. Given the fact
that function calls are one of the slowest parts in the engine this is a
massive cost. I also foresee "clever" developers doing "clever" magic
inside those type cheking routines and in the end creating an
undebugabble mess.
johannes
My concept can be found here:
https://gist.github.com/orolyn/9ff0756b3cb3cdfe454b
I actually have a similar idea I’d like to propose (I’d write a patch first, it’s on my list of things to do), though it has scalar type hints only as a fringe benefit.
I don’t think I like this proposal, though. I don’t think we should introduce a new typehint
keyword. PHP already has too many reserved words. There are some that aren’t reserved which I’d like to reserve (int, float, string and bool), but I don’t think we should make typehint such a word.
Functions in PHP cannot be autoloaded, so this would be quite inconvenient to use. Will people bother adding an include to every file merely to use typehints? Or are typehints classes, in which case, why not simply define them as a class rather than adding a new keyword? Or are they are new kind of autoloaded thing?
As Johannes mentioned, this would require a function call every time an argument is passed. Unlike, say, auto boxing, once validated, you will still need to validate it again for each call. The performance impact isn’t so good.
How does this handle references, and how does it handle null? How is inheritance/interface compatibility dealt with?
Thanks!
Andrea Faulds
http://ajf.me/
Functions in PHP cannot be autoloaded, so this would be quite inconvenient
to use. Will people bother adding an include to every file merely to use
typehints? Or are typehints classes, in which case, why not simply define
them as a class rather than adding a new keyword? Or are they are new kind
of autoloaded thing?As Johannes mentioned, this would require a function call every time an
argument is passed. Unlike, say, auto boxing, once validated, you will
still need to validate it again for each call. The performance impact isn’t
so good.How does this handle references, and how does it handle null? How is
inheritance/interface compatibility dealt with?
They would be treated with the same respect as classes, in the same sense
as traits are. Therefore the autoloading would apply to them, as would
namespaces.
Using actually classes was my first though. I was thinking about a special
interface like "TypeHint" which would invoke special treatment when used in
type hinting.
However I was getting caught up in the semantics of what contract the class
should have with the interface.
Regarding the additional function calls, I don't know. If the performance
hit is due to calling the user defined handler, then I would justify it by
arguing that a similar hit would be suffered from the necessity to use a
strict type to begin with, when the user validates the values in the method
which requires it. If however you are referring to an engine function call
made to determine if the type hint is indeed a special type hint or a
class, then yes I would agree.
For references I proposed that the value parsed to the handler would be a
reference of the actual argument, so any changes made in the handler would
propagate to the previous scope if the original argument is intended to
be a reference.
For inheritance and compatibility, I hadn't thought about, but considering
a sub class or implementer cannot break the compatibility of its
parent/interface, the same rules would apply.
Thanks,
Dominic