Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:98431 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 32474 invoked from network); 8 Mar 2017 15:44:40 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 8 Mar 2017 15:44:40 -0000 Authentication-Results: pb1.pair.com smtp.mail=php@fleshgrinder.com; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=php@fleshgrinder.com; sender-id=unknown Received-SPF: error (pb1.pair.com: domain fleshgrinder.com from 212.232.28.122 cause and error) X-PHP-List-Original-Sender: php@fleshgrinder.com X-Host-Fingerprint: 212.232.28.122 mx201.easyname.com Received: from [212.232.28.122] ([212.232.28.122:42559] helo=mx201.easyname.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 5A/A7-06022-6E620C85 for ; Wed, 08 Mar 2017 10:44:40 -0500 Received: from cable-81-173-135-7.netcologne.de ([81.173.135.7] helo=[192.168.178.20]) by mx.easyname.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1cldlU-0002y7-On; Wed, 08 Mar 2017 15:44:38 +0000 Reply-To: internals@lists.php.net References: To: Andrey Andreev , "internals@lists.php.net" Cc: Larry Garfield , Rowan Collins Message-ID: Date: Wed, 8 Mar 2017 16:44:27 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-DNSBL-PBLSPAMHAUS: YES Subject: Re: [PHP-DEV] [Discussion] is_string(), string type and objects implementing __toString() From: php@fleshgrinder.com (Fleshgrinder) 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