Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:80086 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 46996 invoked from network); 2 Jan 2015 09:16:43 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 2 Jan 2015 09:16:43 -0000 Authentication-Results: pb1.pair.com smtp.mail=ocramius@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=ocramius@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 74.125.82.43 as permitted sender) X-PHP-List-Original-Sender: ocramius@gmail.com X-Host-Fingerprint: 74.125.82.43 mail-wg0-f43.google.com Received: from [74.125.82.43] ([74.125.82.43:58108] helo=mail-wg0-f43.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 71/B0-38471-8F166A45 for ; Fri, 02 Jan 2015 04:16:41 -0500 Received: by mail-wg0-f43.google.com with SMTP id k14so6115684wgh.16 for ; Fri, 02 Jan 2015 01:16:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=uUmc8n6Zx89WlWCYmXV2A2uOhwTZyHq0O8YGGlzmuCM=; b=P0hWIyHXbSCxnHtiqUH/xQFDo/Bv8rgN7ZalHutvWUM4bCSb7CR2Slg2R2Sp16nkC7 wxcvezlxizMKH/M+kZtB+OBM2XvpJ8qkCrxw9t/LlXP/CObhFAsfLt5Z4NOWAxdmQ+sp 1CD8t0DY38RWBn8r8a7OTvlFFjJBRVT1PrmK7pXwuhTvQmvKsR1uqPJogixHOpuDMAlR SFskc9aqyuduFWadVx6R+YpWwhznrihELHiUM6XwxzSnzHFgwmLBPWmimaVRBANGP2KQ QGCvaWkN7s4xVvUDEyJBay8zFfpSXe0C9jSSIc1MmlBkIO8U64MnC5JIzbYafVXQo41S yb8A== X-Received: by 10.180.97.7 with SMTP id dw7mr133931979wib.6.1420190197827; Fri, 02 Jan 2015 01:16:37 -0800 (PST) MIME-Version: 1.0 Received: by 10.194.82.163 with HTTP; Fri, 2 Jan 2015 01:16:17 -0800 (PST) In-Reply-To: <54A5DFCE.6030307@gmail.com> References: <41D5BB0B-73AF-488E-968D-90B2878E3178@ajf.me> <20150101164402.EB1442605AB@dd15934.kasserver.com> <54A5DFCE.6030307@gmail.com> Date: Fri, 2 Jan 2015 10:16:17 +0100 Message-ID: To: Stanislav Malyshev Cc: Thomas Bley , Andrea Faulds , Nikita Popov , PHP Internals List Content-Type: multipart/alternative; boundary=f46d044304404152a9050ba7ccfc Subject: Re: [PHP-DEV] [RFC] Scalar Type Hints From: ocramius@gmail.com (Marco Pivetta) --f46d044304404152a9050ba7ccfc Content-Type: text/plain; charset=UTF-8 On 2 January 2015 at 01:01, Stanislav Malyshev wrote: > Hi! > > > The problem is that the current proposed hints/casts are deviating from > the > > type-hints that we are used to, therefore this particular feature should > > Let's check the manual we're used to. > http://php.net/manual/en/function.substr.php > > string substr ( string $string , int $start [, int $length ] ) > > What "string" and "int" mean there? How they work? What we're > "deviating" from? I'm not sure why everyone is still taking the PHP manual as a good reference about how to write software: PHP internal functions are one of the main reason why this language is under-appreciated. The manual is pulling the concepts of `int`, `string` and so on out of thin air, whereas the correct syntax in those cases is `int|string|Stringable`, with explicit explanation of what those strings should look like. This is what you currently do in a real-world scenario (due to the lack of hints for internal types): class Shipment { public function __construct(ProductId $productId, $amount) { if (! is_int($amount)) { throw new InvalidArgumentException(sprintf('Provided $amount must be integer, %s given', gettype($amount))); } $this->productId = $productId; $this->amount = $amount; } } No allowance of weird values passed in: why would my software ever pass an invalid $amount to my constructor? That's where I'd put a hard-failing assertion instead. This is what I'd like it to be: class Shipment { public function __construct(ProductId $productId, int $amount) { $this->productId = $productId; $this->amount = $amount; } } Following code MUST cause a hard failure: new Shipment($bananasId, '1 of a whole lot'); This is constraining. Constraining has nothing to do with validation and casting: mixing the concepts of type-juggling, validation and constraining is a huge mess (which I don't like, but it's better than having nothing), and it would better be off using a syntax like: class Shipment { public function __construct(ProductId $productId, (int) $amount) { $this->productId = $productId; $this->amount = $amount; } } This makes the difference **much more clear**, as that `(int)` is not a constraint, it's a different, broader concept. I'd rather have the new behavior suggested by Andrea with a syntax that makes this subtle yet gigantic difference explicit. Additionally, the BC break concern of strict type-hinting and classes named `String`, `Int` and `Bool` (and similars) is delayed until we get strict type-hints, as the syntax is currently not allowed by the language and doesn't present any BC issues (http://3v4l.org/3Fqdh): function sum((float) $a, (float) $b) { } From an implementation perspective, it should just be a parser change. @Andrea: as for the "strict" and "non-strict" PHP suggestion you had before, please don't do that. Take following example: function repeat(int $amount, (string) $value) { $acc = ''; $i = 0; while ($i < $amount) { $i += 1; $acc .= $value; } return $acc; } As you can see, mixing implicit cast and strict constraining behaviors is perfectly fine in this case, so please don't include contextual switches: that would be even worse IMO. Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/ --f46d044304404152a9050ba7ccfc--