Hey,
So I have not been as active in this thread as I would have liked, but
life has a tendency to happen, and it's been happening a lot.
I would just like to cover multiple topics that have popped up, in a
bid to get things back on track.
Scalar Type Hints
-----------------
A lot of people obviously feel strongly that scalar type hints are
lacking here, and that while we are discussing type hints now woul-d
be a good time to talk about that. It isn't.
There is an RFC for scalars and I would love to discuss it another time.
https://wiki.php.net/rfc/scalar_type_hinting_with_cast
This "array of" RFC will be made better by scalar types happening, but
they do not have to happen first so let's not worry about them now.
Generics
-------------
As Joe has pointed out, this RFC has nothing to do with generics. They
are a whole different kettle of fish.
1. Rasums hates them
http://comments.gmane.org/gmane.comp.php.devel/76495
2. I hear a lot of people saying "PHP is turning into Java" every time
anything vaguely OOP happens (which is frustrating, and... factually
inaccurate) but adding generics would be INCREDIBLY Java-esque.
http://en.wikipedia.org/wiki/Generics_in_Java
Those who are interested in it should discuss it, but I do not know
why we are talking about them here. Maybe a new RFC and a new thread
for Generics can occur, but they are not alternatives to the same
solution.
Use-cases
--------------
If you don't see the use, maybe ask about the use, don't assume there
is no use. I will happily repeat this on every single RFC thread in
the future, because it happens every single time.
"Type-checking is not PHP"
--------------------------------------
PHP is a loosely typed language. It allows arrays to contain a mixture
of content. It is very vague. GREAT.
Type-hints are lovely for when you do not want to be vague.
A plain-old function declaration:
1. "Give me a bag of stuff, and I'll try using everything like it's a
spanner, but it could be a banana and... well I guess my wing-nuts
will get covered in banana gunk, but whatever, YAY WEAK TYPING."
or
2. "Give me a bag of stuff and I'll fish around in there trying to
find spanners, and ignore everything else"
This RFC optionally allows developers to say:
3. "Give me a bag of spanners, and break if they put anything else in there."
Optional, opt-in, simple, logical, useful.
Performance
-------------------
This adds overhead when used. Like anything, doing more stuff takes
longer. Check.
The overhead is small, and the use-cases where I see this stuff
happening makes it unlikely for usage to be nested in such a way that
this would run multiple times.
That said it is known that the typing system needs an overhaul. Joe
has said that while this does add a trivial overhead, it can easily be
taken care of in future versions with a general drive-by on types.
It's great to see people discussing caches and other performance
improvements, it certainly does not seem impossible to speed this up a
little, but its hardly slow enough to impact anything unless you have
hundreds of these things handling thousands of records. Regardless, if
you are actually doing that then you need to stop and think about your
actions.
Enforcing OOP
---------------------
Not the case. As has been said, this is equally useful for scalar type
hinting - when that gets done. You can type-hint anything, not just
interfaces. Even currently while only array, callable and OOP stuff is
hintable, this optional feature does not enforce OOP any more than
current type hinting.
Doesn't Handle Traversable
----------------------------------------
Right now the typing system cannot handle hint for both "foo(array
$bar)" and foo(Traversable $bar)", so it is purely a consistency thing
that makes this RFC not try to attack that either. The overhaul of the
typing system mentioned in the Performance section could approach
this, but this has nothing to do with the RFC in question and should
be considered off topic. I did explain that on the RFC itself.
"Just use collections"
------------------------------
Something that I have seen before in these discussions is this
conversational approach:
"Why add a feature to do this in a nice, neat, logical fashion, when
you could just throw loads of code at it?!"
This time it is happening with the suggesting of using Collections,
instead of defining the content at a declaration level.
If I want a bag of spanners, then I can absolutely define
"SpannerCollection" and require that on the type-hint level. Sure.
Personally I hate the idea of forcing the implementor of a method (who
may not be the same as the developer of said method) to change their
code on the outside, purely so I can have the convenience of knowing
the contents of the argument on the inside.
I have the overhead of autoloading, finding, populating and generally
f**king around with that collection, when all I want or need is the
ability to be certain that the argument only contains spanners, and
nothing else.
Suggesting that throwing more code at this is a viable solution is
madness, and this specific example is just suggesting a weak form of
generics should be used. Again, this is not generics.
Syntax
---------
There have been a lot of people suggesting various types of syntax. As
Joe said, using generics syntax for not generics would be a travesty,
and an overcomplication of what should be a simple feature.
For those who hate OOP, array of would be a lovely way to ask for an
array of callables. Trying to make generics happen is a great way to
force not only new syntax, but a brand new OOP paradigm that will be
new for EVERYONE, so ignoring that syntax and letting our functional
and OOP folks have a nice thing shouldn't be considered a negative.
One we decide that this is not generics, we can discuss syntax much easier.
So.
function (Foo[] $foo) - No nulls.
This is something I hope we can all agree on. It is by no means
confusing, but I would be happy to run a poll and get NetTuts to tweet
it, to see if the average user is confused by this syntax. I've
tweeted about it and had 1 out of 50ish replies saying they weren't
sure. The confusion of 2% is something that can easily be fixed with
documentation and time.
Again, I'll be blogging about 5.6 features on NetTuts so those same
beginner level users will know all about it, and our documentation
will explain it for everyone else, meaning a 2% sub-section of users
will be EASY to fix.
Allowing Nulls
--------------------
Some folks are concerned that forcing this feature to not consider
null as a valid array entry is somehow a loss to the feature. We can
potentially fix this with MOAR SYNTAX. I offer 3 options here:
1. function (Foo[]? $foo)
Maybe. Not sure we even care about this, and gets a little confusing
with &Foo[]? but it could be considered.
2. function (Foo|null[] $foo)
Fits in line with DocBlock syntax, could allow multiple types, but
folks would assume that function (Foo|null $foo) is also ok.
My suggestion:
3. Do nothing
We implement this feature, as is, then we have a a follow-up for
allowing type-hinting on multiples:
The new RFC at the same time would implement
function (Foo|Bar $foo)
function (Foo|null[] $foo)
function (Foo|Bar[] $foo) or... function (Foo[]|Bar[] $foo) I guess?
Being able to say "I would like a spanner or a monkey-wrench" is a
perfectly valid use-case, just as "I would like a spanner or an 'I owe
you'" is another valid use-case. But to shove nulls in with something
that specifically expects a spanner is clearly a really weird thing to
do.
Either way, there are a LOT of topics being discussed in this thread
that are not super relevant to what is actually being suggested.
I'd really like it if we could discuss just this feature, and keep the
generics, OOP arguments, anti-type-checking, and "bemoaning of
edge-case performance issues on type system that needs some love
anyway" conversations for other threads.
Thanks! :)