Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 5/6/2016 8:02 AM, Dmitry Stogov wrote: > On 05/06/2016 05:06 AM, Jesse Schalken wrote: >> If you're going to say "do what you want" with regards to annotations, >> then >> just let them be a text string. Parsing the annotation as PHP but not >> evaluating it as PHP seems a very strange and arbitrary half-way >> point. If >> the thing consuming the AST is expected to eval() it, then why didn't PHP >> do that already? If the thing consuming the AST is expected not to eval() >> it, then it must effectively implement it's own language sharing PHP's >> syntax but not PHP's semantics. Since it can't possibly attach meaning to >> all of PHP's syntax, PHP will enforce that the string is valid PHP even >> though the annotation language will be a very small subset. Not only does >> that buy you very little in terms of validity checking, but it constrains >> the annotation language to be a subset of PHP's syntax even when such a >> constraint may be entirely inappropriate. >> >> A true "do what you want" approach, if that is the right approach, >> would be >> for the annotation body to be a free text string. > > You talk about a subset of the proposed RFC. > It proposes an additional question about AST usage. > I think he is talking exactly about the proposed RFC, it is completely arbitrary and will lead to much confusion and it is not anymore useful than the current PhpDoc approach that we have in userland. Having an attribute grammar [1] adds overhead to PHP while parsing our files and removes only the regular expression stuff that is currently implemented in the annotation systems of all the software out there; which is at least offline. I do not see a single benefit in the current feature proposal. Especially since one can already run the content of a PhpDoc tag through the AST thingy and *bam* you have exactly the same thing. What we need is an annotation system that works for userland and not this attribute grammar crutch just because it is easier to come up with and agree upon. [1] https://en.wikipedia.org/wiki/Attribute_grammar -- Richard "Fleshgrinder" Fussenegger signature.asc Description: OpenPGP digital signature
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 05/06/2016 05:06 AM, Jesse Schalken wrote: If you're going to say "do what you want" with regards to annotations, then just let them be a text string. Parsing the annotation as PHP but not evaluating it as PHP seems a very strange and arbitrary half-way point. If the thing consuming the AST is expected to eval() it, then why didn't PHP do that already? If the thing consuming the AST is expected not to eval() it, then it must effectively implement it's own language sharing PHP's syntax but not PHP's semantics. Since it can't possibly attach meaning to all of PHP's syntax, PHP will enforce that the string is valid PHP even though the annotation language will be a very small subset. Not only does that buy you very little in terms of validity checking, but it constrains the annotation language to be a subset of PHP's syntax even when such a constraint may be entirely inappropriate. A true "do what you want" approach, if that is the right approach, would be for the annotation body to be a free text string. You talk about a subset of the proposed RFC. It proposes an additional question about AST usage. Thanks. Dmitry. On Fri, May 6, 2016 at 8:36 AM, Dan Ackroydwrote: On 5 May 2016 at 15:24, Larry Garfield wrote: because it doesn't define "right way". Good. I could easily see, for instance, Doctrine annotations building the first, PHPUnit the second, and Zend the 3rd. Good! It's not the job of PHP core to tell people how to use annotations. People can use them however they want. If it turns out that there is a single 'right' way of using them, everyone will gravitate to that way anyway. If it turns out there are different 'right' ways of using them for different use cases, people will be able to pick and choose the use-case that is most appropriate. And most importantly, if what people think is the 'right' way to use them evolves over time, that can be accomplished completely in user-land, without needing to update the internal implementation of annotations. cheers Dan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
If you're going to say "do what you want" with regards to annotations, then just let them be a text string. Parsing the annotation as PHP but not evaluating it as PHP seems a very strange and arbitrary half-way point. If the thing consuming the AST is expected to eval() it, then why didn't PHP do that already? If the thing consuming the AST is expected not to eval() it, then it must effectively implement it's own language sharing PHP's syntax but not PHP's semantics. Since it can't possibly attach meaning to all of PHP's syntax, PHP will enforce that the string is valid PHP even though the annotation language will be a very small subset. Not only does that buy you very little in terms of validity checking, but it constrains the annotation language to be a subset of PHP's syntax even when such a constraint may be entirely inappropriate. A true "do what you want" approach, if that is the right approach, would be for the annotation body to be a free text string. On Fri, May 6, 2016 at 8:36 AM, Dan Ackroydwrote: > On 5 May 2016 at 15:24, Larry Garfield wrote: > > because it doesn't define "right way". > > Good. > > > I could easily see, for instance, Doctrine annotations building the > > first, PHPUnit the second, and Zend the 3rd. > > Good! > > It's not the job of PHP core to tell people how to use annotations. > People can use them however they want. > > If it turns out that there is a single 'right' way of using them, > everyone will gravitate to that way anyway. > > If it turns out there are different 'right' ways of using them for > different use cases, people will be able to pick and choose the > use-case that is most appropriate. > > And most importantly, if what people think is the 'right' way to use > them evolves over time, that can be accomplished completely in > user-land, without needing to update the internal implementation of > annotations. > > cheers > Dan > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 5 May 2016 at 15:24, Larry Garfieldwrote: > because it doesn't define "right way". Good. > I could easily see, for instance, Doctrine annotations building the > first, PHPUnit the second, and Zend the 3rd. Good! It's not the job of PHP core to tell people how to use annotations. People can use them however they want. If it turns out that there is a single 'right' way of using them, everyone will gravitate to that way anyway. If it turns out there are different 'right' ways of using them for different use cases, people will be able to pick and choose the use-case that is most appropriate. And most importantly, if what people think is the 'right' way to use them evolves over time, that can be accomplished completely in user-land, without needing to update the internal implementation of annotations. cheers Dan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
Larry Garfield wrote on 05/05/2016 15:24: <> Translator)>> < > < > I could easily see, for instance, Doctrine annotations building the first, PHPUnit the second, and Zend the 3rd. Those would all be legal-ish, but semantically very different. And there's also then no guarantee that $foo >> Translator actually means a bit-shift (I don't even know what a bitshift in that case would mean) To add some context to these examples: the first is borrowing the overload of ">>" from C++ (meaning "pass to stream") or similar uses in Ruby; the second the use of "|" as a pipe in templating languages like Smarty and Twig (meaning "pass expression to modifier function") or good old Unix shell tradition; and the third is inspired by PostgreSQL and imagines the operator overloaded to mean something like "matches the XPath-like expression given". I'm not sure any of those interpretations would actually be useful in the realm of annotations, but operator overloading is the first thing that sprung to mind when I wondered what a domain-specific language would look like if it were constrained only to producing a valid PHP AST. Another trick could be to abuse brackets, e.g. "something(anything)" will parse as a function call, but needn't be interpreted as one. Regards, -- Rowan Collins [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 05/05/2016 02:07 AM, Dmitry Stogov wrote: Maybe that's what we want to have here - freedom for everybody to invent their own languages - but I fear the danger of fragmentation here and also people implementing tons of slightly different incompatible parsers for ASTs that are generated. We'd have Drupal attributes and Symphony attributes and Doctrine attributes and Zend attributes and so on, and each of them would have different semantics. Not sure this would be good. But maybe it avoids arguing about the syntax now. Today, we have the same with doc-comments. Attributes eliminate the need for separate parser and perform syntax validation at compile time. They also provide flexible syntax to support all existing annotation systems, but they can't solve semantic problems, because they are just meta-data. This, I think, is the key point of disagreement. The proposal does not, actually, provide enough functionality to be useful. It's a first step, but it doesn't go far enough to actually address the problem space. Because while it may provide rudimentary syntax validation (basically, is it a legal PHP string) it doesn't provide any semantic validation (it is a meaningful PHP string if interpreted the right way), because it doesn't define "right way". As Rowan noted, there are lots of technically-legal PHP strings that an AST would be totally fine with that are still completely different and incompatible as far as actually using them. To enhance his examples a bit: <> Translator)>> < > < > I could easily see, for instance, Doctrine annotations building the first, PHPUnit the second, and Zend the 3rd. Those would all be legal-ish, but semantically very different. And there's also then no guarantee that $foo >> Translator actually means a bit-shift (I don't even know what a bitshift in that case would mean), it could mean anything that Doctrine decided to mutate it into. Does the second example actually mean to pipe values, or could it also be parsed into something else? Are lower and escape function names, or magic values that my add-on parser knows? At that point, the only value-add over the status quo (hack the docblock) is a common lexer. But since the semantics are not guaranteed on top of that, it's really not that useful. I'm not fully convinced that all the way to Doctrine classes is the right alternative. It may be, it may not be, I'm not sure yet. But as someone who would be using this system in user-space, I am very convinced that the current proposal simply doesn't go far enough to be useful to me. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
Stanislav Malyshev wrote on 05/05/2016 07:48: The key idea of RFC was not to invite another language for meta-data, >but use PHP language itself. This is a good way to avoid handling a lot of issue, but what I am afraid of is that with this solution, what would happen that people start doing exactly that - inventing another languages for metadata. I tend to agree - what the proposal basically says is "here's a generic parser, invent a domain-specific language using that parser". Theoretically, people could implement all sorts of weird "operator overloading" behaviour: <> Translator)>> < > < > Do we really need or want that kind of flexibility, just to avoid agreeing a specific structure for metadata? Regards, Rowan Collins [IMSoP]
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 05/05/16 08:34, Dmitry Stogov wrote: >> I think this way can give a good start point with possibility to >> standardize handling of attributes in the future. From the PHP engine >> side, all attributes are AST nodes that can be processed later on the >> userland side. >> > Something like this may be implemented, but it should be well designed > and approved first. > I'm not sure if this functionality should be especially implemented as > part of Reflection API (this is easily implementable in PHP itself). > But in any case, this requires the base attribute functionality proposed > in RFC (or some other). That is all I'm asking ... I thought initially the rfc defined more than it does, but just creating another 'free for all' on how something is used seems a pointless exercise? -- Lester Caine - G8HFL - Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 05/05/2016 10:24 AM, Alexander Lisachenko wrote: Hello, internals! 2016-05-05 9:48 GMT+03:00 Stanislav Malyshev>: Maybe that's what we want to have here - freedom for everybody to invent their own languages - but I fear the danger of fragmentation here and also people implementing tons of slightly different incompatible parsers for ASTs that are generated. We'd have Drupal attributes and Symphony attributes and Doctrine attributes and Zend attributes and so on, and each of them would have different semantics. Not sure this would be good. But maybe it avoids arguing about the syntax now. AST for attributes is a nice thing for abstracting from the concrete details about how attribute is handling by the concrete implementation. I can see a lot of common with class autoloading - earlier there were a lot of custom loaders, thanks to spl_autoload_register() that defines a stack of callbacks responsible for loading classes by their names. And everyone uses custom class loader, but later PSR-0 and PSR-4 were described and adopted in composer, so now we have one general tool for that. What if we select the same direction with the stack of callback? How it should work: PHP engine stores all attributes in the plain AST without any transformations. This data should be accessible via ReflectionXXX->getAttributes(ReflectionAttribute::RETURN_AST). After that userland library can register a hook as attribute loader: e.g ReflectionAttribute::registerProcessor(SomeHandler::class, $isPrepend = true) or spl_attribute_handler_register(SomeProcessor::class, $isPrepend = true) Each processor is a class with two methods: interface AttributeProcessorInterface { public function supports(Php\Ast\Node $attributeNode) : boolean; /** @return mixed */ public function process(Php\Ast\Node $attributeNode); } After that if we call ReflectionXXX->getAttributes(ReflectionAttribute::RETURN_VALUE) PHP engine will call each processor and asks it if it supports this AST node. If processor supports this node, then engine call it's process($attributeNode) method, returning the result as a result, otherwise looks for another processor. If no processors can handle this AST then PHP can throw an exception about with information about missing processors for attributes. I think this way can give a good start point with possibility to standardize handling of attributes in the future. From the PHP engine side, all attributes are AST nodes that can be processed later on the userland side. Something like this may be implemented, but it should be well designed and approved first. I'm not sure if this functionality should be especially implemented as part of Reflection API (this is easily implementable in PHP itself). But in any case, this requires the base attribute functionality proposed in RFC (or some other). Thanks. Dmitry.
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
Hello, internals! 2016-05-05 9:48 GMT+03:00 Stanislav Malyshev: > Maybe that's what we want to have here - freedom for everybody to invent > their own languages - but I fear the danger of fragmentation here and > also people implementing tons of slightly different incompatible parsers > for ASTs that are generated. We'd have Drupal attributes and Symphony > attributes and Doctrine attributes and Zend attributes and so on, and > each of them would have different semantics. Not sure this would be > good. But maybe it avoids arguing about the syntax now. > AST for attributes is a nice thing for abstracting from the concrete details about how attribute is handling by the concrete implementation. I can see a lot of common with class autoloading - earlier there were a lot of custom loaders, thanks to spl_autoload_register() that defines a stack of callbacks responsible for loading classes by their names. And everyone uses custom class loader, but later PSR-0 and PSR-4 were described and adopted in composer, so now we have one general tool for that. What if we select the same direction with the stack of callback? How it should work: PHP engine stores all attributes in the plain AST without any transformations. This data should be accessible via ReflectionXXX->getAttributes(ReflectionAttribute::RETURN_AST). After that userland library can register a hook as attribute loader: e.g ReflectionAttribute::registerProcessor(SomeHandler::class, $isPrepend = true) or spl_attribute_handler_register(SomeProcessor::class, $isPrepend = true) Each processor is a class with two methods: interface AttributeProcessorInterface { public function supports(Php\Ast\Node $attributeNode) : boolean; /** @return mixed */ public function process(Php\Ast\Node $attributeNode); } After that if we call ReflectionXXX->getAttributes(ReflectionAttribute::RETURN_VALUE) PHP engine will call each processor and asks it if it supports this AST node. If processor supports this node, then engine call it's process($attributeNode) method, returning the result as a result, otherwise looks for another processor. If no processors can handle this AST then PHP can throw an exception about with information about missing processors for attributes. I think this way can give a good start point with possibility to standardize handling of attributes in the future. From the PHP engine side, all attributes are AST nodes that can be processed later on the userland side.
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 05/05/2016 09:48 AM, Stanislav Malyshev wrote: Hi! It's also possible to write: <> you don't need to split your annotation into many attributes. You should just adopt its syntax to become a valid PHP expression. This expression is not going to be evaluated. It's going to be just parsed into AST. and then you may traverse this AST and transform it into other data structures. The key idea of RFC was not to invite another language for meta-data, but use PHP language itself. This is a good way to avoid handling a lot of issue, but what I am afraid of is that with this solution, what would happen that people start doing exactly that - inventing another languages for metadata. In fact, that's exactly what the expression above does - it uses "=" as named argument, ops, "=" actually should be replaced with "=>", or this won't work. and uses @ as special tag, not like PHP does. So it's in fact mini-language using PHP's AST parser to tokenize its grammar, but having separate semantics. right. RFC doesn't propose any semantic, but higher layer may define completely different semantic. Maybe that's what we want to have here - freedom for everybody to invent their own languages - but I fear the danger of fragmentation here and also people implementing tons of slightly different incompatible parsers for ASTs that are generated. We'd have Drupal attributes and Symphony attributes and Doctrine attributes and Zend attributes and so on, and each of them would have different semantics. Not sure this would be good. But maybe it avoids arguing about the syntax now. Today, we have the same with doc-comments. Attributes eliminate the need for separate parser and perform syntax validation at compile time. They also provide flexible syntax to support all existing annotation systems, but they can't solve semantic problems, because they are just meta-data. Thanks. Dmitry. we don't have fully constructed classes at compile time. Classes may be used during transformation from plain arrays and AST into application specific data structures. We don't have classes but we do namespace resolution right? For namespace resolution, you don't need to have the class actually present. I don't think we need it for ::class either. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
Hi! > It's also possible to write: > > <"id" = "system_branding_block", > "admin_label" = @Translation("Site branding") > ]))>> > > > you don't need to split your annotation into many attributes. You should > just adopt its syntax to become a valid PHP expression. > This expression is not going to be evaluated. It's going to be just > parsed into AST. and then you may traverse this AST and transform it > into other data structures. > The key idea of RFC was not to invite another language for meta-data, > but use PHP language itself. This is a good way to avoid handling a lot of issue, but what I am afraid of is that with this solution, what would happen that people start doing exactly that - inventing another languages for metadata. In fact, that's exactly what the expression above does - it uses "=" as named argument, and uses @ as special tag, not like PHP does. So it's in fact mini-language using PHP's AST parser to tokenize its grammar, but having separate semantics. Maybe that's what we want to have here - freedom for everybody to invent their own languages - but I fear the danger of fragmentation here and also people implementing tons of slightly different incompatible parsers for ASTs that are generated. We'd have Drupal attributes and Symphony attributes and Doctrine attributes and Zend attributes and so on, and each of them would have different semantics. Not sure this would be good. But maybe it avoids arguing about the syntax now. > we don't have fully constructed classes at compile time. Classes may be > used during transformation from plain arrays and AST into application > specific data structures. We don't have classes but we do namespace resolution right? For namespace resolution, you don't need to have the class actually present. I don't think we need it for ::class either. -- Stas Malyshev smalys...@gmail.com -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 05/01/2016 10:47 PM, Larry Garfield wrote: On 04/30/2016 06:21 PM, Rowan Collins wrote: On 30/04/2016 23:45, Stanislav Malyshev wrote: Oh, of course you can have methods, but then it is strange conceptually - you have a normal class, which some other part of the language just uses for something else that classes are not routinely used for. I.e., does it call a constructor? When? With which arguments? What if it fails? What if I just create an object of this class - would it be the same as annotation object? Hm... I was going to say "well, PDO does this if you use PDOStatement::fetchObject"; but then I remembered that the integration with the object there IS a bit weird - it injects raw properties, and *then* calls the constructor. So, I'm not sure there's a limitation in terms of the object being data-only per se, but there are certainly oddities to be dealt with in terms of construction. And as you mentioned, mutability leads to another set of oddities - are the mutations stored for next time you request that annotation, or is the object recreated on each access? Regards, It would never occur to me to not have it regenerated on each access. If I want to cache it I will do so myself, thanks. :-) However, that is not an issue created by using a defined structure for the annotation result. The RFC currently says it returns an associative array, aka anonymous struct. Those are always highly mutable. The RFC proposes only Reflection*::getAttributres() that returns by value. You may modify the returned copy, but the original attributes are immutable. Thanks. Dmitry. A classed object is as mutable as its design allows it to be. To wit: <<__Annotation>> class Definition { protected $foo; protected $bar; public function getFoo() {} public function getBar() {} } <1, bar => 2)>> class Meep {} The resulting annotation object would be an instance of Definition, which is for practical purposes immutable. If it were returned as an array ['foo' => 1, 'bar' => 2], that would obviously be mutable. Whether Definition should have mutator methods on it then becomes the implementer's decision, which is probably for the best. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 04/30/2016 02:47 AM, Larry Garfield wrote: Most of the examples that have been given so far are either trivial boolean flags or data validation rules to be evaled. In practice, very little of Drupal's use of annotations in Drupal 8 fit either category. Rather, they're used primarily as, in essence, a serialized metadata object describing a class, which is used for registering that class and potentially others. I figured I'd give the proposed syntax a try with some Drupal examples and see how well it fit. Disclaimer: I'm sure someone will pipe up with "your use case is invalid because you shouldn't be using annotations that way." I will be the first to agree that Drupal loves to take everything it does to an extreme, and some things may be better done other ways. However, these are still real-world use cases (currently built with Doctrine Annotations) that people are going to want to try and reimplement eventually using a core language feature. This much data is put in one place primarily for DX reasons, to give developers a one-stop-shop for defining a given extension. Saying "well just abandon your approach entirely" is not a satisfying answer. Summary: It doesn't fit well at all, and there's features missing that would prevent Drupal from being able to use the proposed attributes RFC as-is, even without talking about classes-as-annotations. A series of improvement request/suggestions are listed at the end of this email. Simple example: Drupal plugins (usually) use annotations. Here's a simple example: /** * Provides a block to display 'Site branding' elements. * * @Block( * id = "system_branding_block", * admin_label = @Translation("Site branding") * ) */ class SystemBrandingBlock { } This defines a "block" (type of plugin). It's unique machine name identifier is "system_branding_block", and its human-facing label is "Site branding", which is marked as a translatable string. That all seems reasonable to include here. Here's what I came up with for a possible attributes version: <> < > < > class SystemBrandingBlock { } Not too bad at first blush, but there's 2 problems. It's also possible to write: < > Then you'll need you own layer that translates "Drupal" attributes from AST to everything you like. 1) There's no indication that the label is a translatable string. One could hard-code that logic into whatever processing happens for PluginAdminLabel, but then there's no indication for our gettext scanner that "Site branding" is translatable and should be extracted for translation. 2) If we want to say that the value "Block" corresponds to a class (something that would be up to the parser to do), there's no indication of the namespace against which to resolve "Block". The alternative would be to require including the full class name string, like so: < > But that DX is quite terrible. We introduced ::class in 5.5 for a reason. Better would be: < > But that works only if the attribute parser resolves Block::class against the currently "use"d namespaces so that it's a full class name string when reflection picks it up. If not, then that means the user-space parser needs to catch that, then go back to the file and figure out the available use statements and resolve against those. It's doable, but ugly and certainly more work than I'd want to put in as someone writing such a parser. I don't know if that's a feature of the patch at the moment, but it would need to be. So even in a simple case we have insufficient functionality. Complex example: OK, let's go to the other end and look at an example that is way more complicated. (Yes, maybe too complicated.) Doctrine annotations are also used to define Entity Types, which correspond to a class. Here's the annotation for a Node, in all its glory: /** * Defines the node entity class. * * @ContentEntityType( * id = "node", * label = @Translation("Content"), * bundle_label = @Translation("Content type"), * handlers = { * "storage" = "Drupal\node\NodeStorage", * "storage_schema" = "Drupal\node\NodeStorageSchema", * "view_builder" = "Drupal\node\NodeViewBuilder", * "access" = "Drupal\node\NodeAccessControlHandler", * "views_data" = "Drupal\node\NodeViewsData", * "form" = { * "default" = "Drupal\node\NodeForm", * "delete" = "Drupal\node\Form\NodeDeleteForm", * "edit" = "Drupal\node\NodeForm" * }, * "route_provider" = { * "html" = "Drupal\node\Entity\NodeRouteProvider", * }, * "list_builder" = "Drupal\node\NodeListBuilder", * "translation" = "Drupal\node\NodeTranslationHandler" * }, *
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 4 May 2016 10:41 pm, "Rowan Collins"wrote: > > > You could either think of this as "setting lots of variables": > > new Foo { $bar = 1, $baz = 2 } > > or you could think of it as "an object literal like an array literal": > > new Foo { 'bar' => 1, 'baz' => 2 } > I think a $ is only necessary to disambiguate, ie between variable and constant. It isn't necessary as a prefix for properties when it is unambiguous that the thing is a property. Eg property access is ->foo, not ->$foo. I don't think the string literal syntax is appropriate for classes/structs/records which have a defined, static structure. You would use that when you're talking about a hash table/associative array/map/dict, for which the key is often an arbitrary expression. So I would go with plain property name without prefix. It certainly looks nicer in the context of annotations. > > And then we also need to think about sitting nicely with anonymous class syntax. Not to mention Joe's proposal for lexical scope: https://wiki.php.net/rfc/lexical-anon > AFAIK anonymous classes always start with "new class ..", so there would be no ambiguity. It would be an optional {...} part that follows a class instantiation, anonymous or not. > > For the record, I like the idea, if we can come up with a consistent plan for how these pieces of syntax will work together, and not paint ourselves into an ASCII-art hole... > It sounds like this conversation has been had before (but I'm not sure about instantiate-and-set-properties specifically), but nonetheless the problem remains and it's a common pain point for me and fellow devs. Annotations sound like the ideal time to address it since they also need to instantiate classes and set public properties in one expression.
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
Jesse Schalken wrote on 04/05/2016 13:20: (maybe there should be a $ before the property names, not sure) And there's the rub! :P When named parameters have been discussed before, there was a lot of bikeshedding over what the syntax should look like, and this is arguably a very similar feature. You could either think of this as "setting lots of variables": new Foo { $bar = 1, $baz = 2 } or you could think of it as "an object literal like an array literal": new Foo { 'bar' => 1, 'baz' => 2 } And then we also need to think about sitting nicely with anonymous class syntax. Not to mention Joe's proposal for lexical scope: https://wiki.php.net/rfc/lexical-anon For the record, I like the idea, if we can come up with a consistent plan for how these pieces of syntax will work together, and not paint ourselves into an ASCII-art hole... Regards, -- Rowan Collins [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On Sat, Apr 30, 2016 at 9:47 AM, Larry Garfieldwrote: > 3) Some way to provide a data definition for the annotation that can be > checked at compile time. This could be classes, a la Doctrine. It could be > a new Annotation type as others have suggested. It could be something > else, akin to a struct like Liz Smith keeps toying with. I'm flexible > here. But some way to provide a data definition for the annotation that is > more robust than "you get an AST for an associative array that you can eval > to an array yourself, good luck" is, I believe, mandatory for these to be > successful for more than the most trivial use cases. If that data > definition is a class or class-like type, that also resolves the namespace > question very easily. > > I would love it if annotations were just classes with public properties, and the annotation shorthand for instantiating and setting properties was generally avaliable. At the moment if you wish to instantiate an object and set some public properties, you have to use a temporary variable $album = new Album(); $album->name = "Albumius"; $album->artist = "Artistus"; $album->year = 2013; return $album; or define setters for all the properties so you can chain them return (new Album()) ->setName("Albumius") ->setArtist("Artistus") ->setYear(2013); or forego the benefits of classes and use an array return [ 'name' => "Albumius", 'artist' => "Artistus", 'year' => 2013, ]; C# has an "instantiate-and-set-properties" shorthand like this, which would be great to have in PHP: return new Album() { name = "Albumius", artist = "Artistus", year = 2013, }; and if you drop the "new" (and constructor parens are already optional) you've got a pretty good annotation syntax right there. <> < > < > So the annotation syntax could just be class instantiation without the "new". (maybe there should be a $ before the property names, not sure)
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
Hey Stas, On 1 May 2016 at 00:14, Stanislav Malyshevwrote: > > $def instanceof MyAnnotation; //TRUE > > That looks fine, however the problem is that if MyAnnotation is a class, > then PHP does not have multiple inheritance, so it's the only class it > can be. And given that your class has no methods, $def has no methods > either and can not have any semantics besides simple data object. Which > begs the questions: Note that an annotation usage here is basically a constructor call for a concrete instance. Still, this doesn't deny implementing interfaces for annotations, then implementing those on the concrete annotation class. I don't see the need for multiple inheritance therefore. a) why it needs to be a class/object at all Usually as a replacement for what you'd have as a "struct" in C. Having a class definition provides some basic security on what is going on (type-hints, etc). You probably wouldn't ever have behavior on an annotation though, since it is just a data structure: in fact, most of the existing annotations in PHP userland libs are currently just classes with constructor+public properties. Cheers, Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
Hi! > It would never occur to me to not have it regenerated on each access. If I want to cache it I will do so myself, thanks. Not sure why would you care. These should be value objects, so they should keep no state and as such it shouldn't matter when they are generated and how many of them. > However, that is not an issue created by using a defined structure for > the annotation result. The RFC currently says it returns an associative > array, aka anonymous struct. Those are always highly mutable. A > classed object is as mutable as its design allows it to be. To wit: As far as I can see, the RFC says it would return an array of RFC nodes. Now, it is true that array itself is mutable, we don't have immutable containers really, but that's not what I meant. The AST Node should not be really mutable. > <<__Annotation>> > class Definition { > protected $foo; > protected $bar; > public function getFoo() {} > public function getBar() {} > } Except for definitions of $foo and $bar - for which I don't see much use - this is exactly what I proposed, only as a class and not interface. I've already explained why interface is better :) > <1, bar => 2)>> Again, here we have named arguments problem. Note that you're using diffrent syntax for named arguments than last time :) -- Stas Malyshev smalys...@gmail.com -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 04/30/2016 06:21 PM, Rowan Collins wrote: On 30/04/2016 23:45, Stanislav Malyshev wrote: Oh, of course you can have methods, but then it is strange conceptually - you have a normal class, which some other part of the language just uses for something else that classes are not routinely used for. I.e., does it call a constructor? When? With which arguments? What if it fails? What if I just create an object of this class - would it be the same as annotation object? Hm... I was going to say "well, PDO does this if you use PDOStatement::fetchObject"; but then I remembered that the integration with the object there IS a bit weird - it injects raw properties, and *then* calls the constructor. So, I'm not sure there's a limitation in terms of the object being data-only per se, but there are certainly oddities to be dealt with in terms of construction. And as you mentioned, mutability leads to another set of oddities - are the mutations stored for next time you request that annotation, or is the object recreated on each access? Regards, It would never occur to me to not have it regenerated on each access. If I want to cache it I will do so myself, thanks. :-) However, that is not an issue created by using a defined structure for the annotation result. The RFC currently says it returns an associative array, aka anonymous struct. Those are always highly mutable. A classed object is as mutable as its design allows it to be. To wit: <<__Annotation>> class Definition { protected $foo; protected $bar; public function getFoo() {} public function getBar() {} } <1, bar => 2)>> class Meep {} The resulting annotation object would be an instance of Definition, which is for practical purposes immutable. If it were returned as an array ['foo' => 1, 'bar' => 2], that would obviously be mutable. Whether Definition should have mutator methods on it then becomes the implementer's decision, which is probably for the best. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 30/04/2016 23:45, Stanislav Malyshev wrote: Oh, of course you can have methods, but then it is strange conceptually - you have a normal class, which some other part of the language just uses for something else that classes are not routinely used for. I.e., does it call a constructor? When? With which arguments? What if it fails? What if I just create an object of this class - would it be the same as annotation object? Hm... I was going to say "well, PDO does this if you use PDOStatement::fetchObject"; but then I remembered that the integration with the object there IS a bit weird - it injects raw properties, and *then* calls the constructor. So, I'm not sure there's a limitation in terms of the object being data-only per se, but there are certainly oddities to be dealt with in terms of construction. And as you mentioned, mutability leads to another set of oddities - are the mutations stored for next time you request that annotation, or is the object recreated on each access? Regards, -- Rowan Collins [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
Hi! > What would prevent the class from having methods? > > class MyAnnotation > { > public $foo; > public $bar; > public function doStuff() { ... } > } Oh, of course you can have methods, but then it is strange conceptually - you have a normal class, which some other part of the language just uses for something else that classes are not routinely used for. I.e., does it call a constructor? When? With which arguments? What if it fails? What if I just create an object of this class - would it be the same as annotation object? How the "multiple annotations" syntax in RFC would work - what <> means - one object with two parameters or two objects with one parameter? What < 0)>> actually gets? Maybe that should work but all these should be then defined. > I don't see any more need for multiple inheritance here than in any > other class definition. There kind of is if we want annotations to have additional capabilities as annotations - e.g. the AST things. -- Stas Malyshev smalys...@gmail.com -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 30/04/2016 23:14, Stanislav Malyshev wrote: $def instanceof MyAnnotation; //TRUE That looks fine, however the problem is that if MyAnnotation is a class, then PHP does not have multiple inheritance, so it's the only class it can be. And given that your class has no methods, $def has no methods either and can not have any semantics besides simple data object. What would prevent the class from having methods? class MyAnnotation { public $foo; public $bar; public function doStuff() { ... } } I don't see any more need for multiple inheritance here than in any other class definition. -- Rowan Collins [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
Hi! > <> Here you have essentially created a named parameter syntax. That may be a problem later, especially if we do implement named parameters and this won't be the syntax we choose. > $def instanceof MyAnnotation; //TRUE That looks fine, however the problem is that if MyAnnotation is a class, then PHP does not have multiple inheritance, so it's the only class it can be. And given that your class has no methods, $def has no methods either and can not have any semantics besides simple data object. Which begs the questions: a) why it needs to be a class/object at all and b) how would you support all those fancy AST things if you can't even call methods on it. Of course, this is solvable by various way, but looks a bit clunky conceptually. You expect classes to work in a certain way and attributes to work in a slightly different way, at least with current proposal. > MyAnnotation can then have whatever other methods I feel like to > access/mutate those values. If that requires limiting MyAnnotation in Mutable annotation is a very bad idea. That's BTW another problem of defining it as class - we don't have real means to express immutable value classes yet, not without some boilerplate. That's why interface is better - it allows you to do immutability cleanly. > That's essentially the same concept as I described above with the > class. Putting annotations on the object being created seems like a Very similar, expect for: 1. Interface allows you to have richer semantics since you can implement other interfaces and have other classes. Class pretty much limits you to value object unless you do dirty tricks which essentially turn it into interface. trait may be a bit in-between solution, but I didn't really think about it yet, so there may be problems there. 2. You have no mutability issues. 3. You don't confuse template with actual data - i.e., with class, if I just instantiate it, would it be a valid attribute? Of what? 4. You still can make complex attributes return ASTs. > reasonable way to handle nested annotations at first glance, although it > still doesn't resolve the main issue of Translatable which is that we > scan the source code statically to find translatable strings. (We look That can be solved by making translatability a property of an attribute, not a string. That looks to me a better design anyway - if you have a button, what would it mean if its label sometimes translatable and sometimes not? I'd expect translatability to be requirement of a context - i.e. if we use string to display a button, it's translatable. Note that it doesn't mean it *has* translations for every language - you can't ensure that anyway - but it has the *option*. And if you make it a property of the attribute itself, then your tool can have the list of translatable attributes and then extract the values for these attributes for translation. That also makes more sense to me for translation - to translate properly, you need to know the context of the string, same text can translate differently depending on the context, so you'd want to know what value you're translating. -- Stas Malyshev smalys...@gmail.com -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 04/30/2016 04:12 PM, Stanislav Malyshev wrote: Hi! That you for bringing real usage examples. This is an interesting point to consider. Reading through it, however, I can't help but wonder why these things are not just data? I mean, why they are kept in the comments? If there are reasons like performance, there could be solutions developed, and "keeping things together" doesn't exactly work when the things are 2-screen-long data array and I presume equally complex class - they are two separate and independent entities anyway, and their synchronization has to be explicitly managed anyway, nobody can ensure they are in sync just by looking at it - in fact, given its size, nobody can *anything* just by looking at it. It's not really human-readable anymore than database dump is human-readable - the data is there, true, but it's not exactly how you'd prefer to interact with it. That said, of course I imagine there are reasons why Drupal developers made these choices, and I don't think it makes much sense to argue about them now. I just outlined my first impression, but if it sounds wrong and uninformed, just ignore it :) It does, however, makes sense arguing about whether it is something we have to support directly in the language, and to which lengths we should go to do so. At the risk of turning this into a Drupal tutorial (I will try not to), let me try to explain in brief: In previous Drupal versions, such data would be provided in an "info hook". That is, a magically named function that returns a deeply nested array of data that registers "stuff" with the system. That "stuff" was pretty much completely and utterly undefined, and as it was all anonymous structs (aka associative arrays) extremely hard to document. There's also often a corresponding "alter hook" (we still have those), which gets passed the full set of such data as a massive nested array by reference to manipulate. In addition, it was common to have the definition hook in one file and any code it referred to in another. In a few cases it was a class, but in other cases it was a template file, or a series of other magically named functions that could technically live anywhere. All kinds messy. :-) Moving that registration metadata into the same file as the thing it's describing was done for DX reasons: If you want to add a new plugin to Drupal (and there are several dozen kinds of plugin available in Drupal 8, each with a corresponding interface), you have one single class file to edit, usually a base class to extend, and you're done. It makes adding new plugins and registering them really easy. Where the plugin then gets used is up to user configuration "elsewhere". Entities are implemented as just very complex plugins, sort of. (Disclaimer: I disagreed with this decision for a variety of reasons, but lost that battle.) In the complex entity case I showed, the registration information includes: 1) Base definition information common to any plugin (unique ID, human-friendly label, etc.) 2) database information (tables, keys, etc.). Honestly I think a next version of this system shouldn't allow for user control in that area and they should be fully automated. 3) Various handlers. Many of these are essentially services that are coupled to a specific entity type. Trying to register them all via the container, though, would again spread out the work for a particular developer across a lot more places in a lot more contexts. A few are form definitions that get instantiated as ordinary forms in a certain context. 4) Hooks into various other automation tools. In the ideal case, defining an entity class and its annotation, if you include the appropriate data, will result in about a dozen routes getting created with stock, auto-generated UIs and permission controls already baked in. It will integrate with the Views system (Drupal's content assembly / GUI query builder), access control, database-level revisioning, translation, serialization, and so forth. Basically, all of the cool user-facing automation that is why one uses Drupal is "just there", and because the UI is by default auto-generated it's very consistent for end users. Again, all of that could be done elsewhere (just like Doctrine entity annotations could be done via YAML or PHP arrays, too), but having it all together in one place instead of 15 that need manual synchronization of service names and such is a big DX win. Also, I mentioned we still have alter hooks to allow other modules to manipulate that definition, but they now get a keyed array of ContentEntityType objects rather than anonymous arrays. This is a good thing. (I guess I failed at not making this a Drupal tutorial.) Most of that data would not make sense on the object itself, because it's used in a completely different context. We do not have a node, or user, or comment object on hand when we need that data. Amusingly, we don't even
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
Hi! That you for bringing real usage examples. This is an interesting point to consider. Reading through it, however, I can't help but wonder why these things are not just data? I mean, why they are kept in the comments? If there are reasons like performance, there could be solutions developed, and "keeping things together" doesn't exactly work when the things are 2-screen-long data array and I presume equally complex class - they are two separate and independent entities anyway, and their synchronization has to be explicitly managed anyway, nobody can ensure they are in sync just by looking at it - in fact, given its size, nobody can *anything* just by looking at it. It's not really human-readable anymore than database dump is human-readable - the data is there, true, but it's not exactly how you'd prefer to interact with it. That said, of course I imagine there are reasons why Drupal developers made these choices, and I don't think it makes much sense to argue about them now. I just outlined my first impression, but if it sounds wrong and uninformed, just ignore it :) It does, however, makes sense arguing about whether it is something we have to support directly in the language, and to which lengths we should go to do so. > defining a given extension. Saying "well just abandon your approach > entirely" is not a satisfying answer. I would not say "abandon your approach" - what works for you works for you, so trying to convince you otherwise would be wasting your time. I would say that if somebody is developing a new system and are considering this approach - I *would* advise checking a different direction. That is to say, I would be perfectly happy if PHP had annotations that do not support such use case, at least not directly. I know that sounds somewhat insensitive to Drupal developers, and that's not my intent do dismiss their concerns, but I think we should not take it as a primary requirement, sine qua non. My opinion is good design should figure out the best use cases for the feature and serve them as much as possible, without trying to overload the system to serve every need and every use case there could be. Doing 80% of cases well is much better than doing 99.999% cases poorly. My opinion is hundred-element data dumps are well outside of the 80% for annotations. If whatever design we end up with supports it - great, if it doesn't - that's fine too. > * @Block( > * id = "system_branding_block", > * admin_label = @Translation("Site branding") > * ) Why not do just: @Block([ "id" => "system_branding_block", "admin_label" => Translation("Site branding")]) Or, in current RFC syntax: <"system_branding_block", "admin_label" => Translation("Site branding")])>> Now, we get to a touchy issue of how arrays can be consumed by annotations clients and what "Translation" is. Here we have two news, as it should be, good and bad: - Good news is that AST makes kind of easy to have Translation have any semantic the client wants - Bad news is that currently RFC provides no tools for actually operating on deeper data structures, AFAIK. If such tools are provided, then I don't see why this won't work. Also, of course, namespacing is a must, but that was already discussed and I think being taken care of. > Yoinks. Now let's try and turn that into attributes. Here's my first Here it's more complicated, because some data items clearly should be different annotations, like "handlers" - these are probably something like: < > < > etc. and some others may be data. Hard to know without understanding true semantics of the thing. > OK, let's take that to its logical conclusion and directly map in the > full annotation: > < Additionally, even then it's still "just an array", by which I mean an > anonymous struct, by which I mean "you get no help at all on typos." > You may have noticed that I typoed "route_provder" instead of > "route_provider" above. An an array key, that is a silent runtime error > that's crazy hard to debug. Forcing any meaningful data structure into > anonymous structs is doing everyone a disservice. (As a Drupal > developer, I can attest to that fact with personal scars.) True. If we had named parameters, we could probably
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
On 04/29/2016 11:54 PM, Pierre Joye wrote: Hi Larry, On Apr 30, 2016 6:48 AM, "Larry Garfield"wrote: Most of the examples that have been given so far are either trivial boolean flags or data validation rules to be evaled. In practice, very little of Drupal's use of annotations in Drupal 8 fit either category. Rather, they're used primarily as, in essence, a serialized metadata object describing a class, which is used for registering that class and potentially others. I figured I'd give the proposed syntax a try with some Drupal examples and see how well it fit. Disclaimer: I'm sure someone will pipe up with "your use case is invalid because you shouldn't be using annotations that way." What I would like to say yes. Very very loudly. But I am not sure about what is what or what defined what in your complex example Do you have a link to the source file so I can make an informed reply please? Sure. The block annotation is defined here: http://cgit.drupalcode.org/drupal/tree/core/lib/Drupal/Core/Block/Annotation/Block.php And the particular block plugin that I showed is here: http://cgit.drupalcode.org/drupal/tree/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php The annotation for a content entity is here: http://cgit.drupalcode.org/drupal/tree/core/lib/Drupal/Core/Entity/Annotation/ContentEntityType.php And the Node class is here: http://cgit.drupalcode.org/drupal/tree/core/modules/node/src/Entity/Node.php Note that in both cases I omitted the base class definition and such to focus on the annotation. Drupal does make excessive use of inheritance. I have been vocal about this problem for some time, but it will take a little while for enough people to experience the pain of poor design choices for them to get on board with better ones. Nonetheless, an annotation system in core should be informed by real-world usage, and Drupal is now a very significant real-world usage. Also note that because Drupal is so heavily configuration driven, many many things must be more dynamic and abstracted than they would in any bespoke system. That's why Drupal tends to over-do so many things; it's necessary to achieve runtime-configuration-driven data modeling and display business logic. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal
Hi Larry, On Apr 30, 2016 6:48 AM, "Larry Garfield"wrote: > > Most of the examples that have been given so far are either trivial boolean flags or data validation rules to be evaled. In practice, very little of Drupal's use of annotations in Drupal 8 fit either category. Rather, they're used primarily as, in essence, a serialized metadata object describing a class, which is used for registering that class and potentially others. I figured I'd give the proposed syntax a try with some Drupal examples and see how well it fit. > Disclaimer: I'm sure someone will pipe up with "your use case is invalid because you shouldn't be using annotations that way." What I would like to say yes. Very very loudly. But I am not sure about what is what or what defined what in your complex example Do you have a link to the source file so I can make an informed reply please?