> From: Anthony Ferrara [mailto:ircmax...@gmail.com] 
>
> John,
>
> On Tue, Mar 6, 2012 at 9:04 PM, John Crenshaw <johncrens...@priacta.com> 
> wrote:
> > A good number of issues with the current proposal were raised during the 
> > discussion on the mailing list. I don't feel like digging them all up right 
> > now, but off the top of my head I remember the following being raised and 
> > never saw any consensus for how to resolve them:
>
> I went over the replies to the initial POC thread that I posted
> (http://marc.info/?t=133066037200001&r=1&w=2) and I'll rebut your replies.
>

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.

Most of your "rebuttals" focus entirely on whether the RFC contains sufficient 
information to make something technically work. That's not the point at all. 
I've read the RFC. I have no doubt that it "works", nor I think does anyone 
else. That's not the issue.

To quote a recent film: "Titan: Oh yeah? What's the difference? Megamind: 
PRESENTATION!". The code syntax is the UI that PHP presents to developers. Yes, 
this "works" (in the sense that it is possible to implement what the RFC 
describes), but there are serious usability and communication problems. 
Language is also one of the trickiest interfaces to work with because once you 
commit to something you are pretty much stuck with it forever (namespace 
separator). If every PHP developer is going to have to deal with this until the 
end of time it needs to be *awesome*.

> > - inconsistent syntax (one syntax for scalars, a different one for 
> > classes)
>
> This is actually discussed in the RFC, as it is not inconsistent (it's 
> actually consistent with what the patch tries to achieve).  The syntax for 
> classes and normal arrays is a strict check, where if the match fails an 
> error is thrown.  This syntax attempts to distinguish between that 
> functionality by providing a different syntax altogether.  And since it's 
> casting the parameters, the syntax feels natural (for that goal).
>

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.

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.

> > - conflicting syntax (I.E. array vs. (array), RFC simply "allows" 
> > this, and ignores the confusion that this will create for users.)
>
> Actually, it doesn't simply allow that.  It did it for a very specific 
> reason.  "array" is a strict check, and "(array)" is a casting check.
> One will fatal if a non-array is passed, and the other will attempt to 
> convert the parameter to an array.  Very different functionality, which are 
> both internally consistent with the other syntax...
>

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.

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.

> > - different from the syntax used in the docs
>
> Actually, it's the exact same syntax used for casting in the docs.
> It's different from class type hints, because it's intended to be so.
> If you don't like it, that's fine.  But it's intentionally different.
>

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.

> > - lack of sufficient function to justify a core change
>
> That's absolutely something to be considered.  However, I see erroring on 
> invalid casts as a bigger issue not the responsibility of a
> **casting** hint patch.  So that's why I mention explicitly in the RFC and my 
> blog post that solving that problem should be another RFC (culminating in a 
> series of 3 RFCs that each work together very well to fill the overall need).
>

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.

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.)

> > - chaos surrounding null (to accept and if so to cast or not? Creates 
> > a conflict between consistency and implications of the syntax)
>
> That's absolutely a valid concern.  And that's what should be being 
> discussed, if people really feel that the current implementation is wrong...
>
> > - conflicts with references (RFC tries to address this by simply 
> > disallowing references, which IMO just ignores the need that would 
> > have caused this sort of code in the first place.)
>
> Actually, it explicitly disallows references.  This was added because it was 
> explicitly requested on the list in many discussions (including the initial 
> one for the POC).  But if you can make a case on why to implement it, and why 
> it makes sense, then we can add it back.
>

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."

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.

> > There were others, but I'm not making an exhaustive list.
>
> Well, the ones that I saw were either rectified, requested (and
> implemented) or (to me) showed a lack of understanding about the rationale 
> and decisions (which is valid, but shouldn't really bear that much on the 
> discussion, as I feel if you want to raise an issue, you should at least have 
> a cursory understanding of what you're commenting about)...
>
> >> As far as it being crippled, I'm not sure what you mean, just because it's 
> >> only doing casting?
> >>
> >
> > Yes, casting is barely better than doing nothing. If I want a dumb typecast 
> > I can do that already. What I can't do without massive boilerplate 
> > everywhere is an intelligent conversion that accepts safe conversions and 
> > gives a warning or error on unsafe conversions.
>
> Again, I personally see casting data-loss a bigger issue than just parameter 
> hinting, which should get its own RFC to clean up.  That's why I didn't 
> include it here.  On purpose...
>

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.

> > Well, the big issue for me is that I think the type casting hints starts 
> > from a fundamentally bad foundation. The premise here is based on a syntax 
> > that is ugly and strange, and the syntax opens a bunch of new problems that 
> > I don't see a way to resolve. The reason for selecting this syntax was to 
> > avoid a BC break from reserving some new keywords. I don't really see this 
> > as a good trade.
>
> To be perfectly clear, the reason for that syntax was **not** to avoid a BC 
> break.  It was to avoid a FC break.  I wanted a casting hint, and I didn't 
> want to restrict the possibility of adding strict hints later.  And I wanted 
> to clearly distinguish the current strict hints (array + class) and the new 
> casting hints.  To me, the most logical way of doing that was to re-use the 
> casting syntax.  Could we have done foo(int? $foo) or foo(*int $foo) or 
> foo(@int $foo) or whatever?
>

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.

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.

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 ){..}

> 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.

> This way, it's re-using an existing syntax that **every** intermediate 
> developer is intimate with, and applying it to a case that's basically 
> functioning along the same lines...
>

And reusing that syntax leads this straight into the dead end indicated 
previously when talking about the FC objective.

John Crenshaw
Priacta, Inc.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to