On Fri, Mar 15, 2019 at 10:54 AM Nikita Popov <nikita....@gmail.com> wrote:

> On Fri, Mar 15, 2019 at 4:49 AM Kenneth Ellis McCall <xell...@gmail.com>
> wrote:
>
> > Hey all,
> >
> > I'm looking to get feedback on a RFC I want to propose.
> >
> > PHP RFC: Addition of the 'struct' data type.
> >
> > Introduction:
> > PHP has many data types, but does not offer something that is the
> > equivalent to the C struct data type.
> >
> > The purpose of this RFC is to propose a data type of 'struct', which
> > would be a strictly typed, immutable data structure that resembles a mix
> > of a class and an array.
> >
> > Pros:
> > Provides a data type which would immutable and self-validating by
> > mandatory type hinting.
> >
> > Cons:
> > ?
> >
> > Possible future considerations:
> > Advanced Type Validators.
> >
> > Use cases:
> > Configurations, DTOs, anything that needs a strict schema.
> >
> > Proposed usage / syntax:
> > struct MyStuct
> > {
> >      boolean|bool              'prop01';
> >      integer|int               'prop02';
> >      double                    'prop03';
> >      string                    'prop04';
> >      array                     'prop05';
> >      object                    'prop06';
> >      resource                  'prop07';
> >      callable                  'prop08';
> >      iterable                  'prop09';
> >      Acme\MyClass              'prop10';
> >      Acme\ConfStruct           'prop11';
> >      array Acme\AnotherStruct  'prop12';
> >      ?boolean|bool             'prop13';
> >      ?integer|int              'prop14';
> >      ?double                   'prop15';
> >      ?string                   'prop16';
> >      ?array                    'prop17';
> >      ?object                   'prop18';
> >      ?resource                 'prop19';
> >      ?callable                 'prop20';
> >      ?iterable                 'prop21';
> >      ?Acme\MyClass             'prop22';
> >      ?Acme\ConfStruct          'prop23';
> >      ?array Acme\AnotherStruct 'prop24';
> > }
> > OR?
> >
> > struct MyStuct
> > {
> >      'prop01': boolean|bool;
> >      'prop02': integer|int;
> >      'prop03': float;
> >      'prop04': string;
> >      'prop05': array;
> >      'prop06': object;
> >      'prop07': resource;
> >      'prop08': callable;
> >      'prop09': iterable;
> >      'prop10': Acme\MyClass;
> >      'prop11': Acme\ConfStruct;
> >      'prop12': array Acme\AnotherStruct;
> >      'prop13': ?boolean|bool;
> >      'prop14': ?integer|int;
> >      'prop15': ?float;
> >      'prop16': ?string;
> >      'prop17': ?array;
> >      'prop18': ?object;
> >      'prop19': ?resource;
> >      'prop20': ?callable;
> >      'prop21': ?iterable;
> >      'prop22': ?Acme\MyClass;
> >      'prop23': ?Acme\ConfStruct;
> >      'prop24': ?array Acme\AnotherStruct;
> > }
> >
> > struct Acme\ConfStruct
> > {
> >      string 'host';
> >      ?int 'port';
> > }
> >
> > struct Acme\AnotherStruct
> > {
> >      string 'firstName';
> >      string 'lastName';
> >      ?integer 'age';
> > }
> >
> > Acme\ConfStruct $a = {
> >      'host' => '127.0.0.1',
> >      'port' => 8088
> > }
> >
> > Acme\MyStruct $myStruct = {
> >      'prop01' => true,
> >      'prop02' => 1,
> >      'prop03' => 1.01,
> >      'prop04' => 'Hello',
> >      'prop05' => ['a', 'b', 'c'],
> >      'prop06' => new stdClass(),
> >      'prop07' => fopen('xyz.txt', 'wb'),
> >      'prop08' => function() {
> >                  return 1 + 1;
> >                },
> >      'prop09' => [
> >          [1, 2, 3],
> >          [4, 5, 6],
> >          [7, 8, 9]
> >      ],
> >      'prop10' => new Acme\MyClass,
> >      'prop11' => $a,
> >      'prop12' => [
> >          Acme\AnotherStruct [
> >              'firstName' => 'Bob',
> >              'lastName'  => 'Walker'
> >          ],
> >          Acme\AnotherStruct [
> >              'firstName' => 'Little',
> >              'lastName'  => 'Johnny',
> >              'age'       => 5
> >          ],
> >      ],
> >      'prop13' => null,
> >      'prop14' => null,
> >      'prop15' => null,
> >      'prop16' => null,
> >      'prop17' => null,
> >      'prop18' => null,
> >      'prop19' => null,
> >      'prop20' => null,
> >      'prop21' => null,
> >      'prop22' => null,
> >      'prop23' => null,
> >      'prop24' => null
> > };
> >
> > $x = new Some\Other\Class($myStruct);
> >
> > echo $myStruct['prop02'];
> > OR?
> >
> > echo $myStruct->prop02;
> > Warning / Errors / Exceptions:
> > Acme\MyStruct $a = {
> >      'prop01' => 5,
> >      ...
> > }
> > // Should: throw new TypeError("'prop01' should be set as a boolean
> > type, integer type was attempted.")
> >
> > echo $a['xyz']; // or echo $a->xyz (which ever is the preferred syntax
> > after comments).
> > // Should: trigger_error("<b>Notice</b>: Undefined property:
> > Acme\MyStruct::xyz");
> >
> >
> > https://github.com/ellisgl/PHP-RFC-Struct-Data-Type
> >
>
> I think this a worthwhile topic to pursue -- immutable value objects are
> certainly seeing increased use, and it would be great to increase support
> for them. What I mainly wonder in regard to this RFC is: Do we really need
> a new struct type with a new syntax, or can we get this as a combination of
> multiple features for existing class types? In particular, I think your
> struct type proposal can be split into these three parts:
>

I guess needing a new datatype depends if the struct should be passed by
value instead of by reference.


> 1. Property types. As of PHP 7.4 these are already available, yay! Your
> example also make use of some types (e.g. union types) that are not
> currently supported, but likely will be in the future.
>
> 2. Readonly properties: Without requiring an entire object to be immutable,
> we can add support for readonly properties. This may be either a standalone
> feature, or part of / based on a more general property accessors proposal.
>

Read Only types would be a good idea, DOM already uses readonly as a pseudo
keyword to describe their custom property handlers.
A lot of internal classes could benefit from exposing this explicitly.


> 3. Object construction syntax: The last part is a syntax to construct
> objects without a constructor, using a syntax where property names are
> specified, and which ensures that all non-default properties are
> initialized.
>
> Your example
>
> // declaration
> struct AnotherStruct
> {
>     string 'firstName';
>     string 'lastName';
>     ?int 'age';
> }
> // initialization
> AnotherStruct [
>     'firstName' => 'Little',
>     'lastName'  => 'Johnny',
>     'age'       => 5
> ]
>
> could then become something like
>
> // declaration
> class AnotherStruct {
>     readonly string $firstName;
>     readonly string $lastName;
>     readonly ?int $age = null;
> }
> // initialization (syntax up to bikeshedding)
> new AnotherStruct {
>     $firstName => 'Little',
>     $lastName => 'Johnny',
>     $age => 5,
> }
>
> I'd generally prefer a solution that is based on the existing class system.
> Especially as it means that other use-cases can also benefit: Sometimes you
> might only want some of your properties to be readonly, etc.
>
> Nikita
>

Reply via email to