Hi Richard,
Please note that I had drafted this before I saw your last e-mail, so I
think some of its points are now redundant. I'm sending it anyway, in
case it helps with further thoughts.
On 08/03/2017 15:44, Fleshgrinder wrote:
We can coerce an integer to a string but an integer is not a string. The
situation is different for an object that implements the __toString
method, since this object officially opted-in to the contract that it
can safely be used as a string.
The problem is in the definition of "safely convert".
If "safely" means "reversably", i.e. the cast is non-lossy, then an
integer can be "safely" converted to a string, but (for example) an
Exception object (which hasn't ) cannot:
$a = 42;
$b = (string)$a;
$c = (int)$b;
assert($a === $c);
$a = new Exception;
$b = (string)$a;
# Cannot convert back to Exception
To conclude: integers are not stringable because they are not part of
any of the two types (string + Stringable objects), just like stdClass
instances are not part of any of the two types that iterable covers.
This comes back to the same point I made to Ryan earlier: you have to
define this contract in terms of its implementation, not its purpose.
What is it that strings and Stringable objects have in common *other
than* their ability to cast to string? And since an integer can *always*
be cast to a string *and back again*, what makes it not stringable?
Going with the thought experiment of "Stringable" as an interface,
remember that interfaces implement a form of multiple inheritance. So we
don't need an ancestral relationship which links strings to ints, we can
just say that "int implements stringable". This seems perfectly
reasonable to me.
To conclude: integers are not stringable because they are not part of
any of the two types (string + Stringable objects), just like stdClass
instances are not part of any of the two types that iterable covers.
I don't think this is the same case at all; the problem with "iterable"
is that stdClass should never have been usable with foreach in the first
place. The relevant comparison is not to integers, but to objects which
don't implement __toString(). Until PHP 5.2, "$foo = new stdClass; $bar
= (string)$foo;" would actually give you a string
[https://3v4l.org/XDWTh]; not a very useful one, admittedly, but by pure
logic, any object in those PHP versions was "stringable".
I think it comes down to what you're trying to achieve: the language
can't have pseudo-types for every possible combination of types, so if
you want to detect integers as one case, and other things that can be
converted to string as another, just perform your checks in the right order:
if ( is_int($foo) ) {
// ...
} elseif ( is_stringable($foo) ) {
// ...
}
Regards,
--
Rowan Collins
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php