Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:93695 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 7092 invoked from network); 1 Jun 2016 20:36:43 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Jun 2016 20:36:43 -0000 Authentication-Results: pb1.pair.com smtp.mail=jesseschalken@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=jesseschalken@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.214.50 as permitted sender) X-PHP-List-Original-Sender: jesseschalken@gmail.com X-Host-Fingerprint: 209.85.214.50 mail-it0-f50.google.com Received: from [209.85.214.50] ([209.85.214.50:35307] helo=mail-it0-f50.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 58/67-63812-A574F475 for ; Wed, 01 Jun 2016 16:36:42 -0400 Received: by mail-it0-f50.google.com with SMTP id z189so93531921itg.0 for ; Wed, 01 Jun 2016 13:36:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:sender:in-reply-to:references:date:message-id:subject :from:to:cc; bh=R5/jCDrskikgHkG9GozA8sl/QC580kIcZXuCq6hH9Pg=; b=WXqMpDl60DKO1lJDWlm3K+Xna2caNBcBgT+YBREUQG603Ruuz/2CNWZ7LUydBGLXIU hqa2LYZH0kMt7clp9c/+IiPNVilbCJM4vwmaCb2S+ZN5qB/D+kOQ53KZ8Yr1CllHkzxq mxAFMauq/MQGjA2yN8oeufPN4M6k1+DKGEZmYy5fpZpAWAWfI+A5pMWRqG3musU4FLU0 Me4MySyvMDnXlFqjpZslGpk/D6lpitUCI7ivG38SJnb6k2APB0Zx9zWdfud9ZNLQwG/5 mKfYkFzzF9F5Hpt4lPKot81yLw5XVsAz3tdnQyQ68lbPs58H4kyKWI52O8Yekv2hfQZV jnAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:sender:in-reply-to:references:date :message-id:subject:from:to:cc; bh=R5/jCDrskikgHkG9GozA8sl/QC580kIcZXuCq6hH9Pg=; b=T22/avPzHa8s0lqahr1vTycWOh8ZOcrwWy905KCT+T8GG7yeNk+QqhjbaX0Sec/d1S R8ICeutSI/Iz1TgNnixVDLKpgXGX7ZMNzb4TNDb1UIodEjjYiw/a98/BtcWK7M5Q2pr9 qrTYDQdcY//6utQ1r2zHmnLYeFm+A2VnWmj4Vpn52vipnFYHw7OPmP0bdAgT634PEtm7 SiX9M5UiNBnkyuu8WEohqgOBC6RT8ib5ZBnLP7Fg+XJqYv46h+hykJYBh5YZNE0vLGZe 8zOCDfdvQfIYEg4xH0XVqolT4vYkPEsRhXgKmEan/Cz/Kg24NkRHVnIYpEwUxZ88RJaB qBLw== X-Gm-Message-State: ALyK8tKIkjEM3wUdUQHCJlWeZcblBz0VPWMBQoXnPQDiqexOq+/4mdH0d9eIfgtT6hQnG4ipH3b9D3uV7YnjCA== MIME-Version: 1.0 X-Received: by 10.36.208.135 with SMTP id m129mr8161167itg.56.1464813399921; Wed, 01 Jun 2016 13:36:39 -0700 (PDT) Sender: jesseschalken@gmail.com Received: by 10.79.111.208 with HTTP; Wed, 1 Jun 2016 13:36:39 -0700 (PDT) In-Reply-To: References: Date: Thu, 2 Jun 2016 06:36:39 +1000 X-Google-Sender-Auth: mPRmFC7M6UJc156-gazlw_nAIDs Message-ID: To: "guilhermeblanco@gmail.com" Cc: Peter Cowburn , PHP internals Content-Type: multipart/alternative; boundary=001a1149a9545d6a4a05343d7288 Subject: Re: [PHP-DEV] Set object properties inline From: me@jesseschalken.com (Jesse Schalken) --001a1149a9545d6a4a05343d7288 Content-Type: text/plain; charset=UTF-8 On Thu, Jun 2, 2016 at 12:38 AM, guilhermeblanco@gmail.com < guilhermeblanco@gmail.com> wrote: > Hi, > > I very much liked the proposal, specially if we do consider a potential > reusability if anyone ever decide to revisit Attributes RFC. It's out of > scope how I'd see this implemented, so let me focus on the proposal only. > There're some edge cases that need to be discussed and considered here. > Here's one quick example: > > declare("foo", "bar"); > > class Foo { > public $bar; > } > > $f = new Foo() { > foo = "bar" > }; > > Should "foo" be considered as a property identifier or as a constant, > which would then be converted into "bar" and then used as $f->bar = "bar"? > My intention was for "expr->prop = ..." to be equivalent to "expr { prop = ... }", except obviously the result is the object itself and multiple properties can be assigned. So the property name is written directly as an identifier, and wouldn't be looked up as a constant. If expression property names are required I suppose it should mirror the "expr->{expr} = ...;" syntax and become "expr { {expr} ... }". Turns out there is already a "property_name" production in zend_language_parser.y (and also "member_name", but I'm not sure what the difference is), so the grammar would become: expr_without_variable: /* ... */ | expr '{' inline_set_properties '}' ; inline_set_properties: /* empty */ | property_name '=' expr | property_name '=' expr ',' inline_set_properties ; > > Regards, > > > On Wed, Jun 1, 2016 at 5:49 AM, Peter Cowburn > wrote: > >> On 1 June 2016 at 03:15, Jesse Schalken wrote: >> >> > Hi internals, >> > >> > I often have code dealing with plain old PHP objects with properties >> and no >> > methods, either as a substitute for keyword arguments, or to represent a >> > JSON or YAML document for a web service, configuration file or >> schemaless >> > database. >> > >> > At the moment, instantiating an object and setting public properties >> > requires a temporary variable for each object in the structure: >> >> >> > $obj1 = new Obj1(); >> > $obj1->prop1 = ...; >> > $obj1->prop2 = ...; >> > >> > $params = new FooParams(); >> > $params->prop1 = ..; >> > $params->prop2 = ...; >> > $params->prop3 = $obj1; >> > >> > $this->fooMethod($arg1, $arg2, $params); >> > >> > >> > For large structures, this gets verbose very quick. There is a good >> example >> > of this here >> > < >> > >> https://github.com/jesseschalken/fail-whale/blob/72870b37c4c21d19f17324a966344ec476b432a7/src/FailWhale/Introspection.php#L22 >> > > >> > involving >> > 18 unnecessarily variables. >> > >> > I can remove the local variables by defining setters for all the >> > properties: >> > >> > $this->fooMethod( >> > >> > $arg1, >> > $arg2, >> > (new FooParams()) >> > >> > ->setProp1(...) >> > >> > ->setProp2(...) >> > >> > ->setProp3((new Obj1()) >> > >> > ->setProp1(...) >> > >> > ->setProp2(...)) >> > >> > ); >> > >> > >> > But now for each property I have to spend an extra 3-5 lines of code >> > defining a setter, which is more code than it saved (unless the class is >> > used heavily enough). >> > >> > I could define __construct() taking every property as a parameter, but >> then >> > each property has to be mentioned another three times (four times with a >> > doc comment), and the type twice: >> > >> > class FooParams { >> > >> > public int $prop1; >> > // ... >> > >> > >> > public function __construct( >> > int $prop1 >> > // ... >> > ) { >> > >> > $this->prop1 = $prop1; >> > // ... >> > >> > } >> > >> > } >> > >> > >> > and where the object is constructed, it isn't immediately visible what >> the >> > meaning of each positional parameter is without some IDE assistance (eg >> > Ctrl+P in PhpStorm), and only specifying some parameters requires >> filling >> > preceding ones with defaults. >> > >> > I could also define the __call() method to automatically expose setters, >> > but then IDEs and static analysis can't understand what's going on (it >> > can't see that those methods exist, what their parameters are and what >> they >> > return). @method doc comments on the class help, but that's another line >> > for every property which I have to manually keep in sync with the real >> > properties. >> > >> > It would be great if there was a simple shorthand syntax for setting >> > properties on an object in-line, without needing to extract a variable: >> > >> > $this->fooMethod( >> > $arg1, >> > $arg2, >> > new FooParams() { >> > prop1 = ..., >> > prop2 = ..., >> > prop3 = new Obj1() { >> > prop1 = ..., >> > prop2 = ..., >> > }, >> > } >> > ); >> > >> >> While it's not as concise as your example, anonymous classes can do this >> already after a fashion. >> >> $this->fooMethod( >> $arg1, >> $arg2, >> new class() extends FooParams { >> // Constructor because prop3's value isn't a constant expression >> function __construct() { >> $this->prop1 = '...'; >> $this->prop2 = '...'; >> $this->prop3 = new class() extends Obj1 { >> public $prop1 = '...'; >> public $prop2 = '...'; >> }; >> } >> } >> ); >> >> >> > >> > >> > This way the structure can be written directly in the code as an >> expression >> > and FooParams and Obj1 remain simple containers for properties. >> > >> > The grammar might look like (I haven't used bison/yacc before): >> > >> > expr_without_variable: >> > /* ... */ >> > | expr '{' inline_set_properties '}' >> > ; >> > >> > inline_set_properties: >> > /* empty */ >> > | identifier '=' expr >> > | identifier '=' expr ',' inline_set_properties >> > ; >> > >> > >> > (Although I think that would conflict with the alternative $var{8} >> syntax >> > for array/string offset.) >> > >> > Has this been explored before? What problems can you foresee (or have >> been >> > foreseen) with such a feature? >> > >> > Thanks >> > >> > > > > -- > Guilherme Blanco > Lead Architect at E-Block > --001a1149a9545d6a4a05343d7288--