Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:92613 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 21253 invoked from network); 21 Apr 2016 22:08:30 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 21 Apr 2016 22:08:30 -0000 Authentication-Results: pb1.pair.com header.from=kontakt@beberlei.de; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=kontakt@beberlei.de; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain beberlei.de from 74.125.82.42 cause and error) X-PHP-List-Original-Sender: kontakt@beberlei.de X-Host-Fingerprint: 74.125.82.42 mail-wm0-f42.google.com Received: from [74.125.82.42] ([74.125.82.42:35701] helo=mail-wm0-f42.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id DC/18-14036-D5F49175 for ; Thu, 21 Apr 2016 18:08:30 -0400 Received: by mail-wm0-f42.google.com with SMTP id e201so101928434wme.0 for ; Thu, 21 Apr 2016 15:08:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=beberlei-de.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc; bh=JzdxSJnfWcL4Cc4hYo6k/Eh6zNgJOWSZs4gUSCJfxD8=; b=mnp8+2K3JeTeykl2Apzi6QamkMvTs3Sr9Be3Ik6lT0G/O4kdHH4tjK++Z2K6pUnRkR SEx6YcgapH2GdRuSH/yiXtellu7nptnAsgpwyMwFei9xDN4vhpbefPoQPBkFJLuySWwb Z32veLeqc7dAdFpFGvLEKKErnC8Q0Kq/vdPnBQ/WgtUNcvGMvpVxwSMh7oxHCJNKSE4K 338nXe9i6+ZmiWGf5w9H6S6cHTMclhidY4yrz9nqzlEdeRJLw/YvjL739m39+f8Obgcj CkPXg6203S5P3u0ezmb5KwxyXK6HRrLZzw78iwBgJLVhVgCQgVYV9gErNBpCalbHDtSJ NwhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc; bh=JzdxSJnfWcL4Cc4hYo6k/Eh6zNgJOWSZs4gUSCJfxD8=; b=JgZ3mz923CeNbl6SjFu5qEj1EDxyz+8WODhejVhsccI3qYSLpUHp4HRUdy8ioArMWt xGlBrf119rCYiIoheIDR2UF+f1KZn8ErlVqY1DEJJx3z9cErLmUUmDkg3iYQcnYf67PF wnOR0xtJp32SlPl+cKTyUtlChoePFjATO0CiB3ShhtnHaJbGVB+JnSRRNqJPW5YmZN2K UcfNPd30tONLmPyrLh8bera9uoeGCkEzTN3A/s9RnKkXAbfAssKC9IRQN3tn1NuKa8ly dZh8pRJPd4LgecMe0cDzKiuiBDWRPeYvjwJUhvBCwy77syqDPnaGC2UtzMOlAyB+mvIl wEnw== X-Gm-Message-State: AOPr4FXL+erfgbHJE7zI6cf6pu85i+vwoBLCUrO7N95/bnEbq+9LNebxPat6FNQfmlBMFX3PmYOumrmzm60QZw== MIME-Version: 1.0 X-Received: by 10.28.128.143 with SMTP id b137mr223802wmd.57.1461276506023; Thu, 21 Apr 2016 15:08:26 -0700 (PDT) Received: by 10.194.94.163 with HTTP; Thu, 21 Apr 2016 15:08:25 -0700 (PDT) X-Originating-IP: [93.129.81.157] In-Reply-To: <57194B85.60507@garfieldtech.com> References: <57194B85.60507@garfieldtech.com> Date: Fri, 22 Apr 2016 00:08:25 +0200 Message-ID: To: Larry Garfield Cc: PHP Internals Content-Type: multipart/alternative; boundary=001a1141e52c0f8726053105f388 Subject: Re: [PHP-DEV] [RFC] PHP Attributes From: kontakt@beberlei.de (Benjamin Eberlei) --001a1141e52c0f8726053105f388 Content-Type: text/plain; charset=UTF-8 On Thu, Apr 21, 2016 at 11:52 PM, 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.) > > 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.) > > 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? How can I > evaluate test? 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. > They don't exist in any scope. You get an AST of this expression, what you do with it is entirely your choosing and you can set the scope/context yourself. > > 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. > > If I read correctly, the following two would be semantically identical: > > <> > function foo() {} > > <> > <> > function foo() {} > > 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? > > It appears that the annotations themselves are entirely free-form. 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. > I like that its just arrays, PHP is not exclusively OOP, so making this an OOP feature doesn't make sense to me. A library like Doctrine can always add the meaning on top, for example checking: <> class User { } Again resolving this against namespaces for example inside Doctrine Annotations itself, like its done right now. > > 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: > This is why it should be just arrays, using classes suddenly tons of special things can happen and must be thought of. > > < '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. You can build any kind of structure on top of $refl->getAttributes() inside your framework (Drupal in this case) > > > -- > --Larry Garfield > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > --001a1141e52c0f8726053105f388--