Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 

Repository files navigation

Howdy people,

It was brought up to me that I should start a new revision of the discussion.

I'm looking for PHP Wiki Karma: wookieetyler

Should we have a syntax RFC or should I get started on the POC?

In the quest for typed arrays in PHP I beleive it is time to solidify the currently posed syntax:

https://github.com/php/php-src/compare/master...RichardTMiles:php-src:arrayTypes

interface iArrayA ['a' => string ]
interface iArrayB extends iArrayA ['b' => string, 'c' => ?string, ‘d’ =>  SomeClass, ‘e’=>  ?iArrayA, ‘f’ => mixed ]

$array = ( iArrayA &| iArrayB ) [
  'a' => 'Hello'
];

class D {
  public ?iArrayB $exampleA;	// Array<iArrayA>
  public ?iArrayB[] $exampleB;	// Array<iArrayA>[]

  public function definedReturn(): iArrayA {
    return [
      'a' => 'World'
    ]
  }
}

Under the hood this could be a new implementation like SplObjectStorage and SplFixedArray. It may be easier to implement the type cast just set a property in the hash based array, and speed might be worth exploring both implementations as time complexity may exist casting a typed array back to a "normal" hash array. This is worth it's own discussion, so we will focus purely on syntctic capibillity, and/or lack their-of.

https://www.php.net/manual/en/class.splfixedarray.php https://www.php.net/manual/en/class.splobjectstorage.php

If a typed array tries to define an index that does not exist it will throw a RuntimeException: Index invalid, which is consistant with the current implentation of SplFixedArray; If a type is nullable then it is not required to exist during construction.

Standard-type operators should be available.

$a = iArrayA [
  'a' => 'Hello World'
];

$a = ( iArrayA & iArrayB ) [  // throws a RuntimeException since b is required in iArrayB
  'a' => 'Fail'
];

$a = ( iArrayA | iArrayB ) [
  'a' => 'Profit'
];

$a = ( iArrayA &| iArrayB ) [  // throws a RuntimeException since c does not exist in iArrayA and b is required in iArrayB
  'a' => 'fail'
  'c' => ''
];

Why have typed arrays at all? Array access is faster than object access: https://github.com/EFTEC/php-benchmarks/blob/master/benchmark_array_vs_object.php https://medium.com/cook-php/php-benchmark-time-fc19d813aa98

Description Percentage
Array numeric no factory 0%
Array no factory 0.95%
Array numeric factory 566.1%
Array factory 650.07%
Object Constructor 609.03%
Object no constructor 82.77%
Object no constructor setter/getter 2058.43%
Object no constructor magic methods 2273.91%
Object no constructor stdClass 112.53%

Considering a typed array could benifit from knowing the index positions ahead of time, this could mean a faster implemention (other than a hash table) could be appropreate. I see this becomming difficult with a complex type definitions e.g. ( iArrayA &| iArrayB | ( iArrayC & iArrayD ))

How does this differ from generics? Interfaces will be used with generics, but is just another brick in the wall. If anything this would be a building block twords generics. I pose an example:

class A <T extends iArrayA>{
  public T $array = [
		‘a’ => ‘hello’        // this works
	];
}

class A <T extends iArrayB>{
  public T $array = [
		‘a’ => ‘hello’        // this fails with a RuntimeException
	];
}

interface iColorCode { 
  public const string RED = 'red';
  public const array PRINTF_ANSI_COLOR = [
    self::RED => "\033[31m%s\033[0m",
  ];
  public static function colorCode(string $message, string $color = self::RED): iArrayA;
}

class B <T extends iColorCode>{
  public ?iArrayA $arrayA;
  public function __construct(public T $config) {
    $this->arrayA = $config->colorCode('Hello World');
  }
}

Levi Morrison brought up that some work has been done parameterizing traits for anyone whoes intrested: https://github.com/php/php-src/compare/master...morrisonlevi:php-src:parameterized_traits I think this has solid work for that direction. I could see a world where PHP traits, interfaces, and classes could all be made generic. I plan to revisit this work myself after this initiative. Any help is always welcome.

interface iArrayA<T> [ 'a' => T ]

class A <T extends iArrayA<string>>{
  public T $array = [
		‘a’ => ‘hello’        // this works
	];
}

Casper Langemeijer said, "I cannot stand sitting through conference talks on 'generics' that only talk about 'collections'. This could be solved if we had typed arrays. If anything we would get better talks on Generics. :-)"

Thus, I think that the current feedback requires me bring genreics up specifically but I think that it is in fact, a seperate discussion with a seperate scope of work. Even if the type checking is marginally slower than the checks above, then we should still see performance over typed object properties.

I'd like remind everyone that while generics would be cool, it is probably off topic. Issues relating to how this scopes to future work on generics is appropriate. Generally, points should be clear about syntax and how it could present problems or could be made better.

I think im ready to get started on the POC, but would like some feedback specifically from a karma granter as to how I should continue.


I do have a working POC of Apache PHP-CGI Websockets (new function apache_connection_stream), so hopefully I can be granted karma for at least that :) https://github.com/php/php-src/compare/master...RichardTMiles:php-src:apache_connection_stream

Best,

Richard Miles

About

RFC for php internals

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors