Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:92616 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 26963 invoked from network); 21 Apr 2016 22:42:41 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 21 Apr 2016 22:42:41 -0000 Authentication-Results: pb1.pair.com header.from=dmitry@zend.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=dmitry@zend.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain zend.com designates 157.56.111.106 as permitted sender) X-PHP-List-Original-Sender: dmitry@zend.com X-Host-Fingerprint: 157.56.111.106 mail-bn1bbn0106.outbound.protection.outlook.com Received: from [157.56.111.106] ([157.56.111.106:58392] helo=na01-bn1-obe.outbound.protection.outlook.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 11/49-14036-E5759175 for ; Thu, 21 Apr 2016 18:42:39 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=RWSoftware.onmicrosoft.com; s=selector1-zend-com; h=From:To:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=cu8iX7wZ6Q+SgTVhOjssZLUBad3FoCVjSispLTT1L2Q=; b=LPY30CibEC5IDRwOsoWOPz1chVgdtr8E327GIPwnLl8u+f+n6MfyexfnjH1Co+Fvem/d+ieAYtgUytUnxUx6xmdHS2/N7Ja8JhmDeo9qcI3jY3FWchHhuGPwTrlfy+uD0xEaNnAI0lfbnbOjXj9/F/R7FrILAIZBCw3xXKbwM7w= Authentication-Results: gmail.com; dkim=none (message not signed) header.d=none;gmail.com; dmarc=none action=none header.from=zend.com; Received: from tpl2.home (92.62.57.172) by SN1PR0201MB1791.namprd02.prod.outlook.com (10.162.228.21) with Microsoft SMTP Server (TLS) id 15.1.466.19; Thu, 21 Apr 2016 22:42:31 +0000 To: Larry Garfield , , Nikita Popov References: <57194B85.60507@garfieldtech.com> Message-ID: <5719574D.9010900@zend.com> Date: Fri, 22 Apr 2016 01:42:21 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.1 MIME-Version: 1.0 In-Reply-To: <57194B85.60507@garfieldtech.com> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [92.62.57.172] X-ClientProxiedBy: CO1PR06CA049.namprd06.prod.outlook.com (10.242.160.39) To SN1PR0201MB1791.namprd02.prod.outlook.com (10.162.228.21) X-MS-Office365-Filtering-Correlation-Id: 3a628f29-5245-4fb0-b539-08d36a363af4 X-Microsoft-Exchange-Diagnostics: 1;SN1PR0201MB1791;2:jdiJHaM4PeobFk1DUvNun52EcMeJHCPxEog8dYfDUajh/sdedz1Kl66VOuXvI/t7/OEHirSWUEOnsT96pZZPaEr21xITNSCDc8a7iWv782JJk7UnE+EPP5MkyS0iprCzzrLNC2/CnMWhSJrlkV1ujPiC4Fjj7uF3lr/y8L0/V8uFNYclpPtJ9iu74vOJLfxN;3:QIW5yTvsDqR5vgi/mqOhJpz7BVueU3b3MkEqhMDnAN2RYRxcJsygTdBK3FDMdIro5W1irSMAkzMwpzfeExVwXPC1MvccZ7WlzuD9zmOfm+eKeHVTsRzd3SeD0IbowTuI X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:SN1PR0201MB1791; X-Microsoft-Exchange-Diagnostics: 1;SN1PR0201MB1791;25:c6c8tx9PjNC2fbMFAnwUjt51rTi/VZmEZB6ytrzaA2wMwgfLzT032+FxjyyEH0gDfB5Sjt83PxvBKF7ZQHuq3GpeaG2XjjgRA4BXWEIaq4val0pwE2EVf/pDq3ksEFu/oqi5XqxoL3xowtZ/g5dzp+JRU6XWpmAe7rxNl6ZHkw+F3GHj7bqIYxo/cmfxTfRC9b/xfZf8sZwNAyPRVyN7JAidMnkfTEGHNYIpo5f0ZDiM2tJebCFBysv6s/MvSrvmGpJk9d3qjKS4s07OVPMYYsD86+n+ojzX4LQccoXMgLGCrSLmiY6X2M+FQ0649PsKOA/7jz3MDW562/2sxtcMVeSspKsD8185hHWnWr/T8cqLrC44u0yM6naXOw39bDCZ2H2AlAq45Sne70LN8rEY6T6Sfqbrr+yeyT2udVE+JJt3DB8sa5urZak+CB/fffZOSM7V4jZllRQpJJ9dTdQPCmmz6zaukCN9vlt04NV8iGiMQYgHnhzLNz/PBTfbpPeaPbEOVXqh992Xb0/PniEQeTkgw7dDUeFyOI2GIAGBMKEUsWTBKh4McepnInr9umM2XkCx3Yj2mFf61Gs/olroicRS8D+KUwqnwNsXLX6R38RCnekJAr8wvtz6hNZ0y4PV8WngXK6mjgsQC9JkHjh6yVxm56xsdQ4X6omlKE+1JhCb/yhrTWyLNdJ1zmCrCwgBIrC8BI4W+SPh4oRwVszohTeTKneyUGuIYC4b6K7lN5M388bq6segpcl0J7PX8/EriDnluKZX/zzjIZKkBRQikw== X-Microsoft-Exchange-Diagnostics: 1;SN1PR0201MB1791;20:feUecu2UNUv4wAAlrCmWCKl3u54onmSiztS0diEUL3WtAUUZ8NX4XW4D3VQyluQRwQm0z/d/7jLeg+X2bXtMyEB+Vn1ol0nXyqicvDatIUNQRiENpvrqJLliFM9PVar1BmCnEfSBoV+E6+AQqjRsc2UBHLXbr+vD4Whaw0F0eMVsGBx+UJkxT6i+e4D676wxCXZ3sft46N2ymnaKqOxmEo59fRxVyaQCW8xi72WOlVBJ9HpmjhCPZlPTBHE5g1lJ8KNzHeBlk967Id809bkNYeBqoByEpHY3FbC+ouv0YLmazwiGt9bTHHRfTJ2h085insfhTtfVotvbCw6L3GMMosH3qBk6pzBtHnNBIUe9Wm3Zna4nmsDlvjRSeDV685oPDmtFvGJdrb6DA+1rhBf2SaDwDrUwrLgQTGCpRQkMtGovdKME5LHWyqJSWf4mrV2BxTZO1tefb93vfhAFeEwuAiWbxD52syvWsv8MW8zHvb4T7+TKSIqE99kJpg8iuaI4;4:DwHv0DlvRZnHol3D+5EEc5GveQI3mQbAeg5MW3VE3rqhNtgpPRQxCONzje88nr2agutopo2+la6VOA40oeL+OhstlWg0Mc89GN6vMT+F2KA3Dibf20otEJmH/M7Wrlxc5SUGJTCkpcCJVlKfk5L4G+Fmr+umd/YmdIgRfgIcBmk1npOoHSkp0lBnPj6T0JxT2MVk/L1T8tYZjA4+0bDLiNkzpsv9U6eGoq/+A3R9DV3WL+y5iK3mTj4NmIyStR3FjtKmpcHfbBpXPAWl738W5v8y/9yYTVrLAEgzAhUkyH6DNcIjbvhvBE2CeH8s+0ElA3eQ58I+0jMDe41MEahxPE4pQiABGgpFwu7H4pdtC/SMrYvCJghtuW3/Y9gdLL46r3UiVvD3VP9a2T3WxCWmHA== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(9101521026)(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046);SRVR:SN1PR0201MB1791;BCL:0;PCL:0;RULEID:;SRVR:SN1PR0201MB1791; X-Forefront-PRVS: 091949432C X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(24454002)(377454003)(42186005)(561944003)(33656002)(65956001)(92566002)(36756003)(107886002)(5004730100002)(47776003)(5001770100001)(64126003)(2950100001)(76176999)(6116002)(77096005)(99136001)(586003)(1720100001)(189998001)(23746002)(65816999)(50986999)(86362001)(4001350100001)(5008740100001)(50466002)(15975445007)(54356999)(87266999)(83506001)(230700001)(81166005)(66066001)(19580395003);DIR:OUT;SFP:1102;SCL:1;SRVR:SN1PR0201MB1791;H:tpl2.home;FPR:;SPF:None;MLV:sfv;LANG:en; X-Microsoft-Exchange-Diagnostics: =?Windows-1252?Q?1;SN1PR0201MB1791;23:D0dujU3rueht1gXH7p770VOi082HCxjC77n?= =?Windows-1252?Q?rpGuoEcGmfvwRn1N16tSD9FDQnNlUzv41sIAf5Xt3vwHBZwAxiTWN0+9?= =?Windows-1252?Q?h3YlEN217DxpOnMptYXf8zG+lpwBytSnLbGPPJwit0QQq+lAy0LHu/6l?= =?Windows-1252?Q?LkJH9rFbLAzDqH1W1KYLTinZ60Kcb270bndoaS/kFN5jQOrU86XUjMTl?= =?Windows-1252?Q?rlhb/7r1T3hMtFIfHosmIfEWyuEeJTQqyw6gZ/rN7G2ficMUV+Rfgddh?= =?Windows-1252?Q?Z+poZ1SEGJL46T2lk1s8yFnQA49zPopAYYkkjHp5tkFwOmXJ13Uen+tb?= =?Windows-1252?Q?xXOLYlDcCV8VpeP+KRChv08c0nOXNgRiPc204U8e/SC3AS4Y8dzlVR54?= =?Windows-1252?Q?OMWTYnRVRuFWbLkMKsFSpR/kgdQJB1ZNsc14JqPYvFy2Z2YGmV+rkYm4?= =?Windows-1252?Q?a4qRpNcZyii15tHWcx5tj7dVo19KhIsHYYjFcg7jslbZQKdmAi8PSvlr?= =?Windows-1252?Q?ElZJ0WfoqG4g3XNOUgv2l+7Y+PCPj13kFxXyFjWTEACKD3fEmDoQGKl7?= =?Windows-1252?Q?rOXG141SJjxpWAkr16E+8KbZDgrJjSTgQzYJrX1bLN1XM6D8XWL75WP2?= =?Windows-1252?Q?zywEf2yXSTBRPCcYQkZ3V71vy81wr22DVBxm/4YIjAomNFXLSjNEFeqp?= =?Windows-1252?Q?etBkduxEqa/FhWGFQRmnx89Z7JO1kcwxL66sNvk889ZDmmgk7/RfvSP8?= =?Windows-1252?Q?Bw7KWWbb+9TdJzFR6pchiuvO4fQXH0HD64xH3//VMRodrfIhIQ31Vcyw?= =?Windows-1252?Q?XESHHex8oyfkyIdbJ4zH0n6C9KGxDCL+EMZj4iGs3ndcE5gZkmtuN3Z1?= =?Windows-1252?Q?rdoyvEdHRqHIv8se09nNJcvlGsvUmWxq4m9u5WM8I2JlJTM6x5+wfxn8?= =?Windows-1252?Q?xaHFBKZtomI8kCB9RWDp2TC1DqFWrmow0+Fxz9RKV84JVq55BC4IGuoT?= =?Windows-1252?Q?dDZ/8HCXWfh4Q8ZNboBZMVnJMfc5iGs5oTZj1d6eY9NxSE5ZclajrSdI?= =?Windows-1252?Q?cKEcoUVFbsyIOLKTdkKuYc+EdOAG+phGogRZC9I365peuC9Atpol0rEq?= =?Windows-1252?Q?6C/DX2F2LKBuA7pakv/XT7lM=3D?= X-Microsoft-Exchange-Diagnostics: 1;SN1PR0201MB1791;5:bd3VPnl/cjVI/aS4YaRn9KAN11Odbc+q8ACUEd/OjL6zqE9CGR9baddSBmj2VVnDzrwEgsX0euEWMLh782kEUZM5cuswSLaNBoIEsZYt3Hu5mQsACDlVyYc57ILhZW3jHWvQ8TjuhCufLB7DRZLY/WxEXvK3YM6DTfNbiBBRN1fKs1bPVhrVIgahZ0ht7MLV;24:wKlWz2dKUDS9/zfTG7lDzrrf9lw7UOczkuNnCC86DlAIai9QdlnE0iGCwlx+VPAoEssiflGO4Des4UBgQZP71dthvDbf4wYR6C4wsSdC0EA=;7:wfCBYgHjfpvfOCv6mxRA68IM5J/P7EJ9JsTzM63zPS3kMI2ZVrwHmUQ0IFH9xdi+w5S+GBp8gp7qYlNQpLaY74NjkBb2VC3JddBH01sS4fOBPbNy9LPDSNnUwYhbxy8NUeilMewCE5EbbMa0UY1usUoZi/OeFaNYSWO5gHA+701Wt7c9j8qZP7qM+H+q6JABrEIwmwBwPCrDzD8Kta08oYiwRvpZzKT2CKJdJT7zGr8= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: zend.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Apr 2016 22:42:31.6764 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR0201MB1791 Subject: Re: [PHP-DEV] [RFC] PHP Attributes From: dmitry@zend.com (Dmitry Stogov) On 04/22/2016 12:52 AM, Larry Garfield wrote: > On 4/21/16 4:13 PM, Dmitry Stogov wrote: >> Hi, >> >> >> I would like to present an RFC proposing support for native annotation. >> >> The naming, syntax and behavior are mostly influenced by HHVM Hack, >> but not exactly the same. >> >> The most interesting difference is an ability to use arbitrary PHP >> expressions as attribute values. >> >> These expressions are not evaluated, but stored as Abstract Syntax >> Trees, and later may be accessed (node by node) in PHP extensions, >> preprocessors and PHP scripts their selves. I think this ability may >> be useful for "Design By Contract", other formal verification >> systems, Aspect Oriented Programming, etc >> >> >> https://wiki.php.net/rfc/attributes >> >> >> Note that this approach is going to be native, in contrast to >> doc-comment approach that uses not well defined syntax, and even not >> parsed by PHP itself. >> >> >> Additional ideas, endorsement and criticism are welcome. >> >> >> Thanks. Dmitry. > > Thanks, Dmitry! In concept I am in favor of syntax-native > annotations, although I have some concerns with the specifics of the > proposal. Thoughts in no particular order: > > First, for the getAttributes() reflection method, please oh please > don't return array-or-false. That's horrible. Just return an empty > array if there aren't any, as that makes getAttributes() entirely type > safe and saves all callers from a mandatory if-check. (See > http://www.garfieldtech.com/blog/empty-return-values for more > information.) Makes sense. I may change this. > > The reflection section further indicates that the type of the result > is variable, which means I cannot know in advance if I'm going to get > back a scalar or an array. If we go with this free-form approach, I'd > honestly prefer to always get back an array, even for single value, so > that I can always know the type I'm dealing with. (Since I cannot > enforce a given attribute to be single-value.) I'm not sure yet. both decisions may make sense. If I expect just a single value, I'll have to check the number of elements (or just ignore values above the first). > > For the expression example: > > < 0)>> > function foo($a, $b) { > } > > > It is not at all clear to me what scope the annotation's $a and $b > exist in. Are the they same $a and $b as in the function signature? > If so, what happens if I reflect the function before ever calling it? This is just an AST. It may contain any valid PHP expression syntax, but variable, functions and constants don't have to be valid. > How can I evaluate test? I hope this functionality will be provided by php-ast extension. Currently, it is not a problem to reconstruct PHP source from AST and then use regular eval(). In general, we may find a more efficient way. > Or are they inherited from the global scope at the time of > declaration? (That scares me a great deal.) I don't know what to > make of that at all. AST is going to be mainly used by extension and pre-processors (like AOT and DBC), but in general, they also may be used directly in scripts. < 0)>> function foo($a, $b) { ast_eval(RefelectionFunction(__FUNCTION__)->getAttributes()["test"]); } > DB > In the "Attribute syntax" section, the text says the tokens are the > left and right double-angle character, as used for quotations in some > European languages. The rest of the text says it's two left/right > carrot characters, as seen above the comma and period on US > keyboards. I'm assuming the former is just a typo/auto-correct bug. yeah, computers think they are too smart :) > > If I read correctly, the following two would be semantically identical: > > <> > function foo() {} > > <> > <> > function foo() {} right > > Is there a reason you chose the name "attribute" rather than > "annotations", which seems at least in PHP to be the more common term > for this type of declaration? I took the name from HHVM. Personally, I don't care about naming at all. > > > It appears that the annotations themselves are entirely free-form. no. they are parsed according to PHP expression syntax rules. syntax mistakes in attributes are going to be caught at compile time. > At the risk of expanding the typing debate, this concerns me as then > all we're adding is a new way to parse undocumented, undefined > anonymous structs. How can I say what annotations mean what for my > ORM, or routing system, or whatever? We're back to, essentially, > out-of-band documentation of big anonymous structs (aka associative > arrays). > > A more robust alternative would be something along the same lines that > Doctrine uses: Make annotations actual classes. To wit: > > > <> > <> > <> > function foo($a, $b) { } > > Where AThing, AnotherThing, and MoreThing are defined classes, and > subject to namespaces and use statements. Then what gets returned > from getAttributes() is an array consisting of an instance of AThing, > an instance of AnotherThing, and an instance of MoreThing. In this > example we'd just call their constructors with the listed values and > let them do as they will. Doctrine uses named properties in the > annotation that maps to properties on the object, which is even more > flexible and self-documenting although I don't know how feasible that > is without opening up the named properties can of worms globally. This is just a next level. Attributes are just a storage of meta-data. You may use them as you like :) function getAttributesAsObjects($r) { $ret = array(); $a = $r->getAttributes(); foreach ($a as $name => $val) { $ret[] = new $name(...$val); } return $ret; } > > Either way, the advantage then is that I know what annotations are > available, and the class itself serves as documentation for what it > is, what it does, and what its options are. It also helps address > collisions if two different libraries both want to use the same > keyword; we already have a class name resolution mechanism that works > and everyone is familiar with. > > One concern is that not all classes necessarily make sense as an > annotation; perhaps only classes with a certain interface can be > used. Actually (thinking aloud here), that would be a possible > solution to the named property issue. To wit: > > < 'a', b => 'b')>> > foo() {} > > class AThing implements Attribute { > public static function attributeCreate(array $params) { > return new static($param['a'], $param['b']); > } > } > > $r = new ReflectionFunction('foo'); > $a = $r->getAttributes(); > > $a is now an array of one element, an instance of AThing, created with > 'a' and 'b'. The specifics here are probably terrible, but the > general idea of using classes to define annotations is, I think, a big > step forward for documentation and avoiding multi-library collisions. > > While I know some of the things Drupal 8 is using annotations for are > arguably excessive (and I would agree with that argument in some > cases), as is I fear the proposed system is too free-form and > rudimentary for Drupal to switch to them. > We can't use classes and object in storage directly, because they may be defined in different PHP script, may be changed between requests, etc. but as I showed, it's very easy to construct corresponding objects on request. Thanks for deep review and good suggestions. Dmitry.