Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:101480 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 49872 invoked from network); 2 Jan 2018 10:58:24 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 2 Jan 2018 10:58:24 -0000 Authentication-Results: pb1.pair.com smtp.mail=tendoaki@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=tendoaki@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.161.175 as permitted sender) X-PHP-List-Original-Sender: tendoaki@gmail.com X-Host-Fingerprint: 209.85.161.175 mail-yw0-f175.google.com Received: from [209.85.161.175] ([209.85.161.175:36715] helo=mail-yw0-f175.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 0B/A3-23177-FC56B4A5 for ; Tue, 02 Jan 2018 05:58:23 -0500 Received: by mail-yw0-f175.google.com with SMTP id r205so11751466ywb.3 for ; Tue, 02 Jan 2018 02:58:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=cIyotDuATkmzvs+JiA2WzVgxniE+Fy0TzfKBtHYWwEQ=; b=KKM5eqwIzDvlHgmoA04eG3V3JDY7qjyDw3+yXMt0lcWyhelkKPr2lqY6+Abl4MklDi DeU6E1Lsf3oM/0xG0BbECfDnYPf44i1WraQEjHMn74PZhiaagmJ8/+WsBNUzmcwSBYwf 1DvSKL+ff4OA8fSia5Zk/joJvIgq8VpJh48RFbfb3U3oEX1u5fdgJOE7AEqNVuRE/4vJ xtq5pbOQKlH0c0DBI4YFXPo5VXAAwb/vb/mOPn7tNPrvfklBV5HnAwyKjQnLuHPTGEwY Z7FFIFgPaM1RAYgKxA+CMh8lqWXteuCZHLOJNkpI59CR79Q5qjWSHNZo2YXT+jOn/7cx St+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=cIyotDuATkmzvs+JiA2WzVgxniE+Fy0TzfKBtHYWwEQ=; b=rDXiTJ3OmKdSmK2l0C1tkvOlSULJe6OW9HuiwWtJo0XT30F0Z15SOcd0g4uvnTNE8c rY5BKzZqLVMhr1C+C2aOw4fpBhQFmbJbI0X9ql1aydrvV4H6IWKpZSoUt47JY3AslK2k uQzacmWDg1VzlEvJ9MeZiVO7ETM98d76JEEItYkwbVQszVSy2WXv8kdgoj0zFi2dvn2x XH0s3+gqRBA67MO3GqzsClNt3UFegCHpWdx0ryWtiuT2eXtOuOBcb6tvtfGui66O1t/U /HW8ubhd1H9e+zcpDI67dWP6c4ly/mjTNjaXtairae+DqM4Sjq8W/X7frLbGER1w/aD9 T6qQ== X-Gm-Message-State: AKGB3mJhk9Ru3OKzTgobg/rz+3/qzkeofP2snDimBdFTOQzxd125z4vI UGqDXhZb6DPiwgTFs4bbpmbTgWBJH5QSHVtRPeM= X-Google-Smtp-Source: ACJfBouKjhe4cl9OVhxRWq/oodBttGZy/QyRsYcaMz8L4J5jRb1KsYelPrvRiaFszNyBL+DJejwbBEyZYIJYgd7QifA= X-Received: by 10.129.128.69 with SMTP id q66mr32723315ywf.81.1514890700347; Tue, 02 Jan 2018 02:58:20 -0800 (PST) MIME-Version: 1.0 Received: by 10.37.201.7 with HTTP; Tue, 2 Jan 2018 02:58:20 -0800 (PST) Date: Tue, 2 Jan 2018 05:58:20 -0500 Message-ID: To: PHP internals Content-Type: multipart/alternative; boundary="94eb2c030b64115fbd0561c8fade" Subject: [PHP-DEV][RFC][DISCUSSION] Strong Typing Syntax From: tendoaki@gmail.com (Michael Morris) --94eb2c030b64115fbd0561c8fade Content-Type: text/plain; charset="UTF-8" Apologies for the double post - I missed a tag and I'm not sure the list server will send it along because of that mistake. I would like to propose a clean way to add some strong typing to PHP in a manner that is almost fully backward compatible (there is a behavior change with PHP 7 type declarations). As I don't have access to the add RFC's to the wiki I'll place this here. Before I begin detailing this I want to emphasize this syntax is optional and lives alongside PHP's default scalar variables. If variables aren't declared using the syntax detailed below than nothing changes. This is not only for backwards compatibility, but it's also to keep the language easy to learn as understanding datatypes can be a stumbling block (I know it was for me at least). VARIABLE DECLARATION Currently the var keyword is used to formally declare a variable. The keyword will now allow a type argument before the var name as so var [type] $varname; If the type is omitted, scalar is assumed. If Fleshgrinder's scalar RFC is accepted then it would make sense to allow programmers to explicitly declare the variable as a scalar, but in any event when the type is omitted scalar must be assumed for backwards compatibility. The variables created by this pattern auto cast anything assigned to them without pitching an error. So... var string $a = 5.3; The float of 5.3 will be cast as a string. For some this doesn't go far enough - they'd rather have a TypeError thrown when the assignment isn't going to work. For them there is this syntax string $a = "Hello"; Note that the var keyword isn't used. FUNCTION DECLARATION PHP 7 introduced type declarations. This RFC calls for these to become binding for consistency, which introduces the only backward compatibility break of the proposal. Consider the following code. function foo ( string $a ) { $a = 5; echo is_int($a) ? 'Yes' : 'No'; } Under this RFC "No" is returned because 5 is cast to a string when assigned to $a. Currently "Yes" would be returned since a scalar has the type that makes sense for the last assignment. I believe this is an acceptable break for two reasons. 1, the type declaration syntax is relatively new. 2, changing the type of a variable mid-function is a bad pattern anyway. OBJECT TYPE LOCKING Currently there is no way to prevent a variable from being changed from an object to something else. Example. $a = new SomeClass(); $a = 5; If objects are allowed to follow the same pattern outlined above though this problem is mostly solved.. SomeClass $a = new SomeClass(); var SomeClass $a = new SomeClass(); QUESTION: How do we handle the second auto casting case? $a is not allowed to not be a SomeClass() object, but there are no casting rules. We have three options: 1. Throw an error on illegal assign. 2. Allow a magic __cast function that will cast any assignment to the object. 3. Create a PHP Internal interface the object can implement that will accomplish what 2 does without the magic approach. Note that 1 will need to occur without implementation. 2 and 3 are not mutually exclusive though my understanding is PHP is moving away from magic functions. CLASS DECLARATION Again, by default class members are scalars. The syntax translates over here as might be expected. class SomeClass { public var string $a; protected int $b; private SomeOtherClass $c; public var SomeThirdClass $d; } Note a default value doesn't need to be provided. In the case of object members, these types are only checked for on assignment to prevent recursion sending the autoloader into an infinite loop. Also note that one of the functions of setters - guaranteeing correct type assignment - comes free of charge with this change. COMPARISON BEHAVIOR When a strongly typed variable (autocasting or not) is compared to a scalar variable only the scalar switches types. The strict comparison operator is allowed though it only blocks the movement of the scalar. Comparisons between strongly typed variables are always strict and a TypeError results if their types don't match. This actually provides a way to force the greater than, lesser than, and spaceship operation to be strict. FUNCTION CALLING When a strong typed variable is passed to a function that declares a variable's type then autocasting will occur so long as the pass is not by reference. For obvious reasons a TypeError will occur on a by reference assignment.. function bar( string $a) {} function foo( string &$a ) {} $a = 5.3; foo( $a ); // Works, $a is a scalar, so it type adjusts. var bool $b = false; foo( $b ); // TypeError, $b is boolean, function expects to receive a string by reference. bar($b); // Works since the pass isn't by reference, so the type can be adjusted for the local scope. CONCLUSION I believe that covers all the bases needed. This will give those who want things to use strong typing better tools, and those who don't can be free to ignore them. --94eb2c030b64115fbd0561c8fade--