John,
Thanks a lot for the reply. Comments inline:
> You've been spending a lot of time defending these proposals and trying to prove wrong
> feedback that raises concerns. This is preventing you from actually using the feedback to improve
> the proposals. You are losing out on perhaps the biggest advantage of the RFC process, which is that
> multiple minds can work together to hammer out an idea and make it really shine.
I only defended what I thought were misconceptions or miss-information
about them. After all, the quickest way to a failure is assumption
(granted, this is ironic given the rest of this reply)...
> You can mince words, but that doesn't change the problem. It is utterly inconsistent with
> the expectations in creates. You'll argue that it creates an expectation of a type cast, but
> you'd be wrong in far too many cases. The syntax is similar enough to the syntax for
> parameter types in other languages that developers will think of it as basically the same thing. The
> syntax differs however from existing parameter type syntax.
That was intentional. That was the point I was trying to make... But
let's keep going.
> The behavioral difference is also a problem, being too different from parameter typing to be
> useful (it doesn't actually vet the parameter), and yet close enough to validate the confusion
> (behaves too similarly to an implicit conversion). In the end you have a bizarre syntax that looks
> like one thing but is conceptually another, but with a subtle behavioral difference that is
> invisible except when it fails to fail.
Again, up to this point, this fits in with what was intended...
> I know about the behavioral difference. I'm not talking about a technical conflict,
> I'm talking about a conflict in the mind of the developer. Given function(array $a, (array)
> $b){} the difference between $a and $b is a very advanced distinction and will be completely lost by
> the average developer..
I actually think that it's not that advanced of a distinction, but
agree to disagree there.
> The confusion is made worse by the fact that function(array $a) works, but function(int $a)
> doesn't, but function((int) $a) does. I know why, but the average developer just learning PHP
> for the first time won't get it at all.
I won't argue that, but I would make the assertion that there are far
more dangerous things that PHP does that the average developer just
learning PHP won't get. But again, let's go on...
> Sometimes I think you miss the point on purpose.
>
> In the docs substr is defined as:
> string substr ( string $string , int $start [, int $length ] )
>
> If I wanted to write the same thing in my own code I would have to write:
> function my_substr ( (string) $string , (int) $start , (int) $length )
>
> One syntax for the docs, a different one in my code.
Now, finally we get to a solid point. I didn't make the connection to
the parameter hinting in the docs that you meant. You said "syntax in
the docs", and I was thinking about the casting syntax, which is why I
asserted that both the syntax and the behavior are inline with the
docs.
We were both right, just talking about very different things.
Now, with that said, I completely see your point.
> Well, if you argue that this proposal is actually a typecasting enhancement and not a parameter
> type enhancement, then yes, you'd be right. That's not how this is presented though,
> that's not where it is presented (Scalar Type Hinting discussion), that's not when it was
> presented, and that's not how it is getting perceived or measured.
Well, I think that's part of the problem here. People (including both
you and me) have so much vested in this discussion, that they are
reading things into the proposal that aren't there (both in a good
way, and a bad way).
> As far as expanding type casting in this way, it doesn't make sense. There is no
> precedent, it looks and will get treated like parameter hinting (which you are saying it
> isn't), there is no additional functional value, and very little value of any sort beyond casts
> (just a tiny documentation boost and a savings in the number of characters in the few cases where a
> dumb type cast is good enough.)
Well, I think there's a bit more to be gained on both the static
analysis front and the IDE integration front. Additionally, defensive
coding now only needs to worry about 1 type, and it puts the onus to
ensure proper results on the caller (which is where I would argue it
belongs)...
> Again, yes, I know that the RFC takes a position on this. My point is not that the RFC
> doesn't take a position, my point was that the position taken "ignores the need that would
> have caused this sort of code in the first place."
It took a position, because there seemed to be a fair bit of concensus
on the list (in current and past dicussions) that this sort of thing
should explicitly disallow references. I haven't seen much to the
opposite until:
> Reference parameters are basically return values. Just because a parameter will return a value
> doesn't mean that the type no longer matters. In fact, it means that the calling function
> should EXPECT the type to change, and EXPECT the value to be modified. One example that occurs to me
> off hand is preg_match, where the 3rd parameter is documented as an array reference. You can
> actually pass anything, but it's going to be an array when the function returns.
That's completely fair. But I'd argue that it's also never going to
be consistent, since the cast only relies on the passing of the
variable, not the return:
function foo ((int) &$foo) {
$foo = array();
}
$a = 1;
foo($a);
How the heck did $a become an array, when it was passed as an int?
> You can't raise errors like this on lossy casts. Giving a warning if an implicit
> conversion loses data (123 + '456xyz', or substr('foo', 'bar')) makes
> sense, but if I explicitly write (int)'456xyz' or (int)23.7, I must not get a warning
> about data loss (otherwise it would be difficult/impossible to force a deliberately lossy conversion
> without warnings). Since we can't raise warnings on casts, you really won't be able to do
> it with casted parameters either (unless you're willing to accept a consistency break). These
> will be stuck in silence forever.
Absolutely we can. The key is not raising errors on all casts, but
distinguishing between explicit and implicit casts. Explicit casts
always succeed (not sure if that's a good thing IMHO), and implicit
casts error. I would consider passing a variable to a hinted
parameter would count as an implicit cast, since it's happening
**after** the call begins, which means it would issue an error...
> Well, if that is the case, you did not succeed. The FC break you originally worked to avoid is
> something that can never happen anyway, and this does not avoid the most critical FC break.
Well, then what's the point?
> First, "strict" types (in the sense of not allowing an integer to be passed to a
> string parameter) are never going to happen in PHP. Even C++ looks for an implicit conversion and
> uses that if available. PHP has well defined implicit conversions between scalars, and there is
> absolutely no chance that PHP is ever going to implement any form of typing that is more strict than
> typing in C++. A strict set of scalar types hint that don't juggle anything is just not in the
> cards.
To be clear, PHP does not have a well defined implicit conversion
between scalars. It has at least 3 of them (actually more, but I'm
not going to count). Doing $a + 1 causes one set of conversions.
Doing substr($a, 0) does another. Doing echo $a does another (yes,
zend_parse_parameters and make_printable_zval have different (albiet
slightly) logic).
> Second, (bear with me) the form of typing that people seem to have settled on before this RFC
> was introduced is "the same typing as the core, but at the language level." To use a prior
> example, the core has:
> string substr ( string $string , int $start ){...}
>
> and the following behavior:
> substr('foo', 'bar'); // E_WARNING
> substr(123, '1'); // '23'
>
> I should be able to write an equivalent:
>
> function my_substr ( string $string , int $start ){..}
>
> and I should get matching behavior:
> my_substr('foo', 'bar'); // E_WARNING
> my_substr(123, '1'); // '23'
>
> Now here's the point, if somehow this proposal were accepted and incorporated into the
> language it would make it nearly impossible to later achieve the above. Having both would be
> confusing, because the behavioral difference is extremely narrow. Your syntax at that point really
> just silences lossy implicit conversions and would actually be more similar to what one might expect
> from:
> function my_substr ( @string $string, @int $start ){..}
Fair enough...
>> Sure. But I'd argue that anything except foo(int $foo) would have lead to FAR more
>> confusion.
>>
>
> I don't think any other syntax is even an option. This syntax is used by existing type
> hints in PHP, and in the PHP documentation, and in basically all generated library documentation,
> and used for parameter types in every syntactically similar language.
Now we understand each other fully...
> And reusing that syntax leads this straight into the dead end indicated previously when talking
> about the FC objective.
Point taken.
I've withdrawn the parameter hinting RFC.
I truely thank you for helping me understand your concerns. I only
wish they could have been shared more clearly at the POC phase so we
could have avoided this altogether...
Thanks,
Anthony