Hey guys!

The question if an integer is a stringable is pretty much the same as
the question if an stdClass is an iterable. Sure, you can iterate an
stdClass instance with a foreach, but does it qualify as an iterable?
Definitely not, and luckily it was not implemented as such.

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.

In other words: in a coherent type system any object that is stringable
would extend the string class and thus would go through any string type
constraint. This is something that we cannot implement anymore at this
point because we have no coherent type system.

    mixed (super type)
    |
    |- array              is_array
    |- bool               is_bool
    |- float              is_float
    |- int                is_int
    |- iterable           is_iterable
    |- null               is_null
    |- object             is_object || instanceof
    |- resource           is_resource
    |- closed resource    get_resource_type === 'Unknown'
    |- scalar             is_scalar
    |- string             is_string
    |
    void (bottom type)

We have a single root node, but we directly branch into many types
without any relation to each other, a relation always requires hard
coding. Iterable is the very first of those hard coded types which was
added to the runtime to bridge a gab, namely the gab between array and
any object that implements the Traversable interface.

Stringable would be the same as Traversable---hence the -able suffix
(and I would love it if it would be possible to simply have a String
interface but that is impossible)---and bridge the gab between string
and any object that implements the Stringable interface.

Now comes the next specialty that we need to deal with: magic methods.
Any object that provides a magic __toString method automatically
implements the Stringable interface, hence, there is none. I do not like
this, and I would never do something like this if I would design a
programming language or a type system, but here we are. (Note that Go
works like this everywhere, _urgs_.)

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 am open to other names, but I cannot come up with any that clearly
states its purpose: `CharBuffer`?

At this point we could also argue that any object with the magic
__toString method actually is a string. However, I believe that this
would be a crass change, which would definitely break code, e.g.:

    if (is_string($v) && $v !== '') echo $v{0};

We need a pseudo-type here! We most definitely require more pseudo-types
to bridge more of our root leaves. Number comes naturally (the union of
float and int which does not coerce to any of the two), an making scalar
available to userland might be handy too. A possible pseudo-type to
cover everything that can safely be converted to a string could be str
(like in Rust). But note that safely would cover many of our types
(namely bool, float, int, null, stringable objects, resources, closed
resources, and strings). However, I definitely see use cases for all
these types to be honest (think of a message formatter).

-- 
Richard "Fleshgrinder" Fussenegger

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

Reply via email to